summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-store/storage
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-store/storage')
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/block.go895
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/compressor.go104
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/disk.go400
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/errors.go90
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/fs.go65
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/lock.go76
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/memory.go188
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/storage.go54
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/transform.go25
9 files changed, 0 insertions, 1897 deletions
diff --git a/vendor/codeberg.org/gruf/go-store/storage/block.go b/vendor/codeberg.org/gruf/go-store/storage/block.go
deleted file mode 100644
index c0bb6b383..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/block.go
+++ /dev/null
@@ -1,895 +0,0 @@
-package storage
-
-import (
- "bytes"
- "crypto/sha256"
- "fmt"
- "io"
- "io/fs"
- "os"
- "strings"
- "sync"
- "syscall"
-
- "codeberg.org/gruf/go-byteutil"
- "codeberg.org/gruf/go-errors/v2"
- "codeberg.org/gruf/go-fastcopy"
- "codeberg.org/gruf/go-hashenc"
- "codeberg.org/gruf/go-pools"
- "codeberg.org/gruf/go-store/util"
-)
-
-var (
- nodePathPrefix = "node/"
- blockPathPrefix = "block/"
-)
-
-// DefaultBlockConfig is the default BlockStorage configuration
-var DefaultBlockConfig = &BlockConfig{
- BlockSize: 1024 * 16,
- WriteBufSize: 4096,
- Overwrite: false,
- Compression: NoCompression(),
-}
-
-// BlockConfig defines options to be used when opening a BlockStorage
-type BlockConfig struct {
- // BlockSize is the chunking size to use when splitting and storing blocks of data
- BlockSize int
-
- // ReadBufSize is the buffer size to use when reading node files
- ReadBufSize int
-
- // WriteBufSize is the buffer size to use when writing file streams (PutStream)
- WriteBufSize int
-
- // Overwrite allows overwriting values of stored keys in the storage
- Overwrite bool
-
- // Compression is the Compressor to use when reading / writing files, default is no compression
- Compression Compressor
-}
-
-// getBlockConfig returns a valid BlockConfig for supplied ptr
-func getBlockConfig(cfg *BlockConfig) BlockConfig {
- // If nil, use default
- if cfg == nil {
- cfg = DefaultBlockConfig
- }
-
- // Assume nil compress == none
- if cfg.Compression == nil {
- cfg.Compression = NoCompression()
- }
-
- // Assume 0 chunk size == use default
- if cfg.BlockSize < 1 {
- cfg.BlockSize = DefaultBlockConfig.BlockSize
- }
-
- // Assume 0 buf size == use default
- if cfg.WriteBufSize < 1 {
- cfg.WriteBufSize = DefaultDiskConfig.WriteBufSize
- }
-
- // Return owned config copy
- return BlockConfig{
- BlockSize: cfg.BlockSize,
- WriteBufSize: cfg.WriteBufSize,
- Overwrite: cfg.Overwrite,
- Compression: cfg.Compression,
- }
-}
-
-// BlockStorage is a Storage implementation that stores input data as chunks on
-// a filesystem. Each value is chunked into blocks of configured size and these
-// blocks are stored with name equal to their base64-encoded SHA256 hash-sum. A
-// "node" file is finally created containing an array of hashes contained within
-// this value
-type BlockStorage struct {
- path string // path is the root path of this store
- blockPath string // blockPath is the joined root path + block path prefix
- nodePath string // nodePath is the joined root path + node path prefix
- config BlockConfig // cfg is the supplied configuration for this store
- hashPool sync.Pool // hashPool is this store's hashEncoder pool
- bufpool pools.BufferPool // bufpool is this store's bytes.Buffer pool
- cppool fastcopy.CopyPool // cppool is the prepared io copier with buffer pool
- lock *Lock // lock is the opened lockfile for this storage instance
-
- // NOTE:
- // BlockStorage does not need to lock each of the underlying block files
- // as the filename itself directly relates to the contents. If there happens
- // to be an overwrite, it will just be of the same data since the filename is
- // the hash of the data.
-}
-
-// OpenBlock opens a BlockStorage instance for given folder path and configuration
-func OpenBlock(path string, cfg *BlockConfig) (*BlockStorage, error) {
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- // Clean provided path, ensure ends in '/' (should
- // be dir, this helps with file path trimming later)
- path = pb.Clean(path) + "/"
-
- // Get checked config
- config := getBlockConfig(cfg)
-
- // Attempt to open path
- file, err := os.OpenFile(path, defaultFileROFlags, defaultDirPerms)
- if err != nil {
- // If not a not-exist error, return
- if !os.IsNotExist(err) {
- return nil, err
- }
-
- // Attempt to make store path dirs
- err = os.MkdirAll(path, defaultDirPerms)
- if err != nil {
- return nil, err
- }
-
- // Reopen dir now it's been created
- file, err = os.OpenFile(path, defaultFileROFlags, defaultDirPerms)
- if err != nil {
- return nil, err
- }
- }
- defer file.Close()
-
- // Double check this is a dir (NOT a file!)
- stat, err := file.Stat()
- if err != nil {
- return nil, err
- } else if !stat.IsDir() {
- return nil, errPathIsFile
- }
-
- // Open and acquire storage lock for path
- lock, err := OpenLock(pb.Join(path, LockFile))
- if err != nil {
- return nil, err
- }
-
- // Figure out the largest size for bufpool slices
- bufSz := encodedHashLen
- if bufSz < config.BlockSize {
- bufSz = config.BlockSize
- }
- if bufSz < config.WriteBufSize {
- bufSz = config.WriteBufSize
- }
-
- // Prepare BlockStorage
- st := &BlockStorage{
- path: path,
- blockPath: pb.Join(path, blockPathPrefix),
- nodePath: pb.Join(path, nodePathPrefix),
- config: config,
- hashPool: sync.Pool{
- New: func() interface{} {
- return newHashEncoder()
- },
- },
- bufpool: pools.NewBufferPool(bufSz),
- lock: lock,
- }
-
- // Set copypool buffer size
- st.cppool.Buffer(config.ReadBufSize)
-
- return st, nil
-}
-
-// Clean implements storage.Clean()
-func (st *BlockStorage) Clean() error {
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- nodes := map[string]*node{}
- onceErr := errors.OnceError{}
-
- // Walk nodes dir for entries
- err := util.WalkDir(pb, st.nodePath, func(npath string, fsentry fs.DirEntry) {
- // Only deal with regular files
- if !fsentry.Type().IsRegular() {
- return
- }
-
- // Stop if we hit error previously
- if onceErr.IsSet() {
- return
- }
-
- // Get joined node path name
- npath = pb.Join(npath, fsentry.Name())
-
- // Attempt to open RO file
- file, err := open(npath, defaultFileROFlags)
- if err != nil {
- onceErr.Store(err)
- return
- }
- defer file.Close()
-
- // Alloc new Node + acquire hash buffer for writes
- hbuf := st.bufpool.Get()
- defer st.bufpool.Put(hbuf)
- hbuf.Guarantee(encodedHashLen)
- node := node{}
-
- // Write file contents to node
- _, err = io.CopyBuffer(
- &nodeWriter{
- node: &node,
- buf: hbuf,
- },
- file,
- nil,
- )
- if err != nil {
- onceErr.Store(err)
- return
- }
-
- // Append to nodes slice
- nodes[fsentry.Name()] = &node
- })
-
- // Handle errors (though nodePath may not have been created yet)
- if err != nil && !os.IsNotExist(err) {
- return err
- } else if onceErr.IsSet() {
- return onceErr.Load()
- }
-
- // Walk blocks dir for entries
- onceErr.Reset()
- err = util.WalkDir(pb, st.blockPath, func(bpath string, fsentry fs.DirEntry) {
- // Only deal with regular files
- if !fsentry.Type().IsRegular() {
- return
- }
-
- // Stop if we hit error previously
- if onceErr.IsSet() {
- return
- }
-
- inUse := false
- for key, node := range nodes {
- if node.removeHash(fsentry.Name()) {
- if len(node.hashes) < 1 {
- // This node contained hash, and after removal is now empty.
- // Remove this node from our tracked nodes slice
- delete(nodes, key)
- }
- inUse = true
- }
- }
-
- // Block hash is used by node
- if inUse {
- return
- }
-
- // Get joined block path name
- bpath = pb.Join(bpath, fsentry.Name())
-
- // Remove this unused block path
- err := os.Remove(bpath)
- if err != nil {
- onceErr.Store(err)
- return
- }
- })
-
- // Handle errors (though blockPath may not have been created yet)
- if err != nil && !os.IsNotExist(err) {
- return err
- } else if onceErr.IsSet() {
- return onceErr.Load()
- }
-
- // If there are nodes left at this point, they are corrupt
- // (i.e. they're referencing block hashes that don't exist)
- if len(nodes) > 0 {
- nodeKeys := []string{}
- for key := range nodes {
- nodeKeys = append(nodeKeys, key)
- }
- return fmt.Errorf("store/storage: corrupted nodes: %v", nodeKeys)
- }
-
- return nil
-}
-
-// ReadBytes implements Storage.ReadBytes()
-func (st *BlockStorage) ReadBytes(key string) ([]byte, error) {
- // Get stream reader for key
- rc, err := st.ReadStream(key)
- if err != nil {
- return nil, err
- }
- defer rc.Close()
-
- // Read all bytes and return
- return io.ReadAll(rc)
-}
-
-// ReadStream implements Storage.ReadStream()
-func (st *BlockStorage) ReadStream(key string) (io.ReadCloser, error) {
- // Get node file path for key
- npath, err := st.nodePathForKey(key)
- if err != nil {
- return nil, err
- }
-
- // Track open
- st.lock.Add()
-
- // Check if open
- if st.lock.Closed() {
- st.lock.Done()
- return nil, ErrClosed
- }
-
- // Attempt to open RO file
- file, err := open(npath, defaultFileROFlags)
- if err != nil {
- st.lock.Done()
- return nil, errSwapNotFound(err)
- }
- defer file.Close()
-
- // Acquire hash buffer for writes
- hbuf := st.bufpool.Get()
- defer st.bufpool.Put(hbuf)
-
- // Write file contents to node
- node := node{}
- _, err = st.cppool.Copy(
- &nodeWriter{
- node: &node,
- buf: hbuf,
- },
- file,
- )
- if err != nil {
- st.lock.Done()
- return nil, err
- }
-
- // Prepare block reader and return
- rc := util.NopReadCloser(&blockReader{
- storage: st,
- node: &node,
- }) // we wrap the blockreader to decr lockfile waitgroup
- return util.ReadCloserWithCallback(rc, st.lock.Done), nil
-}
-
-func (st *BlockStorage) readBlock(key string) ([]byte, error) {
- // Get block file path for key
- bpath := st.blockPathForKey(key)
-
- // Attempt to open RO file
- file, err := open(bpath, defaultFileROFlags)
- if err != nil {
- return nil, wrap(errCorruptNode, err)
- }
- defer file.Close()
-
- // Wrap the file in a compressor
- cFile, err := st.config.Compression.Reader(file)
- if err != nil {
- return nil, wrap(errCorruptNode, err)
- }
- defer cFile.Close()
-
- // Read the entire file
- return io.ReadAll(cFile)
-}
-
-// WriteBytes implements Storage.WriteBytes()
-func (st *BlockStorage) WriteBytes(key string, value []byte) error {
- return st.WriteStream(key, bytes.NewReader(value))
-}
-
-// WriteStream implements Storage.WriteStream()
-func (st *BlockStorage) WriteStream(key string, r io.Reader) error {
- // Get node file path for key
- npath, err := st.nodePathForKey(key)
- if err != nil {
- return err
- }
-
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Check if this exists
- ok, err := stat(key)
- if err != nil {
- return err
- }
-
- // Check if we allow overwrites
- if ok && !st.config.Overwrite {
- return ErrAlreadyExists
- }
-
- // Ensure nodes dir (and any leading up to) exists
- err = os.MkdirAll(st.nodePath, defaultDirPerms)
- if err != nil {
- return err
- }
-
- // Ensure blocks dir (and any leading up to) exists
- err = os.MkdirAll(st.blockPath, defaultDirPerms)
- if err != nil {
- return err
- }
-
- // Alloc new node
- node := node{}
-
- // Acquire HashEncoder
- hc := st.hashPool.Get().(*hashEncoder)
- defer st.hashPool.Put(hc)
-
- // Create new waitgroup and OnceError for
- // goroutine error tracking and propagating
- wg := sync.WaitGroup{}
- onceErr := errors.OnceError{}
-
-loop:
- for !onceErr.IsSet() {
- // Fetch new buffer for this loop
- buf := st.bufpool.Get()
- buf.Grow(st.config.BlockSize)
-
- // Read next chunk
- n, err := io.ReadFull(r, buf.B)
- switch err {
- case nil, io.ErrUnexpectedEOF:
- // do nothing
- case io.EOF:
- st.bufpool.Put(buf)
- break loop
- default:
- st.bufpool.Put(buf)
- return err
- }
-
- // Hash the encoded data
- sum := hc.EncodeSum(buf.B)
-
- // Append to the node's hashes
- node.hashes = append(node.hashes, sum)
-
- // If already on disk, skip
- has, err := st.statBlock(sum)
- if err != nil {
- st.bufpool.Put(buf)
- return err
- } else if has {
- st.bufpool.Put(buf)
- continue loop
- }
-
- // Check if reached EOF
- atEOF := (n < buf.Len())
-
- wg.Add(1)
- go func() {
- // Perform writes in goroutine
-
- defer func() {
- // Defer release +
- // signal we're done
- st.bufpool.Put(buf)
- wg.Done()
- }()
-
- // Write block to store at hash
- err = st.writeBlock(sum, buf.B[:n])
- if err != nil {
- onceErr.Store(err)
- return
- }
- }()
-
- // Break at end
- if atEOF {
- break loop
- }
- }
-
- // Wait, check errors
- wg.Wait()
- if onceErr.IsSet() {
- return onceErr.Load()
- }
-
- // If no hashes created, return
- if len(node.hashes) < 1 {
- return errNoHashesWritten
- }
-
- // Prepare to swap error if need-be
- errSwap := errSwapNoop
-
- // Build file RW flags
- // NOTE: we performed an initial check for
- // this before writing blocks, but if
- // the utilizer of this storage didn't
- // correctly mutex protect this key then
- // someone may have beaten us to the
- // punch at writing the node file.
- flags := defaultFileRWFlags
- if !st.config.Overwrite {
- flags |= syscall.O_EXCL
-
- // Catch + replace err exist
- errSwap = errSwapExist
- }
-
- // Attempt to open RW file
- file, err := open(npath, flags)
- if err != nil {
- return errSwap(err)
- }
- defer file.Close()
-
- // Acquire write buffer
- buf := st.bufpool.Get()
- defer st.bufpool.Put(buf)
- buf.Grow(st.config.WriteBufSize)
-
- // Finally, write data to file
- _, err = io.CopyBuffer(file, &nodeReader{node: &node}, nil)
- return err
-}
-
-// writeBlock writes the block with hash and supplied value to the filesystem
-func (st *BlockStorage) writeBlock(hash string, value []byte) error {
- // Get block file path for key
- bpath := st.blockPathForKey(hash)
-
- // Attempt to open RW file
- file, err := open(bpath, defaultFileRWFlags)
- if err != nil {
- if err == syscall.EEXIST {
- err = nil /* race issue describe in struct NOTE */
- }
- return err
- }
- defer file.Close()
-
- // Wrap the file in a compressor
- cFile, err := st.config.Compression.Writer(file)
- if err != nil {
- return err
- }
- defer cFile.Close()
-
- // Write value to file
- _, err = cFile.Write(value)
- return err
-}
-
-// statBlock checks for existence of supplied block hash
-func (st *BlockStorage) statBlock(hash string) (bool, error) {
- return stat(st.blockPathForKey(hash))
-}
-
-// Stat implements Storage.Stat()
-func (st *BlockStorage) Stat(key string) (bool, error) {
- // Get node file path for key
- kpath, err := st.nodePathForKey(key)
- if err != nil {
- return false, err
- }
-
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return false, ErrClosed
- }
-
- // Check for file on disk
- return stat(kpath)
-}
-
-// Remove implements Storage.Remove()
-func (st *BlockStorage) Remove(key string) error {
- // Get node file path for key
- kpath, err := st.nodePathForKey(key)
- if err != nil {
- return err
- }
-
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Remove at path (we know this is file)
- if err := unlink(kpath); err != nil {
- return errSwapNotFound(err)
- }
-
- return nil
-}
-
-// Close implements Storage.Close()
-func (st *BlockStorage) Close() error {
- return st.lock.Close()
-}
-
-// WalkKeys implements Storage.WalkKeys()
-func (st *BlockStorage) WalkKeys(opts WalkKeysOptions) error {
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- // Walk dir for entries
- return util.WalkDir(pb, st.nodePath, func(npath string, fsentry fs.DirEntry) {
- // Only deal with regular files
- if fsentry.Type().IsRegular() {
- opts.WalkFn(entry(fsentry.Name()))
- }
- })
-}
-
-// nodePathForKey calculates the node file path for supplied key
-func (st *BlockStorage) nodePathForKey(key string) (string, error) {
- // Path separators are illegal, as directory paths
- if strings.Contains(key, "/") || key == "." || key == ".." {
- return "", ErrInvalidKey
- }
-
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- // Append the nodepath to key
- pb.AppendString(st.nodePath)
- pb.AppendString(key)
-
- // Return joined + cleaned node-path
- return pb.Join(st.nodePath, key), nil
-}
-
-// blockPathForKey calculates the block file path for supplied hash
-func (st *BlockStorage) blockPathForKey(hash string) string {
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
- return pb.Join(st.blockPath, hash)
-}
-
-// hashSeparator is the separating byte between block hashes
-const hashSeparator = byte('\n')
-
-// node represents the contents of a node file in storage
-type node struct {
- hashes []string
-}
-
-// removeHash attempts to remove supplied block hash from the node's hash array
-func (n *node) removeHash(hash string) bool {
- haveDropped := false
- for i := 0; i < len(n.hashes); {
- if n.hashes[i] == hash {
- // Drop this hash from slice
- n.hashes = append(n.hashes[:i], n.hashes[i+1:]...)
- haveDropped = true
- } else {
- // Continue iter
- i++
- }
- }
- return haveDropped
-}
-
-// nodeReader is an io.Reader implementation for the node file representation,
-// which is useful when calculated node file is being written to the store
-type nodeReader struct {
- node *node
- idx int
- last int
-}
-
-func (r *nodeReader) Read(b []byte) (int, error) {
- n := 0
-
- // '-1' means we missed writing
- // hash separator on last iteration
- if r.last == -1 {
- b[n] = hashSeparator
- n++
- r.last = 0
- }
-
- for r.idx < len(r.node.hashes) {
- hash := r.node.hashes[r.idx]
-
- // Copy into buffer + update read count
- m := copy(b[n:], hash[r.last:])
- n += m
-
- // If incomplete copy, return here
- if m < len(hash)-r.last {
- r.last = m
- return n, nil
- }
-
- // Check we can write last separator
- if n == len(b) {
- r.last = -1
- return n, nil
- }
-
- // Write separator, iter, reset
- b[n] = hashSeparator
- n++
- r.idx++
- r.last = 0
- }
-
- // We reached end of hashes
- return n, io.EOF
-}
-
-// nodeWriter is an io.Writer implementation for the node file representation,
-// which is useful when calculated node file is being read from the store
-type nodeWriter struct {
- node *node
- buf *byteutil.Buffer
-}
-
-func (w *nodeWriter) Write(b []byte) (int, error) {
- n := 0
-
- for {
- // Find next hash separator position
- idx := bytes.IndexByte(b[n:], hashSeparator)
- if idx == -1 {
- // Check we shouldn't be expecting it
- if w.buf.Len() > encodedHashLen {
- return n, errInvalidNode
- }
-
- // Write all contents to buffer
- w.buf.Write(b[n:])
- return len(b), nil
- }
-
- // Found hash separator, write
- // current buf contents to Node hashes
- w.buf.Write(b[n : n+idx])
- n += idx + 1
- if w.buf.Len() != encodedHashLen {
- return n, errInvalidNode
- }
-
- // Append to hashes & reset
- w.node.hashes = append(w.node.hashes, w.buf.String())
- w.buf.Reset()
- }
-}
-
-// blockReader is an io.Reader implementation for the combined, linked block
-// data contained with a node file. Basically, this allows reading value data
-// from the store for a given node file
-type blockReader struct {
- storage *BlockStorage
- node *node
- buf []byte
- prev int
-}
-
-func (r *blockReader) Read(b []byte) (int, error) {
- n := 0
-
- // Data left in buf, copy as much as we
- // can into supplied read buffer
- if r.prev < len(r.buf)-1 {
- n += copy(b, r.buf[r.prev:])
- r.prev += n
- if n >= len(b) {
- return n, nil
- }
- }
-
- for {
- // Check we have any hashes left
- if len(r.node.hashes) < 1 {
- return n, io.EOF
- }
-
- // Get next key from slice
- key := r.node.hashes[0]
- r.node.hashes = r.node.hashes[1:]
-
- // Attempt to fetch next batch of data
- var err error
- r.buf, err = r.storage.readBlock(key)
- if err != nil {
- return n, err
- }
- r.prev = 0
-
- // Copy as much as can from new buffer
- m := copy(b[n:], r.buf)
- r.prev += m
- n += m
-
- // If we hit end of supplied buf, return
- if n >= len(b) {
- return n, nil
- }
- }
-}
-
-var (
- // base64Encoding is our base64 encoding object.
- base64Encoding = hashenc.Base64()
-
- // encodedHashLen is the once-calculated encoded hash-sum length
- encodedHashLen = base64Encoding.EncodedLen(
- sha256.New().Size(),
- )
-)
-
-// hashEncoder is a HashEncoder with built-in encode buffer
-type hashEncoder struct {
- henc hashenc.HashEncoder
- ebuf []byte
-}
-
-// newHashEncoder returns a new hashEncoder instance
-func newHashEncoder() *hashEncoder {
- return &hashEncoder{
- henc: hashenc.New(sha256.New(), base64Encoding),
- ebuf: make([]byte, encodedHashLen),
- }
-}
-
-// EncodeSum encodes the src data and returns resulting bytes, only valid until next call to EncodeSum()
-func (henc *hashEncoder) EncodeSum(src []byte) string {
- henc.henc.EncodeSum(henc.ebuf, src)
- return string(henc.ebuf)
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/compressor.go b/vendor/codeberg.org/gruf/go-store/storage/compressor.go
deleted file mode 100644
index d6b975db0..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/compressor.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package storage
-
-import (
- "compress/gzip"
- "compress/zlib"
- "io"
-
- "codeberg.org/gruf/go-store/util"
- "github.com/golang/snappy"
-)
-
-// Compressor defines a means of compressing/decompressing values going into a key-value store
-type Compressor interface {
- // Reader returns a new decompressing io.ReadCloser based on supplied (compressed) io.Reader
- Reader(io.Reader) (io.ReadCloser, error)
-
- // Writer returns a new compressing io.WriteCloser based on supplied (uncompressed) io.Writer
- Writer(io.Writer) (io.WriteCloser, error)
-}
-
-type gzipCompressor struct {
- level int
-}
-
-// GZipCompressor returns a new Compressor that implements GZip at default compression level
-func GZipCompressor() Compressor {
- return GZipCompressorLevel(gzip.DefaultCompression)
-}
-
-// GZipCompressorLevel returns a new Compressor that implements GZip at supplied compression level
-func GZipCompressorLevel(level int) Compressor {
- return &gzipCompressor{
- level: level,
- }
-}
-
-func (c *gzipCompressor) Reader(r io.Reader) (io.ReadCloser, error) {
- return gzip.NewReader(r)
-}
-
-func (c *gzipCompressor) Writer(w io.Writer) (io.WriteCloser, error) {
- return gzip.NewWriterLevel(w, c.level)
-}
-
-type zlibCompressor struct {
- level int
- dict []byte
-}
-
-// ZLibCompressor returns a new Compressor that implements ZLib at default compression level
-func ZLibCompressor() Compressor {
- return ZLibCompressorLevelDict(zlib.DefaultCompression, nil)
-}
-
-// ZLibCompressorLevel returns a new Compressor that implements ZLib at supplied compression level
-func ZLibCompressorLevel(level int) Compressor {
- return ZLibCompressorLevelDict(level, nil)
-}
-
-// ZLibCompressorLevelDict returns a new Compressor that implements ZLib at supplied compression level with supplied dict
-func ZLibCompressorLevelDict(level int, dict []byte) Compressor {
- return &zlibCompressor{
- level: level,
- dict: dict,
- }
-}
-
-func (c *zlibCompressor) Reader(r io.Reader) (io.ReadCloser, error) {
- return zlib.NewReaderDict(r, c.dict)
-}
-
-func (c *zlibCompressor) Writer(w io.Writer) (io.WriteCloser, error) {
- return zlib.NewWriterLevelDict(w, c.level, c.dict)
-}
-
-type snappyCompressor struct{}
-
-// SnappyCompressor returns a new Compressor that implements Snappy
-func SnappyCompressor() Compressor {
- return &snappyCompressor{}
-}
-
-func (c *snappyCompressor) Reader(r io.Reader) (io.ReadCloser, error) {
- return util.NopReadCloser(snappy.NewReader(r)), nil
-}
-
-func (c *snappyCompressor) Writer(w io.Writer) (io.WriteCloser, error) {
- return snappy.NewBufferedWriter(w), nil
-}
-
-type nopCompressor struct{}
-
-// NoCompression is a Compressor that simply does nothing
-func NoCompression() Compressor {
- return &nopCompressor{}
-}
-
-func (c *nopCompressor) Reader(r io.Reader) (io.ReadCloser, error) {
- return util.NopReadCloser(r), nil
-}
-
-func (c *nopCompressor) Writer(w io.Writer) (io.WriteCloser, error) {
- return util.NopWriteCloser(w), nil
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/disk.go b/vendor/codeberg.org/gruf/go-store/storage/disk.go
deleted file mode 100644
index 457cc6364..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/disk.go
+++ /dev/null
@@ -1,400 +0,0 @@
-package storage
-
-import (
- "io"
- "io/fs"
- "os"
- "path"
- _path "path"
- "strings"
- "syscall"
-
- "codeberg.org/gruf/go-bytes"
- "codeberg.org/gruf/go-fastcopy"
- "codeberg.org/gruf/go-store/util"
-)
-
-// DefaultDiskConfig is the default DiskStorage configuration
-var DefaultDiskConfig = &DiskConfig{
- Overwrite: true,
- WriteBufSize: 4096,
- Transform: NopTransform(),
- Compression: NoCompression(),
-}
-
-// DiskConfig defines options to be used when opening a DiskStorage
-type DiskConfig struct {
- // Transform is the supplied key<-->path KeyTransform
- Transform KeyTransform
-
- // WriteBufSize is the buffer size to use when writing file streams (PutStream)
- WriteBufSize int
-
- // Overwrite allows overwriting values of stored keys in the storage
- Overwrite bool
-
- // LockFile allows specifying the filesystem path to use for the lockfile,
- // providing only a filename it will store the lockfile within provided store
- // path and nest the store under `path/store` to prevent access to lockfile
- LockFile string
-
- // Compression is the Compressor to use when reading / writing files, default is no compression
- Compression Compressor
-}
-
-// getDiskConfig returns a valid DiskConfig for supplied ptr
-func getDiskConfig(cfg *DiskConfig) DiskConfig {
- // If nil, use default
- if cfg == nil {
- cfg = DefaultDiskConfig
- }
-
- // Assume nil transform == none
- if cfg.Transform == nil {
- cfg.Transform = NopTransform()
- }
-
- // Assume nil compress == none
- if cfg.Compression == nil {
- cfg.Compression = NoCompression()
- }
-
- // Assume 0 buf size == use default
- if cfg.WriteBufSize < 1 {
- cfg.WriteBufSize = DefaultDiskConfig.WriteBufSize
- }
-
- // Assume empty lockfile path == use default
- if len(cfg.LockFile) < 1 {
- cfg.LockFile = LockFile
- }
-
- // Return owned config copy
- return DiskConfig{
- Transform: cfg.Transform,
- WriteBufSize: cfg.WriteBufSize,
- Overwrite: cfg.Overwrite,
- LockFile: cfg.LockFile,
- Compression: cfg.Compression,
- }
-}
-
-// DiskStorage is a Storage implementation that stores directly to a filesystem
-type DiskStorage struct {
- path string // path is the root path of this store
- cppool fastcopy.CopyPool // cppool is the prepared io copier with buffer pool
- config DiskConfig // cfg is the supplied configuration for this store
- lock *Lock // lock is the opened lockfile for this storage instance
-}
-
-// OpenFile opens a DiskStorage instance for given folder path and configuration
-func OpenFile(path string, cfg *DiskConfig) (*DiskStorage, error) {
- // Get checked config
- config := getDiskConfig(cfg)
-
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- // Clean provided store path, ensure
- // ends in '/' to help later path trimming
- storePath := pb.Clean(path) + "/"
-
- // Clean provided lockfile path
- lockfile := pb.Clean(config.LockFile)
-
- // Check if lockfile is an *actual* path or just filename
- if lockDir, _ := _path.Split(lockfile); len(lockDir) < 1 {
- // Lockfile is a filename, store must be nested under
- // $storePath/store to prevent access to the lockfile
- storePath += "store/"
- lockfile = pb.Join(path, lockfile)
- }
-
- // Attempt to open dir path
- file, err := os.OpenFile(storePath, defaultFileROFlags, defaultDirPerms)
- if err != nil {
- // If not a not-exist error, return
- if !os.IsNotExist(err) {
- return nil, err
- }
-
- // Attempt to make store path dirs
- err = os.MkdirAll(storePath, defaultDirPerms)
- if err != nil {
- return nil, err
- }
-
- // Reopen dir now it's been created
- file, err = os.OpenFile(storePath, defaultFileROFlags, defaultDirPerms)
- if err != nil {
- return nil, err
- }
- }
- defer file.Close()
-
- // Double check this is a dir (NOT a file!)
- stat, err := file.Stat()
- if err != nil {
- return nil, err
- } else if !stat.IsDir() {
- return nil, errPathIsFile
- }
-
- // Open and acquire storage lock for path
- lock, err := OpenLock(lockfile)
- if err != nil {
- return nil, err
- }
-
- // Prepare DiskStorage
- st := &DiskStorage{
- path: storePath,
- config: config,
- lock: lock,
- }
-
- // Set copypool buffer size
- st.cppool.Buffer(config.WriteBufSize)
-
- return st, nil
-}
-
-// Clean implements Storage.Clean()
-func (st *DiskStorage) Clean() error {
- st.lock.Add()
- defer st.lock.Done()
- if st.lock.Closed() {
- return ErrClosed
- }
- return util.CleanDirs(st.path)
-}
-
-// ReadBytes implements Storage.ReadBytes()
-func (st *DiskStorage) ReadBytes(key string) ([]byte, error) {
- // Get stream reader for key
- rc, err := st.ReadStream(key)
- if err != nil {
- return nil, err
- }
- defer rc.Close()
-
- // Read all bytes and return
- return io.ReadAll(rc)
-}
-
-// ReadStream implements Storage.ReadStream()
-func (st *DiskStorage) ReadStream(key string) (io.ReadCloser, error) {
- // Get file path for key
- kpath, err := st.filepath(key)
- if err != nil {
- return nil, err
- }
-
- // Track open
- st.lock.Add()
-
- // Check if open
- if st.lock.Closed() {
- return nil, ErrClosed
- }
-
- // Attempt to open file (replace ENOENT with our own)
- file, err := open(kpath, defaultFileROFlags)
- if err != nil {
- st.lock.Done()
- return nil, errSwapNotFound(err)
- }
-
- // Wrap the file in a compressor
- cFile, err := st.config.Compression.Reader(file)
- if err != nil {
- file.Close() // close this here, ignore error
- st.lock.Done()
- return nil, err
- }
-
- // Wrap compressor to ensure file close
- return util.ReadCloserWithCallback(cFile, func() {
- file.Close()
- st.lock.Done()
- }), nil
-}
-
-// WriteBytes implements Storage.WriteBytes()
-func (st *DiskStorage) WriteBytes(key string, value []byte) error {
- return st.WriteStream(key, bytes.NewReader(value))
-}
-
-// WriteStream implements Storage.WriteStream()
-func (st *DiskStorage) WriteStream(key string, r io.Reader) error {
- // Get file path for key
- kpath, err := st.filepath(key)
- if err != nil {
- return err
- }
-
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Ensure dirs leading up to file exist
- err = os.MkdirAll(path.Dir(kpath), defaultDirPerms)
- if err != nil {
- return err
- }
-
- // Prepare to swap error if need-be
- errSwap := errSwapNoop
-
- // Build file RW flags
- flags := defaultFileRWFlags
- if !st.config.Overwrite {
- flags |= syscall.O_EXCL
-
- // Catch + replace err exist
- errSwap = errSwapExist
- }
-
- // Attempt to open file
- file, err := open(kpath, flags)
- if err != nil {
- return errSwap(err)
- }
- defer file.Close()
-
- // Wrap the file in a compressor
- cFile, err := st.config.Compression.Writer(file)
- if err != nil {
- return err
- }
- defer cFile.Close()
-
- // Copy provided reader to file
- _, err = st.cppool.Copy(cFile, r)
- return err
-}
-
-// Stat implements Storage.Stat()
-func (st *DiskStorage) Stat(key string) (bool, error) {
- // Get file path for key
- kpath, err := st.filepath(key)
- if err != nil {
- return false, err
- }
-
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return false, ErrClosed
- }
-
- // Check for file on disk
- return stat(kpath)
-}
-
-// Remove implements Storage.Remove()
-func (st *DiskStorage) Remove(key string) error {
- // Get file path for key
- kpath, err := st.filepath(key)
- if err != nil {
- return err
- }
-
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Remove at path (we know this is file)
- if err := unlink(kpath); err != nil {
- return errSwapNotFound(err)
- }
-
- return nil
-}
-
-// Close implements Storage.Close()
-func (st *DiskStorage) Close() error {
- return st.lock.Close()
-}
-
-// WalkKeys implements Storage.WalkKeys()
-func (st *DiskStorage) WalkKeys(opts WalkKeysOptions) error {
- // Track open
- st.lock.Add()
- defer st.lock.Done()
-
- // Check if open
- if st.lock.Closed() {
- return ErrClosed
- }
-
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- // Walk dir for entries
- return util.WalkDir(pb, st.path, func(kpath string, fsentry fs.DirEntry) {
- if fsentry.Type().IsRegular() {
- // Only deal with regular files
-
- // Get full item path (without root)
- kpath = pb.Join(kpath, fsentry.Name())[len(st.path):]
-
- // Perform provided walk function
- opts.WalkFn(entry(st.config.Transform.PathToKey(kpath)))
- }
- })
-}
-
-// filepath checks and returns a formatted filepath for given key
-func (st *DiskStorage) filepath(key string) (string, error) {
- // Calculate transformed key path
- key = st.config.Transform.KeyToPath(key)
-
- // Acquire path builder
- pb := util.GetPathBuilder()
- defer util.PutPathBuilder(pb)
-
- // Generated joined root path
- pb.AppendString(st.path)
- pb.AppendString(key)
-
- // Check for dir traversal outside of root
- if isDirTraversal(st.path, pb.StringPtr()) {
- return "", ErrInvalidKey
- }
-
- return pb.String(), nil
-}
-
-// isDirTraversal will check if rootPlusPath is a dir traversal outside of root,
-// assuming that both are cleaned and that rootPlusPath is path.Join(root, somePath)
-func isDirTraversal(root, rootPlusPath string) bool {
- switch {
- // Root is $PWD, check for traversal out of
- case root == ".":
- return strings.HasPrefix(rootPlusPath, "../")
-
- // The path MUST be prefixed by root
- case !strings.HasPrefix(rootPlusPath, root):
- return true
-
- // In all other cases, check not equal
- default:
- return len(root) == len(rootPlusPath)
- }
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/errors.go b/vendor/codeberg.org/gruf/go-store/storage/errors.go
deleted file mode 100644
index 6953e11fe..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/errors.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package storage
-
-import (
- "errors"
- "syscall"
-)
-
-var (
- // ErrClosed is returned on operations on a closed storage
- ErrClosed = errors.New("store/storage: closed")
-
- // ErrNotFound is the error returned when a key cannot be found in storage
- ErrNotFound = errors.New("store/storage: key not found")
-
- // ErrAlreadyExist is the error returned when a key already exists in storage
- ErrAlreadyExists = errors.New("store/storage: key already exists")
-
- // ErrInvalidkey is the error returned when an invalid key is passed to storage
- ErrInvalidKey = errors.New("store/storage: invalid key")
-
- // ErrAlreadyLocked is returned on fail opening a storage lockfile
- ErrAlreadyLocked = errors.New("store/storage: storage lock already open")
-
- // errPathIsFile is returned when a path for a disk config is actually a file
- errPathIsFile = errors.New("store/storage: path is file")
-
- // errNoHashesWritten is returned when no blocks are written for given input value
- errNoHashesWritten = errors.New("storage/storage: no hashes written")
-
- // errInvalidNode is returned when read on an invalid node in the store is attempted
- errInvalidNode = errors.New("store/storage: invalid node")
-
- // errCorruptNode is returned when a block fails to be opened / read during read of a node.
- errCorruptNode = errors.New("store/storage: corrupted node")
-)
-
-// wrappedError allows wrapping together an inner with outer error.
-type wrappedError struct {
- inner error
- outer error
-}
-
-// wrap will return a new wrapped error from given inner and outer errors.
-func wrap(outer, inner error) *wrappedError {
- return &wrappedError{
- inner: inner,
- outer: outer,
- }
-}
-
-func (e *wrappedError) Is(target error) bool {
- return e.outer == target || e.inner == target
-}
-
-func (e *wrappedError) Error() string {
- return e.outer.Error() + ": " + e.inner.Error()
-}
-
-func (e *wrappedError) Unwrap() error {
- return e.inner
-}
-
-// errSwapNoop performs no error swaps
-func errSwapNoop(err error) error {
- return err
-}
-
-// ErrSwapNotFound swaps syscall.ENOENT for ErrNotFound
-func errSwapNotFound(err error) error {
- if err == syscall.ENOENT {
- return ErrNotFound
- }
- return err
-}
-
-// errSwapExist swaps syscall.EEXIST for ErrAlreadyExists
-func errSwapExist(err error) error {
- if err == syscall.EEXIST {
- return ErrAlreadyExists
- }
- return err
-}
-
-// errSwapUnavailable swaps syscall.EAGAIN for ErrAlreadyLocked
-func errSwapUnavailable(err error) error {
- if err == syscall.EAGAIN {
- return ErrAlreadyLocked
- }
- return err
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/fs.go b/vendor/codeberg.org/gruf/go-store/storage/fs.go
deleted file mode 100644
index b4729b041..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/fs.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package storage
-
-import (
- "os"
- "syscall"
-
- "codeberg.org/gruf/go-store/util"
-)
-
-const (
- // default file permission bits
- defaultDirPerms = 0o755
- defaultFilePerms = 0o644
-
- // default file open flags
- defaultFileROFlags = syscall.O_RDONLY
- defaultFileRWFlags = syscall.O_CREAT | syscall.O_RDWR
- defaultFileLockFlags = syscall.O_RDONLY | syscall.O_CREAT
-)
-
-// NOTE:
-// These functions are for opening storage files,
-// not necessarily for e.g. initial setup (OpenFile)
-
-// open should not be called directly.
-func open(path string, flags int) (*os.File, error) {
- var fd int
- err := util.RetryOnEINTR(func() (err error) {
- fd, err = syscall.Open(path, flags, defaultFilePerms)
- return
- })
- if err != nil {
- return nil, err
- }
- return os.NewFile(uintptr(fd), path), nil
-}
-
-// stat checks for a file on disk.
-func stat(path string) (bool, error) {
- var stat syscall.Stat_t
- err := util.RetryOnEINTR(func() error {
- return syscall.Stat(path, &stat)
- })
- if err != nil {
- if err == syscall.ENOENT { //nolint
- err = nil
- }
- return false, err
- }
- return true, nil
-}
-
-// unlink removes a file (not dir!) on disk.
-func unlink(path string) error {
- return util.RetryOnEINTR(func() error {
- return syscall.Unlink(path)
- })
-}
-
-// rmdir removes a dir (not file!) on disk.
-func rmdir(path string) error {
- return util.RetryOnEINTR(func() error {
- return syscall.Rmdir(path)
- })
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/lock.go b/vendor/codeberg.org/gruf/go-store/storage/lock.go
deleted file mode 100644
index 8a6c4c5e8..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/lock.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package storage
-
-import (
- "sync"
- "sync/atomic"
- "syscall"
-
- "codeberg.org/gruf/go-store/util"
-)
-
-// LockFile is our standard lockfile name.
-const LockFile = "store.lock"
-
-// Lock represents a filesystem lock to ensure only one storage instance open per path.
-type Lock struct {
- fd int
- wg sync.WaitGroup
- st uint32
-}
-
-// OpenLock opens a lockfile at path.
-func OpenLock(path string) (*Lock, error) {
- var fd int
-
- // Open the file descriptor at path
- err := util.RetryOnEINTR(func() (err error) {
- fd, err = syscall.Open(path, defaultFileLockFlags, defaultFilePerms)
- return
- })
- if err != nil {
- return nil, err
- }
-
- // Get a flock on the file descriptor
- err = util.RetryOnEINTR(func() error {
- return syscall.Flock(fd, syscall.LOCK_EX|syscall.LOCK_NB)
- })
- if err != nil {
- return nil, errSwapUnavailable(err)
- }
-
- return &Lock{fd: fd}, nil
-}
-
-// Add will add '1' to the underlying sync.WaitGroup.
-func (f *Lock) Add() {
- f.wg.Add(1)
-}
-
-// Done will decrememnt '1' from the underlying sync.WaitGroup.
-func (f *Lock) Done() {
- f.wg.Done()
-}
-
-// Close will attempt to close the lockfile and file descriptor.
-func (f *Lock) Close() error {
- var err error
- if atomic.CompareAndSwapUint32(&f.st, 0, 1) {
- // Wait until done
- f.wg.Wait()
-
- // Ensure gets closed
- defer syscall.Close(f.fd)
-
- // Call funlock on the file descriptor
- err = util.RetryOnEINTR(func() error {
- return syscall.Flock(f.fd, syscall.LOCK_UN|syscall.LOCK_NB)
- })
- }
- return err
-}
-
-// Closed will return whether this lockfile has been closed (and unlocked).
-func (f *Lock) Closed() bool {
- return (atomic.LoadUint32(&f.st) == 1)
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/memory.go b/vendor/codeberg.org/gruf/go-store/storage/memory.go
deleted file mode 100644
index 2dab562d6..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/memory.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package storage
-
-import (
- "io"
- "sync"
-
- "codeberg.org/gruf/go-bytes"
- "codeberg.org/gruf/go-store/util"
-)
-
-// MemoryStorage is a storage implementation that simply stores key-value
-// pairs in a Go map in-memory. The map is protected by a mutex.
-type MemoryStorage struct {
- ow bool // overwrites
- fs map[string][]byte
- mu sync.Mutex
- st uint32
-}
-
-// OpenMemory opens a new MemoryStorage instance with internal map of 'size'.
-func OpenMemory(size int, overwrites bool) *MemoryStorage {
- return &MemoryStorage{
- fs: make(map[string][]byte, size),
- mu: sync.Mutex{},
- ow: overwrites,
- }
-}
-
-// Clean implements Storage.Clean().
-func (st *MemoryStorage) Clean() error {
- st.mu.Lock()
- defer st.mu.Unlock()
- if st.st == 1 {
- return ErrClosed
- }
- return nil
-}
-
-// ReadBytes implements Storage.ReadBytes().
-func (st *MemoryStorage) ReadBytes(key string) ([]byte, error) {
- // Lock storage
- st.mu.Lock()
-
- // Check store open
- if st.st == 1 {
- st.mu.Unlock()
- return nil, ErrClosed
- }
-
- // Check for key
- b, ok := st.fs[key]
- st.mu.Unlock()
-
- // Return early if not exist
- if !ok {
- return nil, ErrNotFound
- }
-
- // Create return copy
- return bytes.Copy(b), nil
-}
-
-// ReadStream implements Storage.ReadStream().
-func (st *MemoryStorage) ReadStream(key string) (io.ReadCloser, error) {
- // Lock storage
- st.mu.Lock()
-
- // Check store open
- if st.st == 1 {
- st.mu.Unlock()
- return nil, ErrClosed
- }
-
- // Check for key
- b, ok := st.fs[key]
- st.mu.Unlock()
-
- // Return early if not exist
- if !ok {
- return nil, ErrNotFound
- }
-
- // Create io.ReadCloser from 'b' copy
- b = bytes.Copy(b)
- r := bytes.NewReader(b)
- return util.NopReadCloser(r), nil
-}
-
-// WriteBytes implements Storage.WriteBytes().
-func (st *MemoryStorage) WriteBytes(key string, b []byte) error {
- // Lock storage
- st.mu.Lock()
- defer st.mu.Unlock()
-
- // Check store open
- if st.st == 1 {
- return ErrClosed
- }
-
- _, ok := st.fs[key]
-
- // Check for already exist
- if ok && !st.ow {
- return ErrAlreadyExists
- }
-
- // Write + unlock
- st.fs[key] = bytes.Copy(b)
- return nil
-}
-
-// WriteStream implements Storage.WriteStream().
-func (st *MemoryStorage) WriteStream(key string, r io.Reader) error {
- // Read all from reader
- b, err := io.ReadAll(r)
- if err != nil {
- return err
- }
-
- // Write to storage
- return st.WriteBytes(key, b)
-}
-
-// Stat implements Storage.Stat().
-func (st *MemoryStorage) Stat(key string) (bool, error) {
- // Lock storage
- st.mu.Lock()
- defer st.mu.Unlock()
-
- // Check store open
- if st.st == 1 {
- return false, ErrClosed
- }
-
- // Check for key
- _, ok := st.fs[key]
- return ok, nil
-}
-
-// Remove implements Storage.Remove().
-func (st *MemoryStorage) Remove(key string) error {
- // Lock storage
- st.mu.Lock()
- defer st.mu.Unlock()
-
- // Check store open
- if st.st == 1 {
- return ErrClosed
- }
-
- // Check for key
- _, ok := st.fs[key]
- if !ok {
- return ErrNotFound
- }
-
- // Remove from store
- delete(st.fs, key)
-
- return nil
-}
-
-// Close implements Storage.Close().
-func (st *MemoryStorage) Close() error {
- st.mu.Lock()
- st.st = 1
- st.mu.Unlock()
- return nil
-}
-
-// WalkKeys implements Storage.WalkKeys().
-func (st *MemoryStorage) WalkKeys(opts WalkKeysOptions) error {
- // Lock storage
- st.mu.Lock()
- defer st.mu.Unlock()
-
- // Check store open
- if st.st == 1 {
- return ErrClosed
- }
-
- // Walk store keys
- for key := range st.fs {
- opts.WalkFn(entry(key))
- }
-
- return nil
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/storage.go b/vendor/codeberg.org/gruf/go-store/storage/storage.go
deleted file mode 100644
index 346aff097..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/storage.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package storage
-
-import (
- "io"
-)
-
-// StorageEntry defines a key in Storage
-type StorageEntry interface {
- // Key returns the storage entry's key
- Key() string
-}
-
-// entry is the simplest possible StorageEntry
-type entry string
-
-func (e entry) Key() string {
- return string(e)
-}
-
-// Storage defines a means of storing and accessing key value pairs
-type Storage interface {
- // ReadBytes returns the byte value for key in storage
- ReadBytes(key string) ([]byte, error)
-
- // ReadStream returns an io.ReadCloser for the value bytes at key in the storage
- ReadStream(key string) (io.ReadCloser, error)
-
- // WriteBytes writes the supplied value bytes at key in the storage
- WriteBytes(key string, value []byte) error
-
- // WriteStream writes the bytes from supplied reader at key in the storage
- WriteStream(key string, r io.Reader) error
-
- // Stat checks if the supplied key is in the storage
- Stat(key string) (bool, error)
-
- // Remove attempts to remove the supplied key-value pair from storage
- Remove(key string) error
-
- // Close will close the storage, releasing any file locks
- Close() error
-
- // Clean removes unused values and unclutters the storage (e.g. removing empty folders)
- Clean() error
-
- // WalkKeys walks the keys in the storage
- WalkKeys(opts WalkKeysOptions) error
-}
-
-// WalkKeysOptions defines how to walk the keys in a storage implementation
-type WalkKeysOptions struct {
- // WalkFn is the function to apply on each StorageEntry
- WalkFn func(StorageEntry)
-}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/transform.go b/vendor/codeberg.org/gruf/go-store/storage/transform.go
deleted file mode 100644
index 3863dd774..000000000
--- a/vendor/codeberg.org/gruf/go-store/storage/transform.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package storage
-
-// KeyTransform defines a method of converting store keys to storage paths (and vice-versa)
-type KeyTransform interface {
- // KeyToPath converts a supplied key to storage path
- KeyToPath(string) string
-
- // PathToKey converts a supplied storage path to key
- PathToKey(string) string
-}
-
-type nopKeyTransform struct{}
-
-// NopTransform returns a nop key transform (i.e. key = path)
-func NopTransform() KeyTransform {
- return &nopKeyTransform{}
-}
-
-func (t *nopKeyTransform) KeyToPath(key string) string {
- return key
-}
-
-func (t *nopKeyTransform) PathToKey(path string) string {
- return path
-}