Skip to main content

forest/db/
db_impl.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use super::{
5    car::ManyCar,
6    parity_db::{GarbageCollectableDb, GarbageCollectableParityDb, ParityDb},
7    *,
8};
9use crate::{
10    db::car::ReloadableManyCar, libp2p_bitswap::*, prelude::*,
11    tool::subcommands::api_cmd::generate_test_snapshot::ReadOpsTrackingStore,
12};
13use ambassador::Delegate;
14use spire_enum::prelude::delegated_enum;
15use std::path::PathBuf;
16
17#[derive(Delegate)]
18#[delegate(SettingsStore)]
19#[delegate(EthMappingsStore)]
20#[delegate(HeaviestTipsetKeyProvider)]
21#[delegate(BitswapStoreRead)]
22#[delegate(BitswapStoreReadWrite)]
23#[delegated_enum(impl_conversions)]
24pub enum DbImpl {
25    ManyCarWithGarbageCollectableParityDb(Arc<ManyCar<Arc<GarbageCollectableParityDb>>>),
26    ManyCarWithMemoryDB(Arc<ManyCar<MemoryDB>>),
27    ManyCarParityDb(Arc<ManyCar<ParityDb>>),
28    Memory(Arc<MemoryDB>),
29    ReadOpsTrackingManyCarParityDb(Arc<ReadOpsTrackingStore<ManyCar<ParityDb>>>),
30}
31
32impl ShallowClone for DbImpl {
33    fn shallow_clone(&self) -> Self {
34        delegate_db_impl!(self.shallow_clone().into())
35    }
36}
37
38impl Blockstore for DbImpl {
39    fn get(&self, k: &Cid) -> anyhow::Result<Option<Vec<u8>>> {
40        delegate_db_impl!(self => |i| Blockstore::get(i, k))
41    }
42
43    fn put_keyed(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()> {
44        delegate_db_impl!(self => |i| Blockstore::put_keyed(i, k, block))
45    }
46
47    fn has(&self, k: &Cid) -> anyhow::Result<bool> {
48        delegate_db_impl!(self => |i| Blockstore::has(i, k))
49    }
50
51    #[allow(clippy::disallowed_types)]
52    fn put<D>(
53        &self,
54        mh_code: multihash_codetable::Code,
55        block: &fvm_ipld_blockstore::Block<D>,
56    ) -> anyhow::Result<Cid>
57    where
58        Self: Sized,
59        D: AsRef<[u8]>,
60    {
61        delegate_db_impl!(self => |i| Blockstore::put(i, mh_code, block))
62    }
63
64    #[allow(clippy::disallowed_types)]
65    fn put_many<D, I>(&self, blocks: I) -> anyhow::Result<()>
66    where
67        Self: Sized,
68        D: AsRef<[u8]>,
69        I: IntoIterator<Item = (multihash_codetable::Code, fvm_ipld_blockstore::Block<D>)>,
70    {
71        delegate_db_impl!(self => |i| Blockstore::put_many(i, blocks))
72    }
73
74    fn put_many_keyed<D, I>(&self, blocks: I) -> anyhow::Result<()>
75    where
76        Self: Sized,
77        D: AsRef<[u8]>,
78        I: IntoIterator<Item = (Cid, D)>,
79    {
80        delegate_db_impl!(self => |i| Blockstore::put_many_keyed(i, blocks))
81    }
82}
83
84impl GarbageCollectableDb for DbImpl {
85    fn reset_gc_columns(&self) -> anyhow::Result<()> {
86        match self {
87            Self::ManyCarWithGarbageCollectableParityDb(db) => db.reset_gc_columns(),
88            _ => anyhow::bail!("db is not garbage collectable"),
89        }
90    }
91}
92
93impl BlockstoreWriteOpsSubscribable for DbImpl {
94    fn subscribe_write_ops(
95        &self,
96    ) -> anyhow::Result<tokio::sync::broadcast::Receiver<Vec<(Cid, bytes::Bytes)>>> {
97        if let Self::ManyCarWithGarbageCollectableParityDb(db) = self {
98            db.subscribe_write_ops()
99        } else {
100            anyhow::bail!("not supported")
101        }
102    }
103
104    fn unsubscribe_write_ops(&self) {
105        if let Self::ManyCarWithGarbageCollectableParityDb(db) = self {
106            db.unsubscribe_write_ops();
107        }
108    }
109}
110
111impl ReloadableManyCar for DbImpl {
112    fn clear_and_reload_cars(&self, files: impl Iterator<Item = PathBuf>) -> anyhow::Result<()> {
113        match self {
114            Self::ManyCarWithGarbageCollectableParityDb(db) => db.clear_and_reload_cars(files),
115            Self::ManyCarWithMemoryDB(db) => db.clear_and_reload_cars(files),
116            Self::ManyCarParityDb(db) => db.clear_and_reload_cars(files),
117            _ => anyhow::bail!("not supported"),
118        }
119    }
120
121    fn heaviest_car_tipset(&self) -> anyhow::Result<Tipset> {
122        match self {
123            Self::ManyCarWithGarbageCollectableParityDb(db) => db.heaviest_car_tipset(),
124            Self::ManyCarWithMemoryDB(db) => db.heaviest_car_tipset(),
125            Self::ManyCarParityDb(db) => db.heaviest_car_tipset(),
126            _ => anyhow::bail!("not supported"),
127        }
128    }
129}