Documentation
¶
Overview ¶
Package segcache is Ether's on-disk cache of decoded Usenet segments. It is a disk budget with segment-granular LRU eviction, pinning and a protection callback, not a library: the stream engine stores segments here so rewatches, seeks and the next episode are instant.
Concurrency model: a single mutex guards the in-memory index (O(1) map lookups plus an intrusive LRU list); segment file IO happens outside it. Per-key striped RW locks order the file-level operations on one key: Get reads under the read lock, while the rename of a Put and the unlink of an eviction/Remove run under the write lock and re-check the index, so an eviction never deletes a newer file put concurrently and a reader never observes a file being replaced underneath it.
A segment larger than the whole budget is rejected by Put with ErrTooLarge. If everything that could be evicted is pinned or protected the cache is allowed to exceed its budget (logged at most once a minute).
Index ¶
- Variables
- type Cache
- func (c *Cache) Close() error
- func (c *Cache) Get(releaseID string, segment int) ([]byte, bool)
- func (c *Cache) Has(releaseID string, segment int) bool
- func (c *Cache) Pin(releaseID string, reason string) error
- func (c *Cache) Pins() map[string][]string
- func (c *Cache) Protect(fn func() map[string]bool)
- func (c *Cache) Put(releaseID string, segment int, data []byte) error
- func (c *Cache) ReleaseBytes(releaseID string) int64
- func (c *Cache) Releases() []ReleaseUsage
- func (c *Cache) Remove(releaseID string) error
- func (c *Cache) SetBudget(budget int64)
- func (c *Cache) Unpin(releaseID string, reason string) error
- func (c *Cache) Usage() (used, budget int64)
- type ReleaseUsage
Constants ¶
This section is empty.
Variables ¶
var ( // ErrTooLarge is returned by Put for a segment bigger than the whole budget. ErrTooLarge = errors.New("segcache: segment larger than cache budget") // ErrClosed is returned by mutating calls after Close. ErrClosed = errors.New("segcache: cache closed") )
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache struct {
// contains filtered or unexported fields
}
Cache implements core.SegmentCache.
func Open ¶
Open opens (creating) a cache rooted at dir with a byte budget (<=0 means unlimited), rebuilding the in-memory index from disk (and cleaning stale temp files from interrupted writes). logger may be nil (slog.Default()).
func (*Cache) Close ¶
Close marks the cache closed. Everything is already durable (pins are written eagerly), so Close only stops further use. It is idempotent.
func (*Cache) Get ¶
Get returns the cached payload (a fresh buffer owned by the caller) and marks it as recently used. A missing, vanished or corrupt file is a miss.
func (*Cache) Pin ¶
Pin protects every segment of a release from eviction while it has at least one pin reason. Pins are persisted to pins.json. If persisting fails the pin still applies in memory and the error is returned.
func (*Cache) Protect ¶
Protect registers a callback returning release IDs that must not be evicted right now. It is only called when an eviction is needed and its result is cached for a few seconds. A nil fn clears it. fn must not call Protect.
func (*Cache) Put ¶
Put stores (or replaces) a segment crash-safely (temp file + rename) and then evicts down to the budget. A payload larger than the whole budget is rejected with ErrTooLarge and nothing is stored. Note that a stored segment may be evicted again immediately if everything else is pinned/protected.
func (*Cache) ReleaseBytes ¶
ReleaseBytes reports how many bytes of a release are currently cached.
func (*Cache) Releases ¶
func (c *Cache) Releases() []ReleaseUsage
Releases lists every release that has cached segments or pins, most recently used first.
func (*Cache) Remove ¶
Remove drops all segments of a release from the index and disk. Pins are kept.
func (*Cache) SetBudget ¶
SetBudget changes the budget (<=0 = unlimited) and evicts immediately if the cache is now over it.