blob: be7265d498791ebbeb2932f06eb0e4f8a768bc05 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package store defines the API for the syncbase storage engine.
// Currently, this API and its implementations are meant to be internal.
package store
// TODO(sadovsky): Decide whether to defensively copy passed-in []byte's vs.
// requiring clients not to modify passed-in []byte's.
// StoreReader reads data from a CRUD-capable storage engine.
type StoreReader interface {
// Get returns the value for the given key. The returned slice may be a
// sub-slice of valbuf if valbuf was large enough to hold the entire value.
// Otherwise, a newly allocated slice will be returned. It is valid to pass a
// nil valbuf.
// If the given key is unknown, valbuf is returned unchanged and the function
// fails with ErrUnknownKey.
Get(key, valbuf []byte) ([]byte, error)
// Scan returns all rows with keys in range [start, limit). If limit is "",
// all rows with keys >= start are included.
// Concurrency semantics: It is legal to perform writes concurrently with
// Scan. The returned stream may or may not reflect subsequent writes to keys
// not yet reached by the stream.
Scan(start, limit []byte) Stream
}
// StoreWriter writes data to a CRUD-capable storage engine.
type StoreWriter interface {
// Put writes the given value for the given key.
Put(key, value []byte) error
// Delete deletes the entry for the given key.
// Succeeds (no-op) if the given key is unknown.
Delete(key []byte) error
}
// storeReadWriter combines StoreReader and StoreWriter.
type storeReadWriter interface {
StoreReader
StoreWriter
}
// Store is a CRUD-capable storage engine that supports transactions.
type Store interface {
storeReadWriter
// Close closes the store.
Close() error
// NewTransaction creates a transaction.
// TODO(rogulenko): add transaction options.
NewTransaction() Transaction
// NewSnapshot creates a snapshot.
// TODO(rogulenko): add snapshot options.
NewSnapshot() Snapshot
}
// SnapshotOrTransaction represents a Snapshot or a Transaction.
type SnapshotOrTransaction interface {
StoreReader
// Abort closes the snapshot or transaction.
// Any subsequent method calls will fail.
// NOTE: this method is also used to distinguish between StoreReader and
// SnapshotOrTransaction.
Abort() error
}
// Snapshot is a handle to particular state in time of a Store.
//
// All read operations are executed against a consistent view of Store commit
// history. Snapshots don't acquire locks and thus don't block transactions.
type Snapshot interface {
SnapshotOrTransaction
// __snapshotSpec is a utility method to distinguish between Snapshot and
// SnapshotOrTransaction. This is a no-op.
__snapshotSpec()
}
// Transaction provides a mechanism for atomic reads and writes. Instead of
// calling this function directly, clients are encouraged to use the
// RunInTransaction() helper function, which detects "concurrent transaction"
// errors and handles retries internally.
//
// Default concurrency semantics:
// - Reads (e.g. gets, scans) inside a transaction operate over a consistent
// snapshot taken during NewTransaction(), and will see the effects of prior
// writes performed inside the transaction.
// - Commit() may fail with ErrConcurrentTransaction, indicating that after
// NewTransaction() but before Commit(), some concurrent routine wrote to a
// key that matches a key or row-range read inside this transaction.
// - Other methods will never fail with error ErrConcurrentTransaction, even if
// it is known that Commit() will fail with this error.
//
// Once a transaction has been committed or aborted, subsequent method calls
// will fail with no effect.
type Transaction interface {
SnapshotOrTransaction
StoreWriter
// Commit commits the transaction.
// Fails if writes from outside this transaction conflict with reads from
// within this transaction.
Commit() error
}
// Stream is an interface for iterating through a collection of key-value pairs.
type Stream interface {
// Advance stages an element so the client can retrieve it with Key or Value.
// Advance returns true iff there is an element to retrieve. The client must
// call Advance before calling Key or Value. The client must call Cancel if it
// does not iterate through all elements (i.e. until Advance returns false).
// Advance may block if an element is not immediately available.
Advance() bool
// Key returns the key of the element that was staged by Advance. The returned
// slice may be a sub-slice of keybuf if keybuf was large enough to hold the
// entire key. Otherwise, a newly allocated slice will be returned. It is
// valid to pass a nil keybuf.
// Key may panic if Advance returned false or was not called at all.
// Key does not block.
Key(keybuf []byte) []byte
// Value returns the value of the element that was staged by Advance. The
// returned slice may be a sub-slice of valbuf if valbuf was large enough to
// hold the entire value. Otherwise, a newly allocated slice will be returned.
// It is valid to pass a nil valbuf.
// Value may panic if Advance returned false or was not called at all.
// Value does not block.
Value(valbuf []byte) []byte
// Err returns a non-nil error iff the stream encountered any errors. Err does
// not block.
Err() error
// Cancel notifies the stream provider that it can stop producing elements.
// The client must call Cancel if it does not iterate through all elements
// (i.e. until Advance returns false). Cancel is idempotent and can be called
// concurrently with a goroutine that is iterating via Advance/Key/Value.
// Cancel causes Advance to subsequently return false. Cancel does not block.
Cancel()
}