2018-12-18 15:44:25 +00:00
|
|
|
package kv
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// ErrKeyNotFound is the error returned when the key requested is not found.
|
|
|
|
ErrKeyNotFound = errors.New("key not found")
|
|
|
|
// ErrTxNotWritable is the error returned when an mutable operation is called during
|
|
|
|
// a non-writable transaction.
|
|
|
|
ErrTxNotWritable = errors.New("transaction is not writable")
|
|
|
|
)
|
|
|
|
|
2019-02-19 23:47:19 +00:00
|
|
|
// IsNotFound returns a boolean indicating whether the error is known to report that a key or was not found.
|
|
|
|
func IsNotFound(err error) bool {
|
|
|
|
return err == ErrKeyNotFound
|
|
|
|
}
|
|
|
|
|
2018-12-18 15:44:25 +00:00
|
|
|
// Store is an interface for a generic key value store. It is modeled after
|
|
|
|
// the boltdb database struct.
|
|
|
|
type Store interface {
|
|
|
|
// View opens up a transaction that will not write to any data. Implementing interfaces
|
|
|
|
// should take care to ensure that all view transactions do not mutate any data.
|
2019-03-05 00:38:10 +00:00
|
|
|
View(context.Context, func(Tx) error) error
|
2018-12-18 15:44:25 +00:00
|
|
|
// Update opens up a transaction that will mutate data.
|
2019-03-05 00:38:10 +00:00
|
|
|
Update(context.Context, func(Tx) error) error
|
2018-12-18 15:44:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Tx is a transaction in the store.
|
|
|
|
type Tx interface {
|
2019-02-19 23:47:19 +00:00
|
|
|
// Bucket possibly creates and returns bucket, b.
|
2018-12-18 15:44:25 +00:00
|
|
|
Bucket(b []byte) (Bucket, error)
|
2019-02-19 23:47:19 +00:00
|
|
|
// Context returns the context associated with this Tx.
|
2018-12-18 15:44:25 +00:00
|
|
|
Context() context.Context
|
2019-02-19 23:47:19 +00:00
|
|
|
// WithContext associates a context with this Tx.
|
2018-12-18 15:44:25 +00:00
|
|
|
WithContext(ctx context.Context)
|
|
|
|
}
|
|
|
|
|
2019-11-20 20:19:08 +00:00
|
|
|
type KeyPredicateFunc func(key []byte) bool
|
|
|
|
|
2019-10-31 20:01:41 +00:00
|
|
|
type CursorHints struct {
|
2019-11-20 20:19:08 +00:00
|
|
|
KeyPrefix *string
|
|
|
|
KeyStart *string
|
|
|
|
KeyPredicateFn KeyPredicateFunc
|
2019-10-31 20:01:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CursorHint configures CursorHints
|
|
|
|
type CursorHint func(*CursorHints)
|
|
|
|
|
|
|
|
// WithCursorHintPrefix is a hint to the store
|
|
|
|
// that the caller is only interested keys with the
|
|
|
|
// specified prefix.
|
|
|
|
func WithCursorHintPrefix(prefix string) CursorHint {
|
|
|
|
return func(o *CursorHints) {
|
|
|
|
o.KeyPrefix = &prefix
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithCursorHintKeyStart is a hint to the store
|
|
|
|
// that the caller is interested in reading keys from
|
|
|
|
// start.
|
|
|
|
func WithCursorHintKeyStart(start string) CursorHint {
|
|
|
|
return func(o *CursorHints) {
|
|
|
|
o.KeyStart = &start
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-20 20:19:08 +00:00
|
|
|
// WithCursorHintKeyPredicate is a hint to the store
|
|
|
|
// to return only key / values which return true for the
|
|
|
|
// f.
|
|
|
|
func WithCursorHintKeyPredicate(f KeyPredicateFunc) CursorHint {
|
|
|
|
return func(o *CursorHints) {
|
|
|
|
o.KeyPredicateFn = f
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-18 15:44:25 +00:00
|
|
|
// Bucket is the abstraction used to perform get/put/delete/get-many operations
|
|
|
|
// in a key value store.
|
|
|
|
type Bucket interface {
|
2019-03-05 00:38:10 +00:00
|
|
|
// TODO context?
|
2019-02-19 23:47:19 +00:00
|
|
|
// Get returns a key within this bucket. Errors if key does not exist.
|
2018-12-18 15:44:25 +00:00
|
|
|
Get(key []byte) ([]byte, error)
|
2019-10-31 20:01:41 +00:00
|
|
|
// Cursor returns a cursor at the beginning of this bucket optionally
|
|
|
|
// using the provided hints to improve performance.
|
|
|
|
Cursor(hints ...CursorHint) (Cursor, error)
|
2018-12-18 15:44:25 +00:00
|
|
|
// Put should error if the transaction it was called in is not writable.
|
|
|
|
Put(key, value []byte) error
|
|
|
|
// Delete should error if the transaction it was called in is not writable.
|
|
|
|
Delete(key []byte) error
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cursor is an abstraction for iterating/ranging through data. A concrete implementation
|
|
|
|
// of a cursor can be found in cursor.go.
|
|
|
|
type Cursor interface {
|
2019-02-19 23:47:19 +00:00
|
|
|
// Seek moves the cursor forward until reaching prefix in the key name.
|
2018-12-18 15:44:25 +00:00
|
|
|
Seek(prefix []byte) (k []byte, v []byte)
|
2019-02-19 23:47:19 +00:00
|
|
|
// First moves the cursor to the first key in the bucket.
|
2018-12-18 15:44:25 +00:00
|
|
|
First() (k []byte, v []byte)
|
2019-02-19 23:47:19 +00:00
|
|
|
// Last moves the cursor to the last key in the bucket.
|
2018-12-18 15:44:25 +00:00
|
|
|
Last() (k []byte, v []byte)
|
2019-02-19 23:47:19 +00:00
|
|
|
// Next moves the cursor to the next key in the bucket.
|
2018-12-18 15:44:25 +00:00
|
|
|
Next() (k []byte, v []byte)
|
2019-02-19 23:47:19 +00:00
|
|
|
// Prev moves the cursor to the prev key in the bucket.
|
2018-12-18 15:44:25 +00:00
|
|
|
Prev() (k []byte, v []byte)
|
|
|
|
}
|