gotools/gopls/internal/filecache/filecache.go

// Start causes the filecache to initialize and start garbage gollection.
//
// Start is automatically called by the first call to Get, but may be called
// explicitly to pre-initialize the cache.
func Start() {}

var memCache

type memKey

// Get retrieves from the cache and returns the value most recently
// supplied to Set(kind, key), possibly by another process.
// Get returns ErrNotFound if the value was not found.
//
// Callers should not modify the returned array.
func Get(kind string, key [32]byte) ([]byte, error) {}

var ErrNotFound

// Set updates the value in the cache.
func Set(kind string, key [32]byte, value []byte) error {}

var active

// writeFileNoTrunc is like os.WriteFile but doesn't truncate until
// after the write, so that racing writes of the same data are idempotent.
func writeFileNoTrunc(filename string, data []byte, perm os.FileMode) error {}

const casKind

const bugKind

var iolimit

var budget

// SetBudget sets a soft limit on disk usage of regular files in the
// cache (in bytes) and returns the previous value. Supplying a
// negative value queries the current value without changing it.
//
// If two gopls processes have different budgets, the one with the
// lower budget will collect garbage more actively, but both will
// observe the effect.
//
// Even in the steady state, the storage usage reported by the 'du'
// command may exceed the budget by as much as a factor of 3 due to
// the overheads of directories and the effects of block quantization,
// which are especially pronounced for the small index files.
func SetBudget(new int64) (old int64) {}

// filename returns the name of the cache file of the specified kind and key.
//
// A typical cache file has a name such as:
//
//	$HOME/Library/Caches / gopls / VVVVVVVV / KK / KKKK...KKKK - kind
//
// The portions separated by spaces are as follows:
// - The user's preferred cache directory; the default value varies by OS.
// - The constant "gopls".
// - The "version", 32 bits of the digest of the gopls executable.
// - The first 8 bits of the key, to avoid huge directories.
// - The full 256 bits of the key.
// - The kind or purpose of this cache file (e.g. "analysis").
//
// The kind establishes a namespace for the keys. It is represented as
// a suffix, not a segment, as this significantly reduces the number
// of directories created, and thus the storage overhead.
//
// Previous iterations of the design aimed for the invariant that once
// a file is written, its contents are never modified, though it may
// be atomically replaced or removed. However, not all platforms have
// an atomic rename operation (our first approach), and file locking
// (our second) is a notoriously fickle mechanism.
//
// The current design instead exploits a trick from the cache
// implementation used by the go command: writes of small files are in
// practice atomic (all or nothing) on all platforms.
// (See GOROOT/src/cmd/go/internal/cache/cache.go.)
//
// Russ Cox notes: "all file systems use an rwlock around every file
// system block, including data blocks, so any writes or reads within
// the same block are going to be handled atomically by the FS
// implementation without any need to request file locking explicitly.
// And since the files are so small, there's only one block. (A block
// is at minimum 512 bytes, usually much more.)" And: "all modern file
// systems protect against [partial writes due to power loss] with
// journals."
//
// We use a two-level scheme consisting of an index and a
// content-addressable store (CAS). A single cache entry consists of
// two files. The value of a cache entry is written into the file at
// filename("cas", sha256(value)). Since the value may be arbitrarily
// large, this write is not atomic. That means we must check the
// integrity of the contents read back from the CAS to make sure they
// hash to the expected key. If the CAS file is incomplete or
// inconsistent, we proceed as if it were missing.
//
// Once the CAS file has been written, we write a small fixed-size
// index file at filename(kind, key), using the values supplied by the
// caller. The index file contains the hash that identifies the value
// file in the CAS. (We could add extra metadata to this file, up to
// 512B, the minimum size of a disk block, if later desired, so long
// as the total size remains fixed.) Because the index file is small,
// concurrent writes to it are atomic in practice, even though this is
// not guaranteed by any OS. The fixed size ensures that readers can't
// see a palimpsest when a short new file overwrites a longer old one.
//
// New versions of gopls are free to reorganize the contents of the
// version directory as needs evolve.  But all versions of gopls must
// in perpetuity treat the "gopls" directory in a common fashion.
//
// In particular, each gopls process attempts to garbage collect
// the entire gopls directory so that newer binaries can clean up
// after older ones: in the development cycle especially, new
// versions may be created frequently.
func filename(kind string, key [32]byte) (string, error) {}

// getCacheDir returns the persistent cache directory of all processes
// running this version of the gopls executable.
//
// It must incorporate the hash of the executable so that we needn't
// worry about incompatible changes to the file format or changes to
// the algorithm that produced the index.
func getCacheDir() (string, error) {}

var cacheDirOnce

var cacheDir

var cacheDirErr

func hashExecutable() (hash [32]byte, err error) {}

// gc runs forever, periodically deleting files from the gopls
// directory until the space budget is no longer exceeded, and also
// deleting files older than the maximum age, regardless of budget.
//
// One gopls process may delete garbage created by a different gopls
// process, possibly running a different version of gopls, possibly
// running concurrently.
func gc(goplsDir string) {}

func init() {}

// BugReports returns a new unordered array of the contents
// of all cached bug reports produced by this executable.
// It also returns the location of the cache directory
// used by this process (or "" on initialization error).
func BugReports() (string, []bug.Bug) {}