use crate::error::Result;
use crate::txn::TxnManager;
use crate::types::{Key, TxnId, TxnMode, Value};
#[derive(Debug, Clone, PartialEq)]
pub enum RuntimeStats {
Memory(crate::kv::memory::MemoryStats),
Lsm(crate::lsm::metrics::LsmMetricsSnapshot),
}
#[cfg(feature = "test-hooks")]
pub mod hooks;
pub mod any;
#[cfg(feature = "tokio")]
pub mod async_adapter;
#[cfg(feature = "async")]
pub mod async_kv;
pub mod change_journal;
pub mod memory;
pub mod owned;
pub mod read_at;
pub mod search;
pub mod storage;
#[cfg(feature = "s3")]
pub mod s3;
pub use any::AnyKV;
#[cfg(feature = "tokio")]
pub use async_adapter::{AsyncKVStoreAdapter, AsyncKVTransactionAdapter};
#[cfg(feature = "async")]
pub use async_kv::{AsyncKVStore, AsyncKVTransaction};
pub use change_journal::{
decode_range_change, journal_key, stage_range_change, RangeChangeJournalCapability,
RangeChangePayload, RangeChangeRecord,
};
pub use owned::{
OwnedKVScan, OwnedKVStore, OwnedKVTransaction, OwnedKVTransactionAdapter, OwnedReadLease,
OwnedReadOptions, OwnedReadSession, OwnedReadSessionApi, OwnedSessionFactory,
OwnedTransactionLease, OwnedTransactionSession, OwnedTransactionSessionApi,
};
pub use read_at::{ReadAtCapability, ReadAtError, ReadAtPoint, ReadAtResult};
pub use search::{
KeyPattern, KeySearchCancellation, KeySearchEntry, KeySearchPage, KeySearchRequest,
};
#[cfg(feature = "s3")]
pub use s3::{S3Config, S3KV};
pub trait KVTransaction<'a> {
fn id(&self) -> TxnId;
fn mode(&self) -> TxnMode;
fn get(&mut self, key: &Key) -> Result<Option<Value>>;
fn put(&mut self, key: Key, value: Value) -> Result<()>;
fn delete(&mut self, key: Key) -> Result<()>;
fn scan_prefix(&mut self, prefix: &[u8])
-> Result<Box<dyn Iterator<Item = (Key, Value)> + '_>>;
fn scan_range(
&mut self,
start: &[u8],
end: &[u8],
) -> Result<Box<dyn Iterator<Item = (Key, Value)> + '_>>;
fn scan_from(&mut self, start: &[u8]) -> Result<Box<dyn Iterator<Item = (Key, Value)> + '_>> {
let _ = start;
Err(crate::error::Error::InvalidParameter {
param: "scan_from".into(),
reason: "backend does not implement cursor-based scanning".into(),
})
}
fn search_keys(&mut self, request: &KeySearchRequest) -> Result<KeySearchPage> {
self.search_keys_with_cancellation(request, &KeySearchCancellation::default())
}
fn search_keys_with_cancellation(
&mut self,
request: &KeySearchRequest,
cancellation: &KeySearchCancellation,
) -> Result<KeySearchPage> {
let prepared = search::PreparedKeySearch::new(request)?;
let mut cursor_start = request.cursor.clone().unwrap_or_default();
let mut scan = if request.cursor.is_some() {
cursor_start.push(0);
self.scan_from(&cursor_start)?
} else {
self.scan_prefix(prepared.prefix())?
};
prepared.collect(
|| Ok(scan.next().map(|(key, value)| (key, Some(value)))),
request,
cancellation,
)
}
fn commit_self(self) -> Result<()>;
fn rollback_self(self) -> Result<()>;
}
pub trait KVStore: Send + Sync {
type Transaction<'a>: KVTransaction<'a>
where
Self: 'a;
type Manager<'a>: TxnManager<'a, Self::Transaction<'a>>
where
Self: 'a;
fn txn_manager(&self) -> Self::Manager<'_>;
fn begin(&self, mode: TxnMode) -> Result<Self::Transaction<'_>>;
fn read_at_capability(&self) -> ReadAtCapability {
ReadAtCapability::unavailable("backend does not prove retained cluster read points")
}
fn begin_read_at(&self, point: &ReadAtPoint) -> ReadAtResult<Self::Transaction<'_>> {
Err(self
.read_at_capability()
.unavailable_error(point, "backend did not implement begin_read_at"))
}
fn runtime_stats(&self) -> Option<RuntimeStats> {
None
}
fn set_memory_limit_bytes(&self, _limit: Option<usize>) -> Result<()> {
Ok(())
}
fn set_cache_capacity_bytes(&self, _capacity: usize) -> Result<()> {
Ok(())
}
fn clear_cache(&self) -> Result<usize> {
Ok(0)
}
}