segcache

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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

func Open(dir string, budget int64, logger *slog.Logger) (*Cache, error)

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

func (c *Cache) Close() error

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

func (c *Cache) Get(releaseID string, segment int) ([]byte, bool)

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) Has

func (c *Cache) Has(releaseID string, segment int) bool

Has reports whether the segment is indexed. No disk IO, no recency update.

func (*Cache) Pin

func (c *Cache) Pin(releaseID string, reason string) error

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) Pins

func (c *Cache) Pins() map[string][]string

Pins returns a copy: releaseID -> sorted pin reasons.

func (*Cache) Protect

func (c *Cache) Protect(fn func() map[string]bool)

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

func (c *Cache) Put(releaseID string, segment int, data []byte) error

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

func (c *Cache) ReleaseBytes(releaseID string) int64

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

func (c *Cache) Remove(releaseID string) error

Remove drops all segments of a release from the index and disk. Pins are kept.

func (*Cache) SetBudget

func (c *Cache) SetBudget(budget int64)

SetBudget changes the budget (<=0 = unlimited) and evicts immediately if the cache is now over it.

func (*Cache) Unpin

func (c *Cache) Unpin(releaseID string, reason string) error

Unpin removes one pin reason. When the last reason goes the release becomes evictable again and the cache is evicted down to budget immediately.

func (*Cache) Usage

func (c *Cache) Usage() (used, budget int64)

Usage returns the payload bytes stored and the budget (0 = unlimited).

type ReleaseUsage

type ReleaseUsage struct {
	ReleaseID string
	Bytes     int64
	Segments  int
	LastUsed  time.Time
	Pins      []string
}

ReleaseUsage describes one release in the cache, for the admin UI.

Jump to

Keyboard shortcuts

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