1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use super::super::errors::*;
use crate::{
    impls::{
        delta_mpt::node_ref_map::DeltaMptId, single_mpt_state::SingleMptState,
        state_manager::DeltaDbManager,
    },
    node_memory_manager::{
        DeltaMptsCacheAlgorithm, DeltaMptsNodeMemoryManager,
    },
    replicated_state::StateFilter,
    storage_db::DeltaDbManagerTrait,
    ArcDeltaDbWrapper, DeltaMpt, OpenableOnDemandOpenDeltaDbTrait,
};
use cfx_types::Space;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use parking_lot::Mutex;
use primitives::EpochId;
use std::{fs, path::PathBuf, sync::Arc};

const DB_NAME: &str = "single_mpt";

pub struct SingleMptStorageManager {
    node_memory_manager: Arc<DeltaMptsNodeMemoryManager>,
    mpt: Arc<DeltaMpt>,

    /// If it's None, we will keep data for both spaces.
    pub space: Option<Space>,
    /// The state is available from (including) this height.
    pub available_height: u64,

    pub genesis_hash: Mutex<EpochId>,
}

impl SingleMptStorageManager {
    pub fn new_arc(
        db_path: PathBuf, space: Option<Space>, available_height: u64,
        cache_start_size: u32, cache_size: u32, idle_size: u32,
    ) -> Arc<Self> {
        if !db_path.exists() {
            fs::create_dir_all(&db_path).expect("db path create error");
        }
        let db_manager = Arc::new(SingleMptDbManager {
            db_manager: DeltaDbManager::new(db_path)
                .expect("DeltaDb initialize error"),
            opened_mpt: Mutex::new(None),
        });
        let node_memory_manager = Arc::new(DeltaMptsNodeMemoryManager::new(
            cache_start_size,
            cache_size,
            idle_size,
            1_000_000, // unused
            DeltaMptsCacheAlgorithm::new(cache_size),
        ));
        let mpt = Arc::new(
            DeltaMpt::new_single_mpt(
                db_manager.clone(),
                node_memory_manager.clone(),
            )
            .expect("MPT initialization error"),
        );
        Arc::new(Self {
            node_memory_manager,
            mpt,
            space,
            available_height,
            // This is only used after `notify_genesis_hash` called.
            genesis_hash: Default::default(),
        })
    }

    pub fn get_state_by_epoch(
        &self, epoch: EpochId,
    ) -> Result<Option<SingleMptState>> {
        let root = self.mpt.get_root_node_ref_by_epoch(&epoch)?;
        match root {
            Some(Some(root)) => {
                Ok(Some(SingleMptState::new(self.mpt.clone(), root)))
            }
            _ => Ok(None),
        }
    }

    pub fn get_state_for_genesis(&self) -> Result<SingleMptState> {
        Ok(SingleMptState::new_empty(self.mpt.clone()))
    }

    pub fn get_state_filter(&self) -> Option<Box<dyn StateFilter>> {
        self.space
            .map(|space| Box::new(space) as Box<dyn StateFilter>)
    }

    pub fn contains_space(&self, space: &Option<Space>) -> bool {
        match (space, &self.space) {
            (_, None) => {
                // We keep the state in all spaces.
                true
            }
            (None, Some(_)) => {
                // We keep a part of states but all states are needed.
                false
            }
            (Some(need_space), Some(kept_space)) => need_space == kept_space,
        }
    }
}

struct SingleMptDbManager {
    db_manager: DeltaDbManager,
    opened_mpt: Mutex<Option<ArcDeltaDbWrapper>>,
}

impl OpenableOnDemandOpenDeltaDbTrait for SingleMptDbManager {
    fn open(&self, mpt_id: DeltaMptId) -> Result<ArcDeltaDbWrapper> {
        if mpt_id == 0 {
            let mut maybe_mpt = self.opened_mpt.lock();
            if maybe_mpt.is_some() {
                return Ok(maybe_mpt.as_ref().unwrap().clone());
            }
            let db = match self.db_manager.get_delta_db(DB_NAME)? {
                Some(db) => db,
                None => self.db_manager.new_empty_delta_db(DB_NAME)?,
            };
            let mpt = ArcDeltaDbWrapper {
                inner: Some(Arc::new(db)),
                lru: None,
                mpt_id,
            };
            *maybe_mpt = Some(mpt.clone());
            Ok(mpt)
        } else {
            Err(Error::DbNotExist.into())
        }
    }
}

impl MallocSizeOf for SingleMptStorageManager {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        let mut size = 0;
        size += self.node_memory_manager.size_of(ops);
        size
    }
}