Documentation
¶
Overview ¶
Package file implements a backend.Backend over a local directory tree. Keys map to files under a root; writes are atomic (temp file + rename) so a reader never observes a partially written object — the property the "manifest written last" part commit relies on (DESIGN.md §8, _ref/docs/storage-engine.md §2).
Index ¶
- type File
- func (f *File) CompareAndSwap(ctx context.Context, key string, expected backend.Version, data []byte) (backend.Version, bool, error)
- func (f *File) CreateObject(_ context.Context, key string) (backend.ObjectWriter, error)
- func (f *File) Delete(_ context.Context, key string) error
- func (f *File) FreeInodes(context.Context) (int64, error)
- func (f *File) FreeSpace(context.Context) (int64, error)
- func (*File) IsEphemeral() bool
- func (*File) IsNodeLocal() bool
- func (f *File) List(_ context.Context, prefix string) ([]string, error)
- func (f *File) PutIfAbsent(_ context.Context, key string, data []byte) (written bool, rerr error)
- func (f *File) Read(_ context.Context, key string) ([]byte, error)
- func (f *File) ReadAt(_ context.Context, key string, off, n int64) ([]byte, error)
- func (f *File) ReadVersioned(ctx context.Context, key string) ([]byte, backend.Version, error)
- func (f *File) Size(_ context.Context, key string) (int64, error)
- func (f *File) Write(_ context.Context, key string, data []byte) (rerr error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type File ¶
type File struct {
// contains filtered or unexported fields
}
File is a directory-backed backend.Backend. Keys are slash-delimited and map to paths under root. Safe for concurrent use (the filesystem serializes renames; reads and writes touch distinct temp files).
Every path operation goes through an os.Root opened for that operation alone. That buys two things over joining strings onto a root path. Containment stops being a check this package has to get right — a symlink inside the tree pointing out of it is refused, not merely a "..". And on Windows the file handles it opens carry FILE_SHARE_DELETE, without which a concurrent reader blocks the rename that publishes an object: plain os.Open there asks for FILE_SHARE_READ|FILE_SHARE_WRITE only, and MoveFileEx over a destination someone holds open fails with ERROR_ACCESS_DENIED. Rename-over-an-open-file is a POSIX guarantee the write path depends on; os.Root is what extends it to Windows.
The handle is per-operation rather than held on the File because os.OpenRoot opens its own directory handle through the same syscall.Open that omits FILE_SHARE_DELETE (os/root_windows.go). A root kept for the backend's lifetime would therefore pin its data directory against removal on Windows, and backend.Backend has no Close with which to release it. The cost is one extra open and close per operation.
func (*File) CompareAndSwap ¶ added in v0.40.0
func (f *File) CompareAndSwap( ctx context.Context, key string, expected backend.Version, data []byte, ) (backend.Version, bool, error)
CompareAndSwap stores data under key if the file's current contents still hash to expected, writing through the same atomic temp+fsync+rename as File.Write. Implements backend.Backend.
func (*File) CreateObject ¶ added in v0.37.0
CreateObject builds key's object incrementally in the temp file that File.Write uses for its whole-object write, renaming it over the final path on commit. Nothing is visible under key until then, so the atomicity contract is the same one; the difference is only that the bytes reach the filesystem as they are produced rather than all at once. Implements backend.ObjectCreator.
func (*File) Delete ¶
Delete removes key, or returns an backend.ErrNotExist-wrapping error if absent.
func (*File) FreeInodes ¶ added in v0.40.0
FreeInodes reports how many more files can be created on the filesystem holding the root directory. A filesystem that allocates inodes dynamically (btrfs, and tmpfs on some kernels) reports a zero total; it has no ceiling to report, so that is backend.ErrSpaceUnknown rather than "none left" — the difference between an unbounded backend and a wedged one.
func (*File) FreeSpace ¶ added in v0.37.0
FreeSpace reports the bytes available on the filesystem holding the root directory. It takes the unprivileged figure, so the reserved root allowance is never counted as usable.
func (*File) IsEphemeral ¶
IsEphemeral reports false: data persists on disk.
func (*File) IsNodeLocal ¶ added in v0.39.0
IsNodeLocal reports true: a directory tree is private to its node unless the root happens to be a shared mount, which the backend cannot tell. See backend.NodeLocal for how to read that.
func (*File) List ¶
List returns, sorted ascending, every key with the given prefix.
The prefix bounds the work, not just the result: keys map to paths, so only the subtree under the prefix's directory component is traversed, and within it only the children whose name can still extend into the prefix's final (possibly partial) segment.
func (*File) PutIfAbsent ¶
PutIfAbsent stores data under key only if it does not already exist, returning whether the write happened. It writes a temp file then hard-links it to the final path: the link fails with EEXIST if the destination exists, giving an atomic, exclusive create (the conditional commit primitive). A reader never sees a partial object — the link publishes a fully written file.
func (*File) Read ¶
Read returns the value stored under key, or an backend.ErrNotExist-wrapping error.
func (*File) ReadAt ¶ added in v0.37.0
ReadAt returns the object's [off, off+n) range, clamped to its end, with one pread — the file backend never maps a part column into memory to hand back a slice of it. Implements backend.ReaderAt.
func (*File) ReadVersioned ¶ added in v0.40.0
ReadVersioned returns the value under key and the digest identifying it. Implements backend.Backend.
func (*File) Size ¶ added in v0.12.0
Size returns the byte size of the object stored under key (a stat, no read), or an backend.ErrNotExist-wrapping error if absent. It implements backend.Sizer.