Skip to content

Commit fa09be9

Browse files
authored
Merge pull request #108 from fjall-rs/2.5.0
2.5.0
2 parents 80a7b99 + 4e92845 commit fa09be9

File tree

18 files changed

+132
-93
lines changed

18 files changed

+132
-93
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "fjall"
33
description = "LSM-based key-value storage engine"
44
license = "MIT OR Apache-2.0"
5-
version = "2.4.4"
5+
version = "2.5.0"
66
edition = "2021"
77
rust-version = "1.74.0"
88
readme = "README.md"
@@ -28,7 +28,7 @@ bytes = ["lsm-tree/bytes"]
2828

2929
[dependencies]
3030
byteorder = "1.5.0"
31-
lsm-tree = { version = "2.4.0", default-features = false }
31+
lsm-tree = { version = "2.5.0", default-features = false }
3232
log = "0.4.21"
3333
std-semaphore = "0.1.0"
3434
tempfile = "3.10.1"

examples/permuterm/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ fn main() -> Result<()> {
8080

8181
for word in WORDS {
8282
for term in permuterm(word) {
83-
db.insert(format!("{term}#{word}"), word).unwrap();
83+
db.insert(format!("{term}#{word}"), *word).unwrap();
8484
}
8585
}
8686

examples/tx-blob-cas/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl Cas {
125125
let rc = self.decrement_ref_count(&mut tx, &prev_content_hash)?;
126126
if rc == 0 {
127127
// No more references
128-
tx.remove(&self.blobs, &prev_content_hash);
128+
tx.remove(&self.blobs, prev_content_hash);
129129
}
130130
}
131131

@@ -156,7 +156,7 @@ impl Cas {
156156
let rc = self.decrement_ref_count(&mut tx, &content_hash)?;
157157
if rc == 0 {
158158
// No more references
159-
tx.remove(&self.blobs, &content_hash);
159+
tx.remove(&self.blobs, content_hash);
160160
}
161161

162162
tx.commit()?;

examples/tx-mpmc-queue/src/main.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ fn main() -> fjall::Result<()> {
6363
// Something like SingleDelete https://github.com/facebook/rocksdb/wiki/Single-Delete
6464
// would be good for this type of workload
6565
if let Some((key, _)) = tx.first_key_value(&tasks)? {
66-
tx.remove(&tasks, &key);
66+
let task_id = std::str::from_utf8(&key).unwrap().to_owned();
67+
68+
tx.remove(&tasks, key);
6769

6870
tx.commit()?;
6971

70-
let task_id = std::str::from_utf8(&key).unwrap();
7172
println!("consumer {idx} completed task {task_id}");
7273

7374
counter.fetch_add(1, Relaxed);

examples/tx-partition-move/src/main.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ fn main() -> fjall::Result<()> {
3333
// Something like SingleDelete https://github.com/facebook/rocksdb/wiki/Single-Delete
3434
// would be good for this type of workload
3535
if let Some((key, value)) = tx.first_key_value(&src)? {
36-
tx.remove(&src, &key);
37-
tx.insert(&dst, &key, &value);
36+
let task_id = std::str::from_utf8(&key).unwrap().to_owned();
37+
38+
tx.remove(&src, key.clone());
39+
tx.insert(&dst, key, value);
3840

3941
tx.commit()?;
4042

41-
let task_id = std::str::from_utf8(&key).unwrap();
4243
println!("consumer {idx} moved {task_id}");
4344

4445
let ms = rng.gen_range(10..100);

examples/tx-ssi-mpmc-queue/src/main.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ fn main() -> fjall::Result<()> {
6565
// Something like SingleDelete https://github.com/facebook/rocksdb/wiki/Single-Delete
6666
// would be good for this type of workload
6767
if let Some((key, _)) = tx.first_key_value(&tasks)? {
68-
tx.remove(&tasks, &key);
68+
let task_id = std::str::from_utf8(&key).unwrap().to_owned();
69+
70+
tx.remove(&tasks, key);
6971

7072
if tx.commit()?.is_ok() {
7173
counter.fetch_add(1, Relaxed);
7274
}
7375

74-
let task_id = std::str::from_utf8(&key).unwrap();
7576
println!("consumer {idx} completed task {task_id}");
7677

7778
let ms = rng.gen_range(50..200);

examples/tx-ssi-partition-move/src/main.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ fn main() -> fjall::Result<()> {
3333
// Something like SingleDelete https://github.com/facebook/rocksdb/wiki/Single-Delete
3434
// would be good for this type of workload
3535
if let Some((key, value)) = tx.first_key_value(&src)? {
36-
tx.remove(&src, &key);
37-
tx.insert(&dst, &key, &value);
36+
let task_id = std::str::from_utf8(&key).unwrap().to_owned();
37+
38+
tx.remove(&src, key.clone());
39+
tx.insert(&dst, key, value);
3840

3941
tx.commit()?.ok();
4042

41-
let task_id = std::str::from_utf8(&key).unwrap();
4243
println!("consumer {idx} moved {task_id}");
4344

4445
let ms = rng.gen_range(10..100);

src/batch/mod.rs

+7-15
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod item;
66

77
use crate::{Keyspace, PartitionHandle, PersistMode};
88
use item::Item;
9-
use lsm_tree::{AbstractTree, ValueType};
9+
use lsm_tree::{AbstractTree, UserKey, UserValue, ValueType};
1010
use std::{collections::HashSet, sync::Arc};
1111

1212
/// Partition key (a.k.a. column family, locality group)
@@ -52,28 +52,20 @@ impl Batch {
5252
}
5353

5454
/// Inserts a key-value pair into the batch
55-
pub fn insert<K: AsRef<[u8]>, V: AsRef<[u8]>>(
55+
pub fn insert<K: Into<UserKey>, V: Into<UserValue>>(
5656
&mut self,
5757
p: &PartitionHandle,
5858
key: K,
5959
value: V,
6060
) {
61-
self.data.push(Item::new(
62-
p.name.clone(),
63-
key.as_ref(),
64-
value.as_ref(),
65-
ValueType::Value,
66-
));
61+
self.data
62+
.push(Item::new(p.name.clone(), key, value, ValueType::Value));
6763
}
6864

6965
/// Adds a tombstone marker for a key
70-
pub fn remove<K: AsRef<[u8]>>(&mut self, p: &PartitionHandle, key: K) {
71-
self.data.push(Item::new(
72-
p.name.clone(),
73-
key.as_ref(),
74-
vec![],
75-
ValueType::Tombstone,
76-
));
66+
pub fn remove<K: Into<UserKey>>(&mut self, p: &PartitionHandle, key: K) {
67+
self.data
68+
.push(Item::new(p.name.clone(), key, vec![], ValueType::Tombstone));
7769
}
7870

7971
/// Commits the batch to the [`Keyspace`] atomically

src/compaction/worker.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@
55
use super::manager::CompactionManager;
66
use crate::snapshot_tracker::SnapshotTracker;
77
use lsm_tree::AbstractTree;
8+
use std::sync::atomic::AtomicUsize;
89

910
/// Runs a single run of compaction.
10-
pub fn run(compaction_manager: &CompactionManager, snapshot_tracker: &SnapshotTracker) {
11+
pub fn run(
12+
compaction_manager: &CompactionManager,
13+
snapshot_tracker: &SnapshotTracker,
14+
compaction_counter: &AtomicUsize,
15+
) {
1116
let Some(item) = compaction_manager.pop() else {
1217
return;
1318
};
@@ -21,10 +26,12 @@ pub fn run(compaction_manager: &CompactionManager, snapshot_tracker: &SnapshotTr
2126

2227
// TODO: loop if there's more work to do
2328

29+
compaction_counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
2430
if let Err(e) = item
2531
.tree
2632
.compact(strategy.inner(), snapshot_tracker.get_seqno_safe_to_gc())
2733
{
2834
log::error!("Compaction failed: {e:?}");
2935
};
36+
compaction_counter.fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
3037
}

src/flush/worker.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ pub fn run(
152152
flush_manager.dequeue_tasks(partition.name.clone(), created_segments.len());
153153

154154
write_buffer_manager.free(memtables_size);
155-
compaction_manager.notify(partition);
155+
156+
for _ in 0..parallelism {
157+
compaction_manager.notify(partition.clone());
158+
}
156159
}
157160
}
158161
Err(e) => {

src/keyspace.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ pub struct KeyspaceInner {
7878
/// True if fsync failed
7979
pub(crate) is_poisoned: Arc<AtomicBool>,
8080

81+
/// Active compaction conter
82+
pub(crate) active_compaction_count: Arc<AtomicUsize>,
83+
8184
#[doc(hidden)]
8285
pub snapshot_tracker: SnapshotTracker,
8386
}
@@ -194,6 +197,14 @@ impl Keyspace {
194197
self.write_buffer_manager.get()
195198
}
196199

200+
/// Returns the number of active compactions currently running.
201+
#[doc(hidden)]
202+
#[must_use]
203+
pub fn active_compactions(&self) -> usize {
204+
self.active_compaction_count
205+
.load(std::sync::atomic::Ordering::Relaxed)
206+
}
207+
197208
/// Returns the amount of journals on disk.
198209
///
199210
/// # Examples
@@ -580,6 +591,7 @@ impl Keyspace {
580591
write_buffer_manager: WriteBufferManager::default(),
581592
is_poisoned: Arc::default(),
582593
snapshot_tracker: SnapshotTracker::default(),
594+
active_compaction_count: Arc::default(),
583595
};
584596

585597
let keyspace = Self(Arc::new(inner));
@@ -713,6 +725,7 @@ impl Keyspace {
713725
write_buffer_manager: WriteBufferManager::default(),
714726
is_poisoned: Arc::default(),
715727
snapshot_tracker: SnapshotTracker::default(),
728+
active_compaction_count: Arc::default(),
716729
};
717730

718731
// NOTE: Lastly, fsync .fjall marker, which contains the version
@@ -792,6 +805,7 @@ impl Keyspace {
792805
let stop_signal = self.stop_signal.clone();
793806
let thread_counter = self.active_background_threads.clone();
794807
let snapshot_tracker = self.snapshot_tracker.clone();
808+
let compaction_counter = self.active_compaction_count.clone();
795809

796810
thread_counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
797811

@@ -802,7 +816,11 @@ impl Keyspace {
802816
log::trace!("compaction: waiting for work");
803817
compaction_manager.wait_for();
804818

805-
crate::compaction::worker::run(&compaction_manager, &snapshot_tracker);
819+
crate::compaction::worker::run(
820+
&compaction_manager,
821+
&snapshot_tracker,
822+
&compaction_counter,
823+
);
806824
}
807825

808826
log::trace!("compaction thread: exiting because keyspace is dropping");

src/partition/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -866,15 +866,19 @@ impl PartitionHandle {
866866
/// # Errors
867867
///
868868
/// Will return `Err` if an IO error occurs.
869-
pub fn insert<K: AsRef<[u8]>, V: AsRef<[u8]>>(&self, key: K, value: V) -> crate::Result<()> {
869+
pub fn insert<K: Into<UserKey>, V: Into<UserValue>>(
870+
&self,
871+
key: K,
872+
value: V,
873+
) -> crate::Result<()> {
870874
use std::sync::atomic::Ordering;
871875

872876
if self.is_deleted.load(Ordering::Relaxed) {
873877
return Err(crate::Error::PartitionDeleted);
874878
}
875879

876-
let key = key.as_ref();
877-
let value = value.as_ref();
880+
let key = key.into();
881+
let value = value.into();
878882

879883
let mut journal_writer = self.journal.get_writer();
880884

@@ -885,7 +889,7 @@ impl PartitionHandle {
885889
return Err(crate::Error::Poisoned);
886890
}
887891

888-
journal_writer.write_raw(&self.name, key, value, lsm_tree::ValueType::Value, seqno)?;
892+
journal_writer.write_raw(&self.name, &key, &value, lsm_tree::ValueType::Value, seqno)?;
889893

890894
if !self.config.manual_journal_persist {
891895
journal_writer
@@ -943,14 +947,14 @@ impl PartitionHandle {
943947
/// # Errors
944948
///
945949
/// Will return `Err` if an IO error occurs.
946-
pub fn remove<K: AsRef<[u8]>>(&self, key: K) -> crate::Result<()> {
950+
pub fn remove<K: Into<UserKey>>(&self, key: K) -> crate::Result<()> {
947951
use std::sync::atomic::Ordering;
948952

949953
if self.is_deleted.load(Ordering::Relaxed) {
950954
return Err(crate::Error::PartitionDeleted);
951955
}
952956

953-
let key = key.as_ref();
957+
let key = key.into();
954958

955959
let mut journal_writer = self.journal.get_writer();
956960

@@ -961,7 +965,7 @@ impl PartitionHandle {
961965
return Err(crate::Error::Poisoned);
962966
}
963967

964-
journal_writer.write_raw(&self.name, key, &[], lsm_tree::ValueType::Tombstone, seqno)?;
968+
journal_writer.write_raw(&self.name, &key, &[], lsm_tree::ValueType::Tombstone, seqno)?;
965969

966970
if !self.config.manual_journal_persist {
967971
journal_writer

src/partition/options.rs

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl lsm_tree::coding::Decode for CreateOptions {
234234
l0_threshold,
235235
target_size,
236236
level_ratio,
237+
..Default::default()
237238
})
238239
}
239240
1 => {

src/tx/conflict_manager.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ impl ConflictManager {
3131
}
3232
}
3333

34-
pub fn mark_read(&mut self, partition: &PartitionKey, key: &Slice) {
35-
self.push_read(partition, Read::Single(key.clone()));
34+
pub fn mark_read(&mut self, partition: &PartitionKey, key: Slice) {
35+
self.push_read(partition, Read::Single(key));
3636
}
3737

38-
pub fn mark_conflict(&mut self, partition: &PartitionKey, key: &[u8]) {
38+
pub fn mark_conflict(&mut self, partition: &PartitionKey, key: Slice) {
3939
if let Some(tbl) = self.conflict_keys.get_mut(partition) {
40-
tbl.insert(key.into());
40+
tbl.insert(key);
4141
} else {
4242
self.conflict_keys
4343
.entry(partition.clone())
4444
.or_default()
45-
.insert(key.into());
45+
.insert(key);
4646
}
4747
}
4848

0 commit comments

Comments
 (0)