Documentation
¶
Overview ¶
Package block_store_writeback keeps every block write in a local store and uploads it to a remote store in the background.
A write is acknowledged once the local store holds the block and a durable marker names it. Upload drains the markers to the remote store and clears each marker only after the remote store holds its block, so writes made while the remote is unreachable upload after it returns, across restarts. Backfill queues the blocks stored before a remote was chosen.
A marker waits a settle age before it uploads, so a block the garbage collector sweeps meanwhile never reaches the remote: the upload finds the block gone and drops its marker.
Index ¶
- type EvictResult
- type Mark
- type MarkFunc
- type MarkingStore
- func (m *MarkingStore) BeginDeferFlush()
- func (m *MarkingStore) BeginReadOperation(ctx context.Context) (block.StoreOps, func(), error)
- func (m *MarkingStore) EndDeferFlush(ctx context.Context) error
- func (m *MarkingStore) GetBlock(ctx context.Context, ref *block.BlockRef) ([]byte, bool, error)
- func (m *MarkingStore) GetBlockExists(ctx context.Context, ref *block.BlockRef) (bool, error)
- func (m *MarkingStore) GetBlockExistsBatch(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
- func (m *MarkingStore) GetHashType() hash.HashType
- func (m *MarkingStore) GetStoreParts() []block.StorePart
- func (m *MarkingStore) GetStoredBlock(ctx context.Context, ref *block.BlockRef) (*block.StoredBlock, error)
- func (m *MarkingStore) GetSupportedFeatures() block.StoreFeature
- func (m *MarkingStore) HoldCompleteRoots(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
- func (m *MarkingStore) MarkRootsComplete(ctx context.Context, roots []*block.BlockRef) error
- func (m *MarkingStore) OpenStage(ctx context.Context) (block.StoreOps, func(), error)
- func (m *MarkingStore) PinRoot(ctx context.Context, ref *block.BlockRef) (func(), error)
- func (m *MarkingStore) PutBlock(ctx context.Context, data []byte, opts *block.PutOpts) (*block.BlockRef, bool, error)
- func (m *MarkingStore) PutBlockBatch(ctx context.Context, entries []*block.PutBatchEntry) ([]bool, error)
- func (m *MarkingStore) ReleaseRoots(ctx context.Context, refs []*block.BlockRef) error
- func (m *MarkingStore) RmBlock(ctx context.Context, ref *block.BlockRef) error
- func (m *MarkingStore) RootsComplete(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
- func (m *MarkingStore) SetRetainedRoots(ctx context.Context, entries []*block.PutBatchEntry, roots []block.NamedRoot) error
- func (m *MarkingStore) StatBlock(ctx context.Context, ref *block.BlockRef) (*block.BlockStat, error)
- func (m *MarkingStore) SupportsRootRetention() bool
- func (m *MarkingStore) Sync(ctx context.Context) (bool, error)
- type Policy
- type Status
- type Store
- func (s *Store) Backfill(ctx context.Context, target string, ...) error
- func (s *Store) Evict(ctx context.Context, remote block.StoreOps, maxBytes int64, ...) (EvictResult, error)
- func (s *Store) GetStatus() (Status, <-chan struct{})
- func (s *Store) GetStoreParts() []block.StorePart
- func (s *Store) Refill(ctx context.Context, ref *block.BlockRef, stored *block.StoredBlock) error
- func (s *Store) SetEnabled(ctx context.Context, enabled bool) error
- func (s *Store) SetError(err error)
- func (s *Store) SetPolicy(policy Policy)
- func (s *Store) Upload(ctx context.Context, remote block.StoreOps) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type EvictResult ¶
type EvictResult struct {
// Evicted is the number of local values dropped.
Evicted int
// EvictedBytes is the recorded size of the dropped values.
EvictedBytes int64
// Requeued is the number of entries the caller kept, queued at the new
// epoch.
Requeued int
// Refused is the number of blocks kept because the remote store may not
// hold them: a marker awaits upload, or the remote does not report them.
Refused int
}
EvictResult reports what an eviction pass did.
type Mark ¶
type Mark struct {
// Hash is the block hash.
Hash *hash.Hash
// Size is the block size in bytes.
Size int64
// At is when the block was written. The zero time uploads it without
// waiting to settle, as a backfill does.
At time.Time
}
Mark names a written block.
type MarkFunc ¶
MarkFunc durably records written blocks before their writes are acknowledged. A batch write passes all of its blocks in one call.
type MarkingStore ¶
type MarkingStore struct {
// contains filtered or unexported fields
}
MarkingStore acknowledges writes only after mark retains each written block.
A write that fails to mark returns the error with the block stored; repeating the write repairs the marker.
func NewMarkingStore ¶
func NewMarkingStore(store block.StoreOps, mark MarkFunc) *MarkingStore
NewMarkingStore wraps store, calling mark after each successful write.
func (*MarkingStore) BeginDeferFlush ¶
func (m *MarkingStore) BeginDeferFlush()
BeginDeferFlush forwards the GC ref-batch scope to the inner store.
func (*MarkingStore) BeginReadOperation ¶
BeginReadOperation opens a read scope on the inner store.
func (*MarkingStore) EndDeferFlush ¶
func (m *MarkingStore) EndDeferFlush(ctx context.Context) error
EndDeferFlush forwards the GC ref-batch scope to the inner store.
func (*MarkingStore) GetBlockExists ¶
GetBlockExists checks if a block exists.
func (*MarkingStore) GetBlockExistsBatch ¶
func (m *MarkingStore) GetBlockExistsBatch(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
GetBlockExistsBatch forwards batched existence probes to the inner store.
func (*MarkingStore) GetHashType ¶
func (m *MarkingStore) GetHashType() hash.HashType
GetHashType returns the inner store hash type.
func (*MarkingStore) GetStoreParts ¶
func (m *MarkingStore) GetStoreParts() []block.StorePart
GetStoreParts returns the wrapped store.
func (*MarkingStore) GetStoredBlock ¶
func (m *MarkingStore) GetStoredBlock(ctx context.Context, ref *block.BlockRef) (*block.StoredBlock, error)
GetStoredBlock forwards to the inner store.
func (*MarkingStore) GetSupportedFeatures ¶
func (m *MarkingStore) GetSupportedFeatures() block.StoreFeature
GetSupportedFeatures returns the inner store native feature bitset.
func (*MarkingStore) HoldCompleteRoots ¶
func (m *MarkingStore) HoldCompleteRoots(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
HoldCompleteRoots holds completion proofs under the inner stage. A hold writes no block, so there is nothing to mark.
func (*MarkingStore) MarkRootsComplete ¶
MarkRootsComplete forwards the durable World proof.
func (*MarkingStore) OpenStage ¶
OpenStage wraps a stage opened on the inner store, so staged writes are marked for upload like any other write.
func (*MarkingStore) PutBlock ¶
func (m *MarkingStore) PutBlock(ctx context.Context, data []byte, opts *block.PutOpts) (*block.BlockRef, bool, error)
PutBlock stores a block and marks it, even when it already existed.
func (*MarkingStore) PutBlockBatch ¶
func (m *MarkingStore) PutBlockBatch(ctx context.Context, entries []*block.PutBatchEntry) ([]bool, error)
PutBlockBatch marks every successful non-tombstone write in one call. A failed marker returns an error; repeating the batch repairs the markers.
func (*MarkingStore) ReleaseRoots ¶
ReleaseRoots forwards staging release to the underlying store.
func (*MarkingStore) RootsComplete ¶
RootsComplete checks the inner store's World proofs.
func (*MarkingStore) SetRetainedRoots ¶
func (m *MarkingStore) SetRetainedRoots(ctx context.Context, entries []*block.PutBatchEntry, roots []block.NamedRoot) error
SetRetainedRoots forwards durable root ownership to the inner store and marks the blocks it wrote.
func (*MarkingStore) StatBlock ¶
func (m *MarkingStore) StatBlock(ctx context.Context, ref *block.BlockRef) (*block.BlockStat, error)
StatBlock returns block metadata.
func (*MarkingStore) SupportsRootRetention ¶
func (m *MarkingStore) SupportsRootRetention() bool
SupportsRootRetention reports the inner store's root ownership capability. Retiring a local root lets the collector sweep superseded blocks; a marker whose block was swept is dropped without upload.
type Policy ¶
type Policy struct {
// Settle is how long a block stays queued before it uploads.
Settle time.Duration
// MaxPendingBytes uploads the oldest blocks before they settle while the
// queued bytes exceed it. Zero sets no limit.
MaxPendingBytes int64
// ResidentHigh is the resident byte budget: past it, eviction drops the
// uploaded blocks read least recently. Zero evicts nothing.
ResidentHigh int64
// ResidentLow is where eviction stops, at most ResidentHigh. Eviction can
// drop only uploaded blocks, so queued bytes past it upload before they
// settle.
ResidentLow int64
}
Policy sets when queued blocks upload and how many bytes the local store keeps.
type Status ¶
type Status struct {
// Enabled reports whether writes are queued for upload.
Enabled bool
// Pending is the number of blocks awaiting upload.
Pending int
// PendingBytes is the size of the blocks awaiting upload.
PendingBytes int64
// Oldest is the write time of the first block awaiting upload, while
// Pending is not zero. Every block written before it has uploaded.
Oldest time.Time
// Err is the last upload failure, cleared by the next successful batch.
Err error
// Target is the remote every block stored before it was chosen is queued
// for, empty until a backfill completes.
Target string
// Policy sets when queued blocks upload and the resident budget.
Policy Policy
// EvictableBytes is the size of the uploaded blocks the eviction queue
// holds. It can overcount blocks the garbage collector swept until an
// eviction pass meets their entries.
EvictableBytes int64
// EvictedBytes is the size of the values eviction dropped since the store
// opened.
EvictedBytes int64
// Refills is the number of evicted blocks read back from the remote since
// the store opened. Each one was a read that waited on the remote.
Refills int64
}
Status is the upload state of a Store.
func (Status) EvictBytes ¶
EvictBytes returns how many uploaded bytes a pass drops to bring the resident bytes from past the high mark down to the low mark, or zero.
func (Status) ResidentBytes ¶
ResidentBytes is the size of the store's blocks the local store holds: the blocks awaiting upload and the uploaded blocks not yet evicted.
type Store ¶
type Store struct {
*MarkingStore
// contains filtered or unexported fields
}
Store is a local block store whose writes queue for upload.
func NewStore ¶
func NewStore( ctx context.Context, local, values block.StoreOps, markers kvtx.Store, enabled bool, ) (*Store, error)
NewStore builds a Store over local, counting the markers left by a previous run. Queued blocks upload at once until SetPolicy sets a settle age. values holds the same blocks as local without its ownership tracking.
When enabled is false, writes are not queued until SetEnabled enables them.
func (*Store) Backfill ¶
func (s *Store) Backfill( ctx context.Context, target string, list func(ctx context.Context) ([]*block.BlockRef, error), ) error
Backfill queues every block list names for upload to target, unless a backfill for target already completed. Call it after enabling uploads for target, so the backfill and new writes together cover every block.
A block the local store does not hold is skipped. The completed target is recorded durably, so an interrupted backfill runs again on the next call.
func (*Store) Evict ¶
func (s *Store) Evict( ctx context.Context, remote block.StoreOps, maxBytes int64, keep func(*hash.Hash) bool, ) (EvictResult, error)
Evict runs one eviction pass, one at a time: it advances the epoch, then walks the queue oldest epoch first and drops local values until it has dropped maxBytes or reaches the new epoch. A block keep reports is queued at the new epoch instead. A nil keep keeps nothing.
A block leaves the local values only while no marker awaits its upload and remote reports holding it, so the remote store always holds what was dropped. An entry whose value is already gone, such as a block the garbage collector swept, is deleted. Values are dropped before their entries, so an interrupted pass leaves only entries the next pass deletes. The pass takes no lock a write waits on, since asking remote can wait on the network.
The volume shares values by hash across its block stores. Eviction relies on each placed store sealing its blocks with its own transform keys, so no other store holds the same hash.
func (*Store) GetStoreParts ¶
GetStoreParts returns the local store that holds every block.
func (*Store) Refill ¶
Refill writes a block read back from the remote store into the local values and queues it for eviction at the current epoch. It changes no ownership, so call it only for a block the reference graph still tracks.
func (*Store) SetEnabled ¶
SetEnabled starts or stops queueing writes for upload.
Disabling drops the queued markers, the eviction queue and the backfill target: the remote store no longer needs the markers, and the local store must keep the blocks it holds.
func (*Store) SetError ¶
SetError records an upload failure in the status, such as a remote store that cannot be opened. The next successful batch clears it.
func (*Store) SetPolicy ¶
SetPolicy sets when queued blocks upload and the resident budget, waking Upload and budget watchers to apply it.
func (*Store) Upload ¶
Upload drains the markers to remote, oldest first, until ctx is canceled. A marker uploads once it is older than the policy's settle age, or earlier while the queue exceeds its byte limit.
Returns the first upload failure, which stays in the status until the next successful batch. The caller retries with its own backoff.