filesystem

package
v0.4.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: MPL-2.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const ChunkSize = 512 * 1024 // 512 KiB

ChunkSize is the granularity for tracking downloaded segments.

View Source
const FilesystemBlockSize = 2 << 17 // 256 KiB. Optimal for Linux cp (uses 128 KiB blocks).
View Source
const ReadAheadBlock = config.GRPCStreamBuffer // 16 MiB

ReadAheadBlock is the amount one on-demand read miss fetches per round trip. The gRPC frame size caps it, so the block lands in a single message. The whole block is cached, so later reads inside it are local. This turns ~32 round trips per 16 MiB into one.

View Source
const StreamPoolSize = 4

StreamPoolSize is the number of parallel gRPC streams per file. Matches typical FUSE readahead parallelism on Linux.

Variables

This section is empty.

Functions

func ApplyOriginMetadata added in v0.4.1

func ApplyOriginMetadata(path string, mode uint32, atimeNs, mtimeNs int64) error

ApplyOriginMetadata sets the origin's permission bits and times on a fully saved file. mtimeNs 0 means no origin data: do nothing. atimeNs 0 falls back to mtime. Chmod/Chtimes act on the backing file directly, not through FUSE, so no notify loop starts. Birth time is not settable on most filesystems and stays view-only.

func BitmapPath

func BitmapPath(filePath string) string

BitmapPath returns the .kdbitmap sidecar path for a given file path.

func GetFreeDiskSpace

func GetFreeDiskSpace(path string) (freeBytesAvail, totalNumberOfBytes, totalNumberFreeBytes uint64, err error)

func OpenShared added in v0.4.0

func OpenShared(path string, flags int, mode uint32) (*os.File, error)

OpenShared opens path with FILE_SHARE_DELETE on Windows so a long-lived writer handle does not block rename or unlink of the file (plain os.OpenFile passes no delete sharing). Unix behaves like os.OpenFile.

func RenameShared added in v0.4.0

func RenameShared(oldpath, newpath string) error

RenameShared renames with the platform strategy platRename implements: POSIX-semantics replace plus copy fallback on Windows, plain rename on unix. Receive-path disk moves need it for the same reason the FUSE Rename does — pinned cache handles.

Types

type ChunkBitmap

type ChunkBitmap struct {
	// contains filtered or unexported fields
}

ChunkBitmap tracks which chunks of a file are downloaded. Thread-safe: Has() uses RLock, Set() uses Lock. hashes stays nil until the first SetHash call (no fingerprints, e.g. fresh load).

func LoadChunkBitmap

func LoadChunkBitmap(path string, expectedFileSize int64) (*ChunkBitmap, error)

LoadChunkBitmap reads a bitmap from a .kdbitmap file. It returns an error when the file is corrupt or the fileSize does not match.

func NewChunkBitmap

func NewChunkBitmap(fileSize int64) *ChunkBitmap

NewChunkBitmap creates a bitmap for a file of the given size using ChunkSize granularity. Returns nil for size <= 0 (empty files need no tracking).

func NewChunkBitmapWithSize

func NewChunkBitmapWithSize(fileSize int64, chunkSize int) *ChunkBitmap

NewChunkBitmapWithSize creates a bitmap with a custom chunk size.

func (*ChunkBitmap) ChunkSizeBytes

func (b *ChunkBitmap) ChunkSizeBytes() int

ChunkSizeBytes returns the chunk size used by this bitmap.

func (*ChunkBitmap) Clear added in v0.3.6

func (b *ChunkBitmap) Clear(chunkIdx int)

Clear clears the bit for chunkIdx and decrements have. Zeroes hashes[chunkIdx] if hashes is allocated. Idempotent for already-clear chunks.

func (*ChunkBitmap) ClearRange added in v0.3.6

func (b *ChunkBitmap) ClearRange(offset int64, size int)

ClearRange clears all chunks covering [offset, offset+size). Mirrors SetRange.

func (*ChunkBitmap) FileSize

func (b *ChunkBitmap) FileSize() int64

FileSize returns the tracked file size.

func (*ChunkBitmap) Has

func (b *ChunkBitmap) Has(chunkIdx int) bool

Has reports whether the chunk at chunkIdx is downloaded.

func (*ChunkBitmap) HasHashes added in v0.3.6

func (b *ChunkBitmap) HasHashes() bool

HasHashes reports whether the bitmap stores per-chunk fingerprints. A fresh or disk-loaded bitmap has none until the first SetHash call.

func (*ChunkBitmap) HasRange

func (b *ChunkBitmap) HasRange(offset int64, size int) bool

HasRange reports whether all chunks covering [offset, offset+size) are downloaded.

func (*ChunkBitmap) Hash added in v0.3.6

func (b *ChunkBitmap) Hash(chunkIdx int) (uint64, bool)

Hash returns the stored fingerprint for a chunk. It returns (0, false) when hashes is nil, the chunk index is out of range, or the chunk is absent. A zero hash value does not mean absent; only the bit and the alloc matter.

func (*ChunkBitmap) Have

func (b *ChunkBitmap) Have() int

Have returns the number of downloaded chunks.

func (*ChunkBitmap) IsComplete

func (b *ChunkBitmap) IsComplete() bool

IsComplete reports whether all chunks are downloaded.

func (*ChunkBitmap) NextMissing

func (b *ChunkBitmap) NextMissing(from int) int

NextMissing returns the index of the first missing chunk at or after from. It returns -1 when no missing chunks remain.

func (*ChunkBitmap) Progress

func (b *ChunkBitmap) Progress() float64

Progress returns download completion as a fraction [0.0, 1.0].

func (*ChunkBitmap) Save

func (b *ChunkBitmap) Save(path string) error

Save writes the bitmap state to a .kdbitmap file.

func (*ChunkBitmap) Set

func (b *ChunkBitmap) Set(chunkIdx int)

Set marks a chunk as downloaded. Idempotent.

func (*ChunkBitmap) SetHash added in v0.3.6

func (b *ChunkBitmap) SetHash(chunkIdx int, h uint64)

SetHash stores a per-chunk content fingerprint. Lazily allocates hashes on first use.

func (*ChunkBitmap) SetRange

func (b *ChunkBitmap) SetRange(offset int64, size int)

SetRange marks all chunks covering [offset, offset+size) as downloaded.

func (*ChunkBitmap) Total

func (b *ChunkBitmap) Total() int

Total returns the total number of chunks.

type Dir

type Dir struct {
	Inode uint64 `json:"inode"` // Inodes must be unique and never reused.
	Name  string `json:"name"`

	RelativePath   string `json:"relativePath"`      // Path relative to the mount root.
	RealPathOfFile string `json:"pathOnLocalSystem"` // Path on the local system.

	PeerLastEdit   uint64 `json:"peerLastEdit"`
	IsLocalPresent bool   `json:"isLocalPresent"`

	LocalDownloadFolder string // Folder that stores files downloaded from the peer.

	Parent *Dir
	Root   *Dir

	OpenFileHandlers map[uint64]*HandleEntry
	OpenMapLock      sync.RWMutex

	Adm       sync.RWMutex
	AllDirMap map[string]*Dir

	AfmLock    sync.RWMutex
	AllFileMap map[string]*File

	// Collab sync options (propagated from FS).
	PrefetchOnOpen bool // If true, Open() fetches the whole file and writes it to local disk.
	PrefetchAutoMB int  // Files at or above this many MB prefetch on open (0=off).
	PushOnWrite    bool // If true, Write() pushes deltas to the peer asynchronously.
	MountReadOnly  bool // Set on the ROOT dir: local mutating FUSE ops return EROFS.
	// PreserveMetadata is set on the ROOT dir: when a remote file's content
	// completes on disk, apply the origin's mode and times to the saved file.
	PreserveMetadata bool

	// ReadAheadWindowBlocks caps predictive sequential read-ahead. Sequential
	// reads fetch up to this many ReadAheadBlock-sized blocks ahead of the read
	// head, so a high-RTT link does not stall at each block boundary. The in-use
	// window self-tunes by hit/miss feedback and never exceeds this cap. A slow
	// consumer (e.g. video) settles well below it. 0 = off (pure on-demand).
	// The value comes from config read_ahead_window_mb.
	ReadAheadWindowBlocks int

	RemoteFilesLock sync.RWMutex
	RemoteFiles     map[string]*File

	// PrefetchSem limits concurrent prefetch goroutines. Without a limit, a large
	// clone (600+ files) opens 600+ parallel StreamFile gRPC streams and
	// overwhelms the connection.
	PrefetchSem chan struct{}
	// contains filtered or unexported fields
}

func (*Dir) Access

func (d *Dir) Access(path string, _mask uint32) (errCode int)

func (*Dir) AddRemoteFile

func (d *Dir) AddRemoteFile(logger *slog.Logger, path string, name string, stat *winfuse.Stat_t) error

func (*Dir) AddRemoteFileWithBase added in v0.4.0

func (d *Dir) AddRemoteFileWithBase(logger *slog.Logger, path string, name string, stat *winfuse.Stat_t, baseMtimeNs int64) error

AddRemoteFileWithBase is AddRemoteFile plus the announcement's declared base (see NotifyRequest.base_mtime_ns). Base 0 means unknown: plain LWW, never a conflict copy.

func (*Dir) Chmod

func (d *Dir) Chmod(path string, mode uint32) (errCode int)

func (*Dir) Chown

func (d *Dir) Chown(path string, uid uint32, gid uint32) (errCode int)

func (*Dir) Create

func (d *Dir) Create(path string, flags int, mode uint32) (errCode int, retFh uint64)

Create creates a new file.

oflag includes exactly one access mode: O_RDONLY, O_WRONLY, or O_RDWR. O_APPEND, O_CREAT, O_TRUNC, and O_EXCL can be OR'd in. Use winfuse.O_ACCMODE to extract the access mode (portable across macOS/Linux/Windows).

Create is dead on all platforms: cgofuse routes creates through CreateEx (see host.go create dispatch). It exists only to satisfy fuse.FileSystemInterface. It delegates to CreateEx so one implementation exists: no duplicated logic to drift, and it stays correct if ever called.

func (*Dir) CreateEx

func (d *Dir) CreateEx(path string, mode uint32, fi *winfuse.FileInfo_t) (errCode int)

CreateEx implements FileSystemOpenEx interface for per-file direct_io control.

func (*Dir) Ctx added in v0.4.0

func (d *Dir) Ctx() context.Context

Ctx returns the live FUSE context from the root. Disconnect swaps it, so do not cache the returned context across sessions.

func (*Dir) Destroy

func (d *Dir) Destroy()

Destroy runs on unmount.

func (*Dir) EditRemoteFile

func (d *Dir) EditRemoteFile(logger *slog.Logger, path string, name string, stat *winfuse.Stat_t) error

func (*Dir) EditRemoteFileWithBase added in v0.4.0

func (d *Dir) EditRemoteFileWithBase(logger *slog.Logger, path string, name string, stat *winfuse.Stat_t, baseMtimeNs int64) error

EditRemoteFileWithBase is EditRemoteFile plus the announcement's declared base (see NotifyRequest.base_mtime_ns). Base 0 means unknown: plain LWW, never a conflict copy.

func (*Dir) Flush

func (d *Dir) Flush(path string, fh uint64) (errCode int)

func (*Dir) Fsync

func (d *Dir) Fsync(path string, datasync bool, fh uint64) (errCode int)

func (*Dir) Fsyncdir

func (d *Dir) Fsyncdir(path string, datasync bool, fh uint64) (errCode int)

func (*Dir) Getattr

func (d *Dir) Getattr(path string, stat *winfuse.Stat_t, fh uint64) (errCode int)

func (*Dir) Getxattr

func (d *Dir) Getxattr(path string, name string) (errCode int, data []byte)

func (*Dir) Init

func (d *Dir) Init()
func (d *Dir) Link(oldpath string, newpath string) (errCode int)

func (*Dir) Listxattr

func (d *Dir) Listxattr(path string, fill func(name string) bool) (errCode int)

func (*Dir) Mkdir

func (d *Dir) Mkdir(path string, mode uint32) (errCode int)

func (*Dir) MkdirFromPeer

func (d *Dir) MkdirFromPeer(path string, mode uint32) (errCode int)

MkdirFromPeer creates a directory without notifying the peer (to avoid loops).

func (*Dir) Mknod

func (d *Dir) Mknod(path string, mode uint32, dev uint64) (errCode int)

func (*Dir) OnLocalChange

func (d *Dir) OnLocalChange(event types.FileEvent)

OnLocalChange reports a local file event to the session. It routes through the root's atomically published callback and does nothing while no session callback is wired.

func (*Dir) Open

func (d *Dir) Open(path string, flags int) (errCode int, retFh uint64)

Open is dead on all platforms: cgofuse routes opens through OpenEx (see host.go's open dispatch). The suite passes with this returning ENOSYS on Linux+macOS. It exists only to satisfy the base fuse.FileSystemInterface; OpenEx is the real open path. It delegates to OpenEx so no duplicated open logic can drift. That duplication hid the handle-counter bug, now fixed once in OpenEx.

func (*Dir) OpenEx

func (d *Dir) OpenEx(path string, fi *winfuse.FileInfo_t) (errCode int)

OpenEx implements FileSystemOpenEx interface for per-file direct_io control.

func (*Dir) OpenStreamProvider

func (d *Dir) OpenStreamProvider() types.FileStreamProvider

OpenStreamProvider returns the current session's stream provider, or nil while no session factory is wired. It routes through the root's atomically published factory.

func (*Dir) Opendir

func (d *Dir) Opendir(path string) (errCode int, retFh uint64)

func (*Dir) PendingAnnounceSuperseded added in v0.4.0

func (d *Dir) PendingAnnounceSuperseded(path string) bool

PendingAnnounceSuperseded reports that path's queued ADD announce describes bytes whose authority was lost to an acceptance: no open edit session and LocalNewer cleared. The CancelPendingNotify fast path usually wins the race; this state check closes it when the flush fires first (CI-speed runners bounced the peer's own bytes back as a newer edit and diverged).

func (*Dir) PreserveMeta added in v0.4.1

func (d *Dir) PreserveMeta() bool

PreserveMeta reports the root's preserve-metadata flag. Download-completion paths check it before applying the origin's mode and times to saved files.

func (*Dir) Read

func (d *Dir) Read(path string, buff []byte, offset int64, fh uint64) (errCode int)

func (*Dir) ReadOnlyMount added in v0.4.1

func (d *Dir) ReadOnlyMount() bool

ReadOnlyMount reports the root's read-only flag. Mutating FUSE ops check it and return EROFS; peer-driven updates (*FromPeer, remote add) bypass it.

func (*Dir) Readdir

func (d *Dir) Readdir(path string, fill func(name string, stat *winfuse.Stat_t, offset int64) bool, offset int64, fh uint64) (errCode int)
func (d *Dir) Readlink(path string) (errCode int, target string)

func (*Dir) Release

func (d *Dir) Release(path string, fh uint64) (errCode int)

func (*Dir) Releasedir

func (d *Dir) Releasedir(path string, fh uint64) (errCode int)

func (*Dir) Removexattr

func (d *Dir) Removexattr(path string, name string) (errCode int)

func (*Dir) Rename

func (d *Dir) Rename(oldpath string, newpath string) (errCode int)

Rename renames a file or directory. macOS apps use atomic rename-swap (renamex_np with RENAME_SWAP), which cgofuse does not expose. Such requests fall back to a basic rename.

func (*Dir) Rmdir

func (d *Dir) Rmdir(path string) (errCode int)

func (*Dir) RmdirFromPeer

func (d *Dir) RmdirFromPeer(path string) (errCode int)

RmdirFromPeer removes a directory without notifying the peer (to avoid loops).

func (*Dir) SetCallbacks added in v0.4.0

func (d *Dir) SetCallbacks(onLocalChange func(event types.FileEvent), provider func() types.FileStreamProvider)

SetCallbacks publishes both session callbacks. Call it on the root.

func (*Dir) SetCtx added in v0.4.0

func (d *Dir) SetCtx(ctx context.Context)

SetCtx publishes a fresh FUSE context. Call it on the root.

func (*Dir) SetOnLocalChange added in v0.4.0

func (d *Dir) SetOnLocalChange(fn func(event types.FileEvent))

SetOnLocalChange publishes the local-change callback. Call it on the root.

func (*Dir) SetStreamProvider added in v0.4.0

func (d *Dir) SetStreamProvider(fn func() types.FileStreamProvider)

SetStreamProvider publishes the stream-provider factory. Call it on the root.

func (*Dir) Setxattr

func (d *Dir) Setxattr(path string, name string, value []byte, flags int) (errCode int)

func (*Dir) Statfs

func (d *Dir) Statfs(path string, stat *winfuse.Statfs_t) (errCode int)

func (*Dir) StreamProviderFn added in v0.4.0

func (d *Dir) StreamProviderFn() func() types.FileStreamProvider

StreamProviderFn returns the published factory itself, for callers that wrap and restore it (tests).

func (*Dir) SwapWouldConflict added in v0.4.0

func (d *Dir) SwapWouldConflict(path string, baseMtimeNs int64) bool

SwapWouldConflict reports whether a swap arriving for path with the given declared base would hit LOCAL authority it provably never saw. The rename handler must then not clobber the disk before the acceptance verdict runs.

func (d *Dir) Symlink(target string, newpath string) (errCode int)

func (*Dir) Truncate

func (d *Dir) Truncate(path string, size int64, fh uint64) (errCode int)

Truncate sets the file size. On Windows, open has no truncate flag, so Open is followed at once by Truncate.

func (d *Dir) Unlink(path string) (errCode int)

Unlink removes a file.

func (*Dir) UnlinkFromPeer

func (d *Dir) UnlinkFromPeer(path string) (errCode int)

UnlinkFromPeer removes a file without notifying the peer (to avoid loops).

func (*Dir) Utimens

func (d *Dir) Utimens(path string, tmsp []winfuse.Timespec) (errCode int)

Utimens sets file access and modification times. We return success but don't persist the changes (timestamps come from underlying storage).

func (*Dir) Write

func (d *Dir) Write(path string, buff []byte, offset int64, fh uint64) (errCode int)

The method returns the number of bytes written.

type DownloadState

type DownloadState struct {
	TotalSize       atomic.Uint64 // Expected total bytes from peer.
	BytesDownloaded atomic.Uint64 // Bytes successfully written to local cache.
	LastReadOffset  atomic.Int64  // Last successfully read offset.
	StartedAt       atomic.Int64  // Unix nano when download started.
	LastSuccessAt   atomic.Int64  // Unix nano of last successful read.
	AttemptCount    atomic.Int32  // Reconnection attempts since last success.
	MaxRetries      int           // Maximum retries before the download stops (default 5).
	// contains filtered or unexported fields
}

DownloadState tracks download progress for resume after reconnect.

func (*DownloadState) CanRetry

func (ds *DownloadState) CanRetry() bool

CanRetry reports whether the download can try another reconnect.

func (*DownloadState) Checksum

func (ds *DownloadState) Checksum() uint64

Checksum returns the current xxHash3 checksum of received data.

func (*DownloadState) IsComplete

func (ds *DownloadState) IsComplete() bool

IsComplete reports whether all bytes are downloaded.

func (*DownloadState) Progress

func (ds *DownloadState) Progress() float64

Progress returns download completion percentage (0-100).

func (*DownloadState) RecordAttempt

func (ds *DownloadState) RecordAttempt() int32

RecordAttempt increments the retry counter.

func (*DownloadState) Reset

func (ds *DownloadState) Reset(totalSize uint64)

Reset clears download state for a new download.

func (*DownloadState) UpdateChecksum

func (ds *DownloadState) UpdateChecksum(data []byte)

UpdateChecksum adds data to the running checksum. Pass bytes in receive order, not offset order.

func (*DownloadState) UpdateProgress

func (ds *DownloadState) UpdateProgress(offset int64, bytesRead int)

UpdateProgress records successful read progress and updates the checksum.

type FS

type FS struct {
	OnLocalChange      func(event types.FileEvent)
	OpenStreamProvider func() types.FileStreamProvider

	// Collab sync options (set from env before Mount).
	PrefetchOnOpen    bool // If true, Open() fetches the whole file and writes it to local disk.
	PrefetchAutoMB    int  // Files at or above this many MB prefetch on open (0=off; PrefetchOnOpen forces any size).
	ReadAheadWindowMB int  // MB cap for predictive sequential read-ahead (0=off). Each Dir converts it to blocks.
	PushOnWrite       bool // If true, Write() pushes deltas to the peer asynchronously.
	AutoCache         bool // If true (live_collab), add macFUSE auto_cache so a peer's same-size in-place edit shows live. Costs mmap-write integrity (git) on macOS; no-op on Linux/Windows.
	MountReadOnly     bool // If true, every mutating FUSE op returns EROFS. Peer updates still apply.
	PreserveMetadata  bool // If true, apply the origin's mode and times to files saved on disk when their content completes.
	// contains filtered or unexported fields
}

func NewFS

func NewFS(logger *slog.Logger) *FS

func (*FS) CancelInFlight added in v0.3.6

func (fs *FS) CancelInFlight()

CancelInFlight cancels in-flight reads/prefetches and resets the FUSE context. It preserves the cached file view (maps + bitmaps). Use it on a disconnect from a peer that may reconnect or resume: the same peer finds its files still there and resumes on-demand with no re-fetch. The full ClearFiles wipe is only for a switch to a different peer (see EnsurePeerScope).

func (*FS) ClearFiles added in v0.3.2

func (fs *FS) ClearFiles()

ClearFiles cancels in-flight operations and clears all file/dir maps. The mount stays alive as an empty folder, so a reconnect after disconnect reuses it (cgofuse allows only one mount per process).

func (*FS) EnsurePeerScope added in v0.3.6

func (fs *FS) EnsurePeerScope(fp string)

EnsurePeerScope binds the cached file view to a peer identity. A different peer than the cached one drops the cache first, so one peer's artifacts never leak to the next. The same peer (reconnect or later session) keeps the cache with no re-fetch. The first peer adopts the empty cache without a clear. Repeat calls are idempotent and cheap. fp is the peer's actual verified fingerprint, so this is correct in TOFU mode too.

func (*FS) IsMounted added in v0.3.2

func (fs *FS) IsMounted() bool

IsMounted reports whether the FUSE host is active.

func (*FS) Mount

func (fs *FS) Mount(mountPoint string, isSecond bool, downloadPath string) error

Mount blocks for the lifetime of the FUSE session. It returns an error at once if the mount point is invalid or host.Mount() fails. On success it returns nil only after a clean unmount.

func (*FS) RefreshCallbacks added in v0.3.2

func (fs *FS) RefreshCallbacks()

RefreshCallbacks updates the Root's callbacks to match the FS-level ones. Call it after setupFilesystem re-wires OnLocalChange/OpenStreamProvider, so the persistent Root uses the new session's gRPC client.

func (*FS) Root

func (fs *FS) Root() *Dir

Root returns the mounted root dir, or nil while unmounted.

func (*FS) SetRoot added in v0.4.0

func (fs *FS) SetRoot(root *Dir)

SetRoot publishes the root dir. Mount sets it in production; tests use it to wire a hand-built tree.

func (*FS) Unmount

func (fs *FS) Unmount()

type File

type File struct {
	Inode           uint64 `json:"inode"` // Inodes must be unique and never reused.
	CurrentHandleID uint64 // Opaque FUSE handle ID for the currently-open fd.
	Name            string `json:"name"`

	RelativePath string `json:"relativePath"` // Path relative to the mount root.

	RealPathOfFile string // Path on the local system.

	Parent *Dir
	Root   *Dir

	LastEditTime uint64 `json:"lastEdit"` // Use time.Now().UnixNano().
	CreatedTime  uint64 `json:"createdAt"`

	PeerLastEdit   uint64 `json:"peerLastEdit"`
	IsLocalPresent bool   `json:"isLocalPresent"`

	NotLocalSynced  bool
	NotRemoteSynced bool

	LocalNewer bool

	HadEdits bool

	// RemoteMtimeNs is the newest peer-announced mtime (UnixNano). Only
	// notifications set it, under RemoteFilesLock. Local ops overwrite
	// stat.Mtim and must not join the staleness comparison.
	RemoteMtimeNs int64

	// Origin metadata captured when an announce's stat is adopted, guarded by
	// metaMu. Getattr mutates f.stat from the local partial file during a
	// download, so these keep the origin's values for preserve_metadata.
	OriginMode    uint32
	OriginAtimeNs int64
	OriginMtimeNs int64

	// EditBaseMtimeNs is max(HeldMtimeNs, LastAnnouncedMtimeNs), snapshotted
	// at the first dirtying op of an edit session under metaMu. The announce
	// carries it so the receiver can prove a concurrent edit: a base below the
	// version the receiver holds means the edit never saw that version.
	EditBaseMtimeNs int64

	// HeldMtimeNs is the newest version stamp whose BYTES are materialized
	// locally: own announces, landed fetches, and the startup scan raise it;
	// a metadata-only accept does not. The session base uses it, so an
	// announce can never claim a version this peer never held. Model v3
	// proves the rule: a blind overwrite then loses the base comparison and
	// the receiver preserves the only copy of the victim bytes.
	HeldMtimeNs int64

	// LastAnnouncedMtimeNs is the mtime of our newest announce for this file,
	// guarded by metaMu. RemoteMtimeNs records only the peer's announcements,
	// so without this an owner-side base degrades to unknown and a conflict on
	// its own file cannot be proved.
	LastAnnouncedMtimeNs int64

	// WasTruncatedToZero records an explicit Truncate(size=0) call. With
	// HadEdits, it separates legitimate empty files from transient states.
	WasTruncatedToZero bool

	// LastNotifiedSize is the file size last sent to the peer in ADD_FILE. It
	// prevents duplicate same-size notifications during a file copy.
	LastNotifiedSize int64

	// PeerStoppedSharing is set when the peer sends REMOVE_FILE during a download.
	// On Release with 0 open handles, the code removes the file reference.
	PeerStoppedSharing bool

	StreamProvider types.FileStreamProvider
	StreamPool     *StreamPool        // Pool of parallel gRPC streams for on-demand reads.
	StreamCancel   context.CancelFunc // Cancel function for the stream context.
	CacheFD        *os.File           // Persistent cache file descriptor for on-demand writes.
	CacheWg        sync.WaitGroup     // Tracks in-flight async cache writes. Release waits for them.

	// Download resumption state.
	Download DownloadState

	// Bitmap tracks which 512 KiB chunks are downloaded from the remote peer.
	// It is nil for local-origin files and empty files (size=0).
	Bitmap *ChunkBitmap

	// PrefetchCancel cancels the background prefetch goroutine for this file.
	PrefetchCancel context.CancelFunc
	// contains filtered or unexported fields
}

func (*File) CountOpenDescriptors

func (f *File) CountOpenDescriptors() uint64

CountOpenDescriptors returns the number of open file handles.

func (*File) NotifyPeer

func (f *File) NotifyPeer()

type HandleEntry

type HandleEntry struct {
	FD   int // Kernel file descriptor for syscalls.
	File *File
}

HandleEntry maps an opaque FUSE handle ID to the kernel fd and File metadata. Handle IDs only increase and never repeat, so a kernel fd number reused after close() causes no race.

type OpenFileCounter

type OpenFileCounter struct {
	// contains filtered or unexported fields
}

OpenFileCounter counts open file handles. Each Create and Open call must have a matching Release call.

func (*OpenFileCounter) CountOpenDescriptors

func (ofc *OpenFileCounter) CountOpenDescriptors() uint64

func (*OpenFileCounter) Open

func (ofc *OpenFileCounter) Open()

func (*OpenFileCounter) OpenIfActive added in v0.3.3

func (ofc *OpenFileCounter) OpenIfActive() bool

OpenIfActive increments the count and returns true only if it was already >0. This prevents reuse of a handle whose last Release runs teardown.

func (*OpenFileCounter) Release

func (ofc *OpenFileCounter) Release() uint64

type StreamPool

type StreamPool struct {
	// contains filtered or unexported fields
}

StreamPool holds N parallel gRPC streams for a single file. FUSE reads pick a stream by chunk-index modulo N. This removes lock contention between concurrent readahead requests.

func NewStreamPool

func NewStreamPool(provider types.FileStreamProvider, ctx context.Context, inode uint64, path string, n int) (*StreamPool, error)

NewStreamPool opens n parallel gRPC streams for the given file. On partial failure, it closes the already-open streams.

func (*StreamPool) Close

func (p *StreamPool) Close() error

Close closes all streams in the pool.

func (*StreamPool) ReadAt

func (p *StreamPool) ReadAt(ctx context.Context, offset int64, size int64) ([]byte, error)

ReadAt routes the request to a stream selected by read-ahead block index. Consecutive 16 MiB blocks land on different streams, so a multi-block read-ahead window pipelines across the pool in parallel. Sharding by chunk index would map every block-aligned fetch (the only kind the on-demand path issues) to stream 0 and serialize the whole window on one stream. Any stream can serve any offset, so this is pure load distribution. Singleflight above this layer already collapses concurrent reads of the same block, so one stream per block adds no contention.

type WriteStats

type WriteStats struct {
	// contains filtered or unexported fields
}

WriteStats tracks timing for Write operations (for profiling)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL