MCPcopy
hub / github.com/benbjohnson/litestream / ReadAt

Method ReadAt

vfs.go:1422–1540  ·  view source on GitHub ↗
(p []byte, off int64)

Source from the content-addressed store, hash-verified

1420}
1421
1422func (f *VFSFile) ReadAt(p []byte, off int64) (n int, err error) {
1423 f.logger.Debug("reading at", "off", off, "len", len(p))
1424 pageSize, err := f.pageSizeBytes()
1425 if err != nil {
1426 return 0, err
1427 }
1428
1429 pgno := uint32(off/int64(pageSize)) + 1
1430 pageOffset := int(off % int64(pageSize))
1431
1432 // Check dirty pages first (takes priority over cache and remote)
1433 f.mu.Lock()
1434 if f.writeEnabled {
1435 if bufferOff, ok := f.dirty[pgno]; ok {
1436 // Read page from buffer file
1437 data := make([]byte, pageSize)
1438 if _, err := f.bufferFile.ReadAt(data, bufferOff); err != nil {
1439 f.mu.Unlock()
1440 return 0, fmt.Errorf("read dirty page from buffer: %w", err)
1441 }
1442 n = copy(p, data[pageOffset:])
1443 f.mu.Unlock()
1444 f.logger.Debug("dirty page hit", "page", pgno, "n", n)
1445
1446 // Update the first page to pretend like we are in journal mode.
1447 if off == 0 && len(p) >= 28 {
1448 p[18], p[19] = 0x01, 0x01
1449 _, _ = rand.Read(p[24:28])
1450 }
1451
1452 return n, nil
1453 }
1454 }
1455 f.mu.Unlock()
1456
1457 // If hydration complete, read from local file
1458 if f.hydrator != nil && f.hydrator.Complete() {
1459 return f.hydrator.ReadAt(p, off)
1460 }
1461
1462 // Check cache (cache is thread-safe)
1463 if data, ok := f.cache.Get(pgno); ok {
1464 n = copy(p, data[pageOffset:])
1465 f.logger.Debug("cache hit", "page", pgno, "n", n)
1466
1467 // Update the first page to pretend like we are in journal mode.
1468 if off == 0 {
1469 p[18], p[19] = 0x01, 0x01
1470 _, _ = rand.Read(p[24:28])
1471 }
1472
1473 return n, nil
1474 }
1475
1476 // Get page index element
1477 f.mu.Lock()
1478 elem, ok := f.index[pgno]
1479 writeEnabled := f.writeEnabled // capture while holding lock to avoid data race

Calls 9

pageSizeBytesMethod · 0.95
FetchPageFunction · 0.85
isRetryablePageErrorFunction · 0.85
CompleteMethod · 0.80
StopMethod · 0.80
LockMethod · 0.45
UnlockMethod · 0.45
ReadMethod · 0.45
ErrorMethod · 0.45