]> Untitled Git - bdk/commitdiff
feat(chain, file_store): add `is_empty` method to `PersistBackend` trait
author志宇 <hello@evanlinjin.me>
Wed, 25 Oct 2023 23:47:29 +0000 (07:47 +0800)
committer志宇 <hello@evanlinjin.me>
Wed, 15 Nov 2023 23:01:56 +0000 (07:01 +0800)
crates/chain/src/persist.rs
crates/file_store/src/store.rs

index 2ecc23c13c8522182c399828016316693ea13301..634e369e9a55932e8cfde428feafe3c7f4cb8aac 100644 (file)
@@ -80,6 +80,15 @@ pub trait PersistBackend<C> {
 
     /// Return the aggregate changeset `C` from persistence.
     fn load_from_persistence(&mut self) -> Result<C, Self::LoadError>;
+
+    /// Returns whether the persistence backend contains no data.
+    fn is_empty(&mut self) -> Result<bool, Self::LoadError>
+    where
+        C: Append,
+    {
+        self.load_from_persistence()
+            .map(|changeset| changeset.is_empty())
+    }
 }
 
 impl<C: Default> PersistBackend<C> for () {
@@ -94,4 +103,8 @@ impl<C: Default> PersistBackend<C> for () {
     fn load_from_persistence(&mut self) -> Result<C, Self::LoadError> {
         Ok(C::default())
     }
+
+    fn is_empty(&mut self) -> Result<bool, Self::LoadError> {
+        Ok(true)
+    }
 }
index a4aa2963ceb10aebea15a691ac8c524e63d484e2..fa73480e5202e4d675ef6ae4c90e3eb345546780 100644 (file)
@@ -37,6 +37,14 @@ where
         let (changeset, result) = self.aggregate_changesets();
         result.map(|_| changeset)
     }
+
+    fn is_empty(&mut self) -> Result<bool, Self::LoadError> {
+        let init_pos = self.db_file.stream_position()?;
+        let stream_len = self.db_file.seek(io::SeekFrom::End(0))?;
+        let magic_len = self.magic.len() as u64;
+        self.db_file.seek(io::SeekFrom::Start(init_pos))?;
+        Ok(stream_len == magic_len)
+    }
 }
 
 impl<'a, C> Store<'a, C>
@@ -182,6 +190,19 @@ mod test {
     #[derive(Debug)]
     struct TestTracker;
 
+    #[test]
+    fn is_empty() {
+        let mut file = NamedTempFile::new().unwrap();
+        file.write_all(&TEST_MAGIC_BYTES).expect("should write");
+
+        let mut db = Store::<TestChangeSet>::new(&TEST_MAGIC_BYTES, file.reopen().unwrap())
+            .expect("must open");
+        assert!(db.is_empty().expect("must read"));
+        db.write_changes(&vec!["hello".to_string(), "world".to_string()])
+            .expect("must write");
+        assert!(!db.is_empty().expect("must read"));
+    }
+
     #[test]
     fn new_fails_if_file_is_too_short() {
         let mut file = NamedTempFile::new().unwrap();