pub struct Db { /* private fields */ }
Expand description
The sled
embedded database!
Implementations
sourceimpl Db
impl Db
sourcepub fn start_default<P: AsRef<Path>>(path: P) -> Result<Db, ()>
pub fn start_default<P: AsRef<Path>>(path: P) -> Result<Db, ()>
Load existing or create a new Db
with a default configuration.
sourcepub fn generate_id(&self) -> Result<usize, ()>
pub fn generate_id(&self) -> Result<usize, ()>
Generate a monotonic ID. Not guaranteed to be
contiguous. Written to disk every idgen_persist_interval
operations, followed by a blocking flush. During recovery, we
take the last recovered generated ID and add 2x
the idgen_persist_interval
to it. While persisting, if the
previous persisted counter wasn’t synced to disk yet, we will do
a blocking flush to fsync the latest counter, ensuring
that we will never give out the same counter twice.
sourcepub fn open_tree(&self, name: Vec<u8>) -> Result<Arc<Tree>, ()>
pub fn open_tree(&self, name: Vec<u8>) -> Result<Arc<Tree>, ()>
Open or create a new disk-backed Tree with its own keyspace,
accessible from the Db
via the provided identifier.
sourcepub fn was_recovered(&self) -> bool
pub fn was_recovered(&self) -> bool
Returns true
if the database was
recovered from a previous process.
Note that database state is only
guaranteed to be present up to the
last call to flush
! Otherwise state
is synced to disk periodically if the
sync_every_ms
configuration option
is set to Some(number_of_ms_between_syncs)
or if the IO buffer gets filled to
capacity before being rotated.
sourcepub fn mark_pending_tx(&self, _pages: Vec<PageId>, _txid: u64) -> Result<(), ()>
pub fn mark_pending_tx(&self, _pages: Vec<PageId>, _txid: u64) -> Result<(), ()>
Record a set of pages as being involved in
a transaction that is about to be written to
one of the structures in the Db. Do this
before performing transactions in case
the system crashes before all changes
can be written. During recovery,
you can call possibly_dirty_pages
to get the set of pages that may have
transactional state written to them.
sourcepub fn abort_tx(&self, _txid: u64) -> Result<(), ()>
pub fn abort_tx(&self, _txid: u64) -> Result<(), ()>
Mark a transaction as being aborted. This ensures that during recovery we know that this transaction is not the last one that should be recovered, because the process finished the transaction, but we may need to clean up its pending state still.
sourcepub fn commit_tx(&self, _txid: u64) -> Result<(), ()>
pub fn commit_tx(&self, _txid: u64) -> Result<(), ()>
Mark a transaction as being completed. This ensures that during recovery we know that this transaction completed, and that we can safely remove its entry in the transaction table.
Methods from Deref<Target = Tree>
sourcepub fn watch_prefix(&self, prefix: Vec<u8>) -> SubscriberⓘNotable traits for Subscriberimpl Iterator for Subscriber type Item = Event;
pub fn watch_prefix(&self, prefix: Vec<u8>) -> SubscriberⓘNotable traits for Subscriberimpl Iterator for Subscriber type Item = Event;
Subscribe to Event
s that happen to keys that have
the specified prefix. Events for particular keys are
guaranteed to be witnessed in the same order by all
threads, but threads may witness different interleavings
of Event
s across different keys. If subscribers don’t
keep up with new writes, they will cause new writes
to block. There is a buffer of 1024 items per
Subscriber
. This can be used to build reactive
and replicated systems.
Examples
use sled::{Event, ConfigBuilder};
let config = ConfigBuilder::new().temporary(true).build();
let tree = sled::Db::start(config).unwrap();
// watch all events by subscribing to the empty prefix
let mut events = tree.watch_prefix(vec![]);
let tree_2 = tree.clone();
let thread = std::thread::spawn(move || {
tree.set(vec![0], vec![1]).unwrap();
});
// events is a blocking `Iterator` over `Event`s
for event in events.take(1) {
match event {
Event::Set(key, value) => assert_eq!(key, vec![0]),
Event::Merge(key, partial_value) => {}
Event::Del(key) => {}
}
}
thread.join().unwrap();
sourcepub fn clear(&self) -> Result<(), ()>
pub fn clear(&self) -> Result<(), ()>
Clears the Tree
, removing all values.
Note that this is not atomic.
sourcepub fn flush(&self) -> Result<(), ()>
pub fn flush(&self) -> Result<(), ()>
Flushes all dirty IO buffers and calls fsync. If this succeeds, it is guaranteed that all previous writes will be recovered if the system crashes.
sourcepub fn contains_key<K: AsRef<[u8]>>(&self, key: K) -> Result<bool, ()>
pub fn contains_key<K: AsRef<[u8]>>(&self, key: K) -> Result<bool, ()>
Returns true
if the Tree
contains a value for
the specified key.
sourcepub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<PinnedValue>, ()>
pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<PinnedValue>, ()>
Retrieve a value from the Tree
if it exists.
sourcepub fn get_lt<K: AsRef<[u8]>>(
&self,
key: K
) -> Result<Option<(Vec<u8>, PinnedValue)>, ()>
pub fn get_lt<K: AsRef<[u8]>>(
&self,
key: K
) -> Result<Option<(Vec<u8>, PinnedValue)>, ()>
Retrieve the key and value before the provided key, if one exists.
Examples
use sled::{ConfigBuilder, Error};
let config = ConfigBuilder::new().temporary(true).build();
let tree = sled::Db::start(config).unwrap();
for i in 0..10 {
tree.set(vec![i], vec![i]).expect("should write successfully");
}
assert!(tree.get_lt(vec![]).unwrap().is_none());
assert!(tree.get_lt(vec![0]).unwrap().is_none());
assert!(tree.get_lt(vec![1]).unwrap().unwrap().1 == vec![0]);
assert!(tree.get_lt(vec![9]).unwrap().unwrap().1 == vec![8]);
assert!(tree.get_lt(vec![10]).unwrap().unwrap().1 == vec![9]);
assert!(tree.get_lt(vec![255]).unwrap().unwrap().1 == vec![9]);
sourcepub fn get_gt<K: AsRef<[u8]>>(
&self,
key: K
) -> Result<Option<(Vec<u8>, PinnedValue)>, ()>
pub fn get_gt<K: AsRef<[u8]>>(
&self,
key: K
) -> Result<Option<(Vec<u8>, PinnedValue)>, ()>
Retrieve the next key and value from the Tree
after the
provided key.
Examples
use sled::{ConfigBuilder, Error};
let config = ConfigBuilder::new().temporary(true).build();
let tree = sled::Db::start(config).unwrap();
for i in 0..10 {
tree.set(vec![i], vec![i]).expect("should write successfully");
}
assert!(tree.get_gt(vec![]).unwrap().unwrap().1 == vec![0]);
assert!(tree.get_gt(vec![0]).unwrap().unwrap().1 == vec![1]);
assert!(tree.get_gt(vec![1]).unwrap().unwrap().1 == vec![2]);
assert!(tree.get_gt(vec![8]).unwrap().unwrap().1 == vec![9]);
assert!(tree.get_gt(vec![9]).unwrap().is_none());
sourcepub fn cas<K: AsRef<[u8]>>(
&self,
key: K,
old: Option<&[u8]>,
new: Option<Vec<u8>>
) -> Result<(), Option<PinnedValue>>
pub fn cas<K: AsRef<[u8]>>(
&self,
key: K,
old: Option<&[u8]>,
new: Option<Vec<u8>>
) -> Result<(), Option<PinnedValue>>
Compare and swap. Capable of unique creation, conditional modification, or deletion. If old is None, this will only set the value if it doesn’t exist yet. If new is None, will delete the value if old is correct. If both old and new are Some, will modify the value if old is correct. If Tree is read-only, will do nothing.
Examples
use sled::{ConfigBuilder, Error};
let config = ConfigBuilder::new().temporary(true).build();
let t = sled::Db::start(config).unwrap();
// unique creation
assert_eq!(t.cas(&[1], None, Some(vec![1])), Ok(()));
// assert_eq!(t.cas(&[1], None, Some(vec![1])), Err(Error::CasFailed(Some(vec![1]))));
// conditional modification
assert_eq!(t.cas(&[1], Some(&*vec![1]), Some(vec![2])), Ok(()));
// assert_eq!(t.cas(&[1], Some(vec![1]), Some(vec![2])), Err(Error::CasFailed(Some(vec![2]))));
// conditional deletion
assert_eq!(t.cas(&[1], Some(&[2]), None), Ok(()));
assert_eq!(t.get(&[1]), Ok(None));
sourcepub fn set<K: AsRef<[u8]>>(
&self,
key: K,
value: Vec<u8>
) -> Result<Option<PinnedValue>, ()>
pub fn set<K: AsRef<[u8]>>(
&self,
key: K,
value: Vec<u8>
) -> Result<Option<PinnedValue>, ()>
Set a key to a new value, returning the old value if it was set.
sourcepub fn del<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<PinnedValue>, ()>
pub fn del<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<PinnedValue>, ()>
Delete a value, returning the last result if it existed.
Examples
let config = sled::ConfigBuilder::new().temporary(true).build();
let t = sled::Db::start(config).unwrap();
t.set(&[1], vec![1]);
assert_eq!(t.del(&*vec![1]).unwrap().unwrap(), vec![1]);
assert_eq!(t.del(&*vec![1]), Ok(None));
sourcepub fn merge<K: AsRef<[u8]>>(&self, key: K, value: Vec<u8>) -> Result<(), ()>
pub fn merge<K: AsRef<[u8]>>(&self, key: K, value: Vec<u8>) -> Result<(), ()>
Merge state directly into a given key’s value using the configured merge operator. This allows state to be written into a value directly, without any read-modify-write steps. Merge operators can be used to implement arbitrary data structures.
Panics
Calling merge
will panic if no merge operator has been
configured.
Examples
fn concatenate_merge(
_key: &[u8], // the key being merged
old_value: Option<&[u8]>, // the previous value, if one existed
merged_bytes: &[u8] // the new bytes being merged in
) -> Option<Vec<u8>> { // set the new value, return None to delete
let mut ret = old_value
.map(|ov| ov.to_vec())
.unwrap_or_else(|| vec![]);
ret.extend_from_slice(merged_bytes);
Some(ret)
}
let config = sled::ConfigBuilder::new()
.temporary(true)
.merge_operator(concatenate_merge)
.build();
let tree = sled::Db::start(config).unwrap();
let k = b"k1";
tree.set(k, vec![0]);
tree.merge(k, vec![1]);
tree.merge(k, vec![2]);
// assert_eq!(tree.get(k).unwrap().unwrap(), vec![0, 1, 2]);
// sets replace previously merged data,
// bypassing the merge function.
tree.set(k, vec![3]);
// assert_eq!(tree.get(k), Ok(Some(vec![3])));
// merges on non-present values will add them
tree.del(k);
tree.merge(k, vec![4]);
// assert_eq!(tree.get(k).unwrap().unwrap(), vec![4]);
sourcepub fn iter(&self) -> Iter<'_>ⓘNotable traits for Iter<'a>impl<'a> Iterator for Iter<'a> type Item = Result<(Vec<u8>, PinnedValue), ()>;
pub fn iter(&self) -> Iter<'_>ⓘNotable traits for Iter<'a>impl<'a> Iterator for Iter<'a> type Item = Result<(Vec<u8>, PinnedValue), ()>;
Create a double-ended iterator over the tuples of keys and values in this tree.
Examples
let config = sled::ConfigBuilder::new().temporary(true).build();
let t = sled::Db::start(config).unwrap();
t.set(&[1], vec![10]);
t.set(&[2], vec![20]);
t.set(&[3], vec![30]);
let mut iter = t.iter();
// assert_eq!(iter.next(), Some(Ok((vec![1], vec![10]))));
// assert_eq!(iter.next(), Some(Ok((vec![2], vec![20]))));
// assert_eq!(iter.next(), Some(Ok((vec![3], vec![30]))));
// assert_eq!(iter.next(), None);
sourcepub fn scan<K>(&self, key: K) -> Iter<'_>ⓘNotable traits for Iter<'a>impl<'a> Iterator for Iter<'a> type Item = Result<(Vec<u8>, PinnedValue), ()>;
where
K: AsRef<[u8]>,
pub fn scan<K>(&self, key: K) -> Iter<'_>ⓘNotable traits for Iter<'a>impl<'a> Iterator for Iter<'a> type Item = Result<(Vec<u8>, PinnedValue), ()>;
where
K: AsRef<[u8]>,
Create a double-ended iterator over tuples of keys and values, starting at the provided key.
Examples
let config = sled::ConfigBuilder::new()
.temporary(true)
.build();
let t = sled::Db::start(config).unwrap();
t.set(b"0", vec![0]).unwrap();
t.set(b"1", vec![10]).unwrap();
t.set(b"2", vec![20]).unwrap();
t.set(b"3", vec![30]).unwrap();
t.set(b"4", vec![40]).unwrap();
t.set(b"5", vec![50]).unwrap();
let mut r = t.scan(b"2");
assert_eq!(r.next().unwrap().unwrap().0, b"2");
assert_eq!(r.next().unwrap().unwrap().0, b"3");
assert_eq!(r.next().unwrap().unwrap().0, b"4");
assert_eq!(r.next().unwrap().unwrap().0, b"5");
assert_eq!(r.next(), None);
let mut r = t.scan(b"2").rev();
assert_eq!(r.next().unwrap().unwrap().0, b"2");
assert_eq!(r.next().unwrap().unwrap().0, b"1");
assert_eq!(r.next().unwrap().unwrap().0, b"0");
assert_eq!(r.next(), None);
sourcepub fn range<K, R>(&self, range: R) -> Iter<'_>ⓘNotable traits for Iter<'a>impl<'a> Iterator for Iter<'a> type Item = Result<(Vec<u8>, PinnedValue), ()>;
where
K: AsRef<[u8]>,
R: RangeBounds<K>,
pub fn range<K, R>(&self, range: R) -> Iter<'_>ⓘNotable traits for Iter<'a>impl<'a> Iterator for Iter<'a> type Item = Result<(Vec<u8>, PinnedValue), ()>;
where
K: AsRef<[u8]>,
R: RangeBounds<K>,
Create a double-ended iterator over tuples of keys and values, where the keys fall within the specified range.
Examples
let config = sled::ConfigBuilder::new()
.temporary(true)
.build();
let t = sled::Db::start(config).unwrap();
t.set(b"0", vec![0]).unwrap();
t.set(b"1", vec![10]).unwrap();
t.set(b"2", vec![20]).unwrap();
t.set(b"3", vec![30]).unwrap();
t.set(b"4", vec![40]).unwrap();
t.set(b"5", vec![50]).unwrap();
let start: &[u8] = b"2";
let end: &[u8] = b"4";
let mut r = t.range(start..end);
assert_eq!(r.next().unwrap().unwrap().0, b"2");
assert_eq!(r.next().unwrap().unwrap().0, b"3");
assert_eq!(r.next(), None);
let start = b"2".to_vec();
let end = b"4".to_vec();
let mut r = t.range(start..end).rev();
assert_eq!(r.next().unwrap().unwrap().0, b"3");
assert_eq!(r.next().unwrap().unwrap().0, b"2");
assert_eq!(r.next(), None);
sourcepub fn keys<K>(&self, key: K) -> Keys<'_>ⓘNotable traits for Keys<'a>impl<'a> Iterator for Keys<'a> type Item = Result<Vec<u8>, ()>;
where
K: AsRef<[u8]>,
pub fn keys<K>(&self, key: K) -> Keys<'_>ⓘNotable traits for Keys<'a>impl<'a> Iterator for Keys<'a> type Item = Result<Vec<u8>, ()>;
where
K: AsRef<[u8]>,
Create a double-ended iterator over keys, starting at the provided key.
Examples
let config = sled::ConfigBuilder::new().temporary(true).build();
let t = sled::Db::start(config).unwrap();
t.set(&[1], vec![10]);
t.set(&[2], vec![20]);
t.set(&[3], vec![30]);
let mut iter = t.scan(&*vec![2]);
// assert_eq!(iter.next(), Some(Ok(vec![2])));
// assert_eq!(iter.next(), Some(Ok(vec![3])));
// assert_eq!(iter.next(), None);
sourcepub fn values<K: AsRef<[u8]>>(&self, key: K) -> Values<'_>ⓘNotable traits for Values<'a>impl<'a> Iterator for Values<'a> type Item = Result<PinnedValue, ()>;
pub fn values<K: AsRef<[u8]>>(&self, key: K) -> Values<'_>ⓘNotable traits for Values<'a>impl<'a> Iterator for Values<'a> type Item = Result<PinnedValue, ()>;
Create a double-ended iterator over values, starting at the provided key.
Examples
let config = sled::ConfigBuilder::new().temporary(true).build();
let t = sled::Db::start(config).unwrap();
t.set(&[1], vec![10]);
t.set(&[2], vec![20]);
t.set(&[3], vec![30]);
let mut iter = t.scan(&*vec![2]);
// assert_eq!(iter.next(), Some(Ok(vec![20])));
// assert_eq!(iter.next(), Some(Ok(vec![30])));
// assert_eq!(iter.next(), None);