diff --git a/Cargo.lock b/Cargo.lock index 84ddf7bda..23c41b274 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,6 +329,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "chacha20" version = "0.5.0" @@ -405,6 +411,12 @@ dependencies = [ "bitflags", ] +[[package]] +name = "const_fn" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -417,6 +429,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "criterion" version = "0.3.3" @@ -459,7 +480,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -469,8 +490,8 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-epoch 0.8.2", + "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -481,11 +502,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg", - "cfg-if", - "crossbeam-utils", + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset", + "memoffset 0.5.6", + "scopeguard", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" +dependencies = [ + "cfg-if 1.0.0", + "const_fn", + "crossbeam-utils 0.8.1", + "lazy_static", + "memoffset 0.6.1", "scopeguard", ] @@ -496,7 +531,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", "lazy_static", ] @@ -732,7 +778,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", "winapi 0.3.9", @@ -911,6 +957,15 @@ dependencies = [ "pin-project", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder 1.3.4", +] + [[package]] name = "gcc" version = "0.3.55" @@ -964,7 +1019,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -1169,7 +1224,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -1217,12 +1272,14 @@ dependencies = [ "libp2p", "multibase", "multihash", + "once_cell", "prost", "prost-build", "rand 0.7.3", "serde", "serde_json", "sha2 0.9.1", + "sled", "tempfile", "thiserror", "tokio", @@ -1365,9 +1422,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.79" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" [[package]] name = "libp2p" @@ -1675,7 +1732,7 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -1714,6 +1771,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -1736,7 +1802,7 @@ version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", @@ -1830,7 +1896,7 @@ version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] @@ -1872,9 +1938,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "oorandom" @@ -1901,7 +1967,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 0.1.10", "foreign-types", "lazy_static", "libc", @@ -1966,7 +2032,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.0.3", "libc", "redox_syscall", @@ -1980,7 +2046,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi 0.1.0", "instant", "libc", @@ -2070,7 +2136,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5884790f1ce3553ad55fec37b5aaac5882e0e845a2612df744d6c85c9bf046c" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "universal-hash", ] @@ -2299,7 +2365,7 @@ checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils", + "crossbeam-utils 0.7.2", "lazy_static", "num_cpus", ] @@ -2388,7 +2454,7 @@ dependencies = [ "base64", "blake2b_simd", "constant_time_eq", - "crossbeam-utils", + "crossbeam-utils 0.7.2", ] [[package]] @@ -2531,7 +2597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 0.1.10", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", @@ -2556,7 +2622,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 0.1.10", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", @@ -2595,6 +2661,22 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "sled" +version = "0.34.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc" +dependencies = [ + "crc32fast", + "crossbeam-epoch 0.9.1", + "crossbeam-utils 0.8.1", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.0", +] + [[package]] name = "smallvec" version = "1.4.2" @@ -2625,7 +2707,7 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", "winapi 0.3.9", @@ -2729,7 +2811,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand 0.7.3", "redox_syscall", @@ -2858,7 +2940,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "log", "pin-project-lite", "tracing-core", @@ -3145,7 +3227,7 @@ version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "wasm-bindgen-macro", ] @@ -3170,7 +3252,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "js-sys", "wasm-bindgen", "web-sys", diff --git a/Cargo.toml b/Cargo.toml index 619b9a21a..d64929458 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ version = "0.2.1" [features] default = [] +sled_data_store = [] test_go_interop = [] test_js_interop = [] @@ -42,6 +43,8 @@ tracing-futures = { default-features = false, features = ["std", "futures-03"], void = { default-features = false, version = "1.0" } fs2 = "0.4.3" tempfile = "3.1.0" +sled = "0.34" +once_cell = "1.5.2" [target.'cfg(windows)'.dependencies] # required for DNS resolution diff --git a/src/lib.rs b/src/lib.rs index 6e4cf7af4..3f6b196d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,9 @@ impl IpfsTypes for T {} pub struct Types; impl RepoTypes for Types { type TBlockStore = repo::fs::FsBlockStore; + #[cfg(feature = "sled_data_store")] + type TDataStore = repo::kv::KvDataStore; + #[cfg(not(feature = "sled_data_store"))] type TDataStore = repo::fs::FsDataStore; type TLock = repo::fs::FsLock; } diff --git a/src/repo/kv.rs b/src/repo/kv.rs new file mode 100644 index 000000000..b47c46615 --- /dev/null +++ b/src/repo/kv.rs @@ -0,0 +1,380 @@ +use super::{Column, DataStore}; +use crate::error::Error; +use crate::repo::{PinKind, PinMode, PinStore, References}; +use async_trait::async_trait; +use cid::{self, Cid}; +use futures::stream::{StreamExt, TryStreamExt}; +use once_cell::sync::OnceCell; +use sled::{self, Config as DbConfig, Db, Mode as DbMode}; +use std::collections::BTreeSet; +use std::convert::Into; +use std::path::PathBuf; +use std::str::{self, FromStr}; +use tracing_futures::Instrument; + +#[derive(Debug)] +pub struct KvDataStore { + path: PathBuf, + // it is a trick for not modifying the Data:init + db: OnceCell, +} + +impl KvDataStore { + fn _put(&self, key: &str, value: &str) -> Result<(), Error> { + let db = self.get_db(); + + let _ = db.insert(key, value)?; + + Ok(()) + } + + fn _remove(&self, key: &str) -> Result<(), Error> { + let db = self.get_db(); + + match db.remove(key) { + Ok(_) => Ok(()), + Err(e) => Err(e.into()), + } + } + + fn _apply_batch(&self, batch: sled::Batch) -> Result<(), Error> { + let db = self.get_db(); + + Ok(db.apply_batch(batch)?) + } + + fn get_db(&self) -> &Db { + self.db.get().unwrap() + } +} + +#[async_trait] +impl DataStore for KvDataStore { + fn new(root: PathBuf) -> KvDataStore { + KvDataStore { + path: root, + db: Default::default(), + } + } + + async fn init(&self) -> Result<(), Error> { + let config = DbConfig::new(); + + let db = config + .mode(DbMode::HighThroughput) + .path(self.path.as_path()) + .open()?; + + match self.db.set(db) { + Ok(()) => Ok(()), + Err(_) => Err(anyhow::anyhow!("failed to init sled")), + } + } + + async fn open(&self) -> Result<(), Error> { + Ok(()) + } + + /// Checks if a key is present in the datastore. + async fn contains(&self, _col: Column, _key: &[u8]) -> Result { + Err(anyhow::anyhow!("not implemented")) + } + + /// Returns the value associated with a key from the datastore. + async fn get(&self, _col: Column, _key: &[u8]) -> Result>, Error> { + Err(anyhow::anyhow!("not implemented")) + } + + /// Puts the value under the key in the datastore. + async fn put(&self, _col: Column, _key: &[u8], _value: &[u8]) -> Result<(), Error> { + Err(anyhow::anyhow!("not implemented")) + } + + /// Removes a key-value pair from the datastore. + async fn remove(&self, _col: Column, _key: &[u8]) -> Result<(), Error> { + Err(anyhow::anyhow!("not implemented")) + } + + /// Wipes the datastore. + async fn wipe(&self) { + todo!() + } +} + +#[async_trait] +impl PinStore for KvDataStore { + async fn is_pinned(&self, block: &Cid) -> Result { + is_pinned(self, block) + } + + async fn insert_direct_pin(&self, target: &Cid) -> Result<(), Error> { + let already_pinned = get_pinned_mode(self, target)?; + + let mut batch = sled::Batch::default(); + + match already_pinned { + Some(PinMode::Direct) => return Ok(()), + Some(PinMode::Recursive) => return Err(anyhow::anyhow!("already pinned recursively")), + Some(PinMode::Indirect) => { + let pin_key = get_pin_key(target, &PinMode::Indirect); + batch.remove(pin_key.as_str()); + } + None => {} + } + + let direct_key = get_pin_key(target, &PinMode::Direct); + + batch.insert(direct_key.as_str(), ""); + + Ok(self._apply_batch(batch)?) + } + + async fn insert_recursive_pin( + &self, + target: &Cid, + referenced: References<'_>, + ) -> Result<(), Error> { + let set = referenced.try_collect::>().await?; + + let mut batch = sled::Batch::default(); + let already_pinned = get_pinned_mode(self, target)?; + + match already_pinned { + Some(PinMode::Recursive) => return Ok(()), + Some(mode @ PinMode::Direct) | Some(mode @ PinMode::Indirect) => { + let key = get_pin_key(target, &mode); + batch.remove(key.as_str()); + } + None => {} + } + + let recursive_key = get_pin_key(target, &PinMode::Recursive); + batch.insert(recursive_key.as_str(), ""); + + for cid in &set { + let indirect_key = get_pin_key(cid, &PinMode::Indirect); + + let is_already_pinned = is_pinned(self, cid); + + if let Ok(true) = is_already_pinned { + continue; + } + + // value is for get information like "Qmd9WDTA2Kph4MKiDDiaZdiB4HJQpKcxjnJQfQmM5rHhYK indirect through QmXr1XZBg1CQv17BPvSWRmM7916R6NLL7jt19rhCPdVhc5" + batch.insert(indirect_key.as_str(), target.to_string().as_str()); + } + + Ok(self._apply_batch(batch)?) + } + + async fn remove_direct_pin(&self, target: &Cid) -> Result<(), Error> { + if is_not_pinned_or_pinned_indirectly(self, target)? { + return Err(anyhow::anyhow!("not pinned or pinned indirectly")); + } + + let key = get_pin_key(target, &PinMode::Direct); + + Ok(self._remove(&key)?) + } + + async fn remove_recursive_pin( + &self, + target: &Cid, + referenced: References<'_>, + ) -> Result<(), Error> { + if is_not_pinned_or_pinned_indirectly(self, target)? { + return Err(anyhow::anyhow!("not pinned or pinned indirectly")); + } + + let set = referenced.try_collect::>().await?; + + let mut batch = sled::Batch::default(); + + let recursive_key = get_pin_key(target, &PinMode::Recursive); + + batch.remove(recursive_key.as_str()); + + for cid in &set { + let already_pinned = get_pinned_mode(self, cid)?; + + match already_pinned { + Some(PinMode::Recursive) | Some(PinMode::Direct) => continue, // this should be unreachable + Some(PinMode::Indirect) => { + let indirect_key = get_pin_key(cid, &PinMode::Indirect); + batch.remove(indirect_key.as_str()); + } + None => {} + } + } + + Ok(self._apply_batch(batch)?) + } + + async fn list( + &self, + expected_mode: Option, + ) -> futures::stream::BoxStream<'static, Result<(Cid, PinMode), Error>> { + let db = self.get_db(); + + // the minimum cid of version 0 + let min_key = "pin.0.0000000000000000000000000000000000000000000000"; + assert_eq!(min_key.len(), 52); + + let iter = db.range(min_key..); + let mut all_keys: Vec = vec![]; + + for item in iter.filter(|item| item.is_ok()) { + let (raw_key, _) = item.unwrap(); + let key = String::from_utf8_lossy(raw_key.as_ref()); + + if !key.starts_with("pin.") { + continue; + } + + all_keys.push(key.to_owned().to_string()); + } + + let st = async_stream::try_stream! { + for key in all_keys.iter() { + let cid_str_with_prefix = &key[4..]; + let cid_str = &key[6..]; + + let pin_mode = match cid_str_with_prefix { + _ if cid_str_with_prefix.starts_with("d") => { + PinMode::Direct + }, + + _ if cid_str_with_prefix.starts_with("r") => { + PinMode::Recursive + } + + _ if cid_str_with_prefix.starts_with("i") => { + PinMode::Indirect + } + + _ => continue, + }; + + match Cid::from_str(cid_str) { + Ok(cid) => { + match expected_mode { + Some(ref expected) => if pin_mode == *expected { + yield (cid, pin_mode); + } + Some(_) => {} + None => yield (cid, pin_mode), + } + } + + Err(_) => {} + } + } + }; + + st.in_current_span().boxed() + } + + async fn query( + &self, + ids: Vec, + requirement: Option, + ) -> Result)>, Error> { + let mut res = Vec::<(Cid, PinKind)>::new(); + + let pin_mode_matches = |pin_mode: &PinMode| match requirement { + Some(ref expected) => *expected == *pin_mode, + None => true, + }; + + let db = self.get_db(); + + for id in ids.iter() { + match get_pinned_mode(self, id) { + Ok(Some(pin_mode)) => { + if !pin_mode_matches(&pin_mode) { + continue; + } + + match pin_mode { + PinMode::Direct => res.push((id.clone(), PinKind::Direct)), + PinMode::Recursive => res.push((id.clone(), PinKind::Recursive(0))), + PinMode::Indirect => { + let pin_key = get_pin_key(id, &PinMode::Indirect); + + match db.get(pin_key.as_str()) { + Ok(Some(indirect_from_raw)) => { + let indirect_from_str = + str::from_utf8(indirect_from_raw.as_ref())?; + + match Cid::from_str(indirect_from_str) { + Ok(indirect_from_cid) => res.push(( + id.clone(), + PinKind::IndirectFrom(indirect_from_cid), + )), + Err(_) => { + warn!("invalid indirect from cid of {}", id); + continue; + } + } + } + Ok(None) => {} + Err(e) => return Err(e.into()), + } + } + } + } + Ok(None) => {} + Err(e) => return Err(e), + } + } + + Ok(res) + } +} + +fn pin_mode_literal(pin_mode: &PinMode) -> &'static str { + match pin_mode { + PinMode::Direct => "d", + PinMode::Indirect => "i", + PinMode::Recursive => "r", + } +} + +fn get_pin_key(cid: &Cid, pin_mode: &PinMode) -> String { + format!("pin.{}.{}", pin_mode_literal(pin_mode), cid) +} + +fn get_pinned_mode(kv_db: &KvDataStore, block: &Cid) -> Result, Error> { + for mode in &[PinMode::Direct, PinMode::Recursive, PinMode::Indirect] { + let key = get_pin_key(block, mode); + + let db = kv_db.get_db(); + + match db.get(key.as_str()) { + Ok(Some(_)) => return Ok(Some(mode.clone())), + Ok(None) => {} + Err(e) => return Err(e.into()), + } + } + + Ok(None) +} + +fn is_pinned(db: &KvDataStore, block: &Cid) -> Result { + match get_pinned_mode(db, block) { + Ok(Some(_)) => Ok(true), + Ok(None) => Ok(false), + Err(e) => Err(e), + } +} + +fn is_not_pinned_or_pinned_indirectly(db: &KvDataStore, block: &Cid) -> Result { + match get_pinned_mode(db, block) { + Ok(Some(PinMode::Indirect)) | Ok(None) => Ok(true), + Ok(_) => Ok(false), + Err(e) => Err(e), + } +} + +#[cfg(test)] +crate::pinstore_interface_tests!(common_tests, crate::repo::kv::KvDataStore::new); diff --git a/src/repo/mod.rs b/src/repo/mod.rs index 57b894131..30006b157 100644 --- a/src/repo/mod.rs +++ b/src/repo/mod.rs @@ -25,6 +25,7 @@ use std::{error, fmt, io}; mod common_tests; pub mod fs; +pub mod kv; pub mod mem; /// Consolidates `BlockStore` and `DataStore` into a representation of storage.