summary refs log tree commit diff
path: root/ripple/fossil
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2022-04-28 21:40:08 +0000
committeredef <edef@unfathomable.blue>2022-04-28 21:40:08 +0000
commitb5a97ad86e81e3bd8ff325ea991459c5f262b245 (patch)
tree5802a3096c288c36d5539a6026f82df5f5fd4f80 /ripple/fossil
parentc08692df2c43c4c4e71691b83f43e4012aa6315e (diff)
ripple/fossil: ensure durability of add_path
sled doesn't actually promise not to eat your data until you invoke
flush. This is observable under normal circumstances as add_path
occasionally just not committing anything to the store.

While we're at it, ensure we're syncing the chunks file data to disk,
so the database *might* actually be consistent. We're not going for
full crash-correctness yet, mostly for performance and complexity
reasons.

Change-Id: I6cc69a013dc18cd50df26e73801b185de596565c
Diffstat (limited to 'ripple/fossil')
-rw-r--r--ripple/fossil/src/lib.rs15
1 files changed, 14 insertions, 1 deletions
diff --git a/ripple/fossil/src/lib.rs b/ripple/fossil/src/lib.rs
index 4cea16a..c79105c 100644
--- a/ripple/fossil/src/lib.rs
+++ b/ripple/fossil/src/lib.rs
@@ -66,6 +66,20 @@ impl Store {
 
 	pub fn add_path(&self, path: impl AsRef<Path>) -> Node {
 		let path = path.as_ref();
+		let node = self.add_path_inner(path);
+
+		// NOTE: sled *can* flush without us explicitly asking for it, so it's
+		// possible for the store to end up containing pointers to chunks that
+		// aren't fsynced yet. The easiest fix is to always `chunks_file.sync_data()`
+		// before we write anything to the database, but that's kind of a performance hazard.
+		// TODO(edef): keep pending and known-durable blobs/chunks separate in the database
+		self.chunks_file.borrow_mut().sync_data().unwrap();
+		self.meta.flush().unwrap();
+
+		node
+	}
+
+	fn add_path_inner(&self, path: &Path) -> Node {
 		let meta = fs::symlink_metadata(path).unwrap();
 
 		match meta.file_type() {
@@ -151,7 +165,6 @@ impl Store {
 			buf
 		};
 
-		// TODO(edef): figure out fsync for durability
 		(&self.blobs, &self.chunks, &self.meta)
 			.transaction(|(blobs, chunks, meta)| {
 				chunks.apply_batch(&batch)?;