1use crate::stats::StateUsageStats;
22use sp_core::storage::ChildInfo;
23use sp_runtime::{
24 traits::{Block as BlockT, HashingFor},
25 StateVersion,
26};
27use sp_state_machine::{
28 backend::{AsTrieBackend, Backend as StateBackend},
29 BackendTransaction, IterArgs, StorageIterator, StorageKey, StorageValue, TrieBackend,
30};
31use sp_trie::MerkleValue;
32use std::sync::Arc;
33
34pub struct RecordStatsState<S, B: BlockT> {
36 usage: StateUsageStats,
38 overlay_stats: sp_state_machine::StateMachineStats,
40 state: S,
42 block_hash: Option<B::Hash>,
44 state_usage: Arc<StateUsageStats>,
46}
47
48impl<S, B: BlockT> std::fmt::Debug for RecordStatsState<S, B> {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 write!(f, "Block {:?}", self.block_hash)
51 }
52}
53
54impl<S, B: BlockT> Drop for RecordStatsState<S, B> {
55 fn drop(&mut self) {
56 self.state_usage.merge_sm(self.usage.take());
57 }
58}
59
60impl<S: StateBackend<HashingFor<B>>, B: BlockT> RecordStatsState<S, B> {
61 pub(crate) fn new(
63 state: S,
64 block_hash: Option<B::Hash>,
65 state_usage: Arc<StateUsageStats>,
66 ) -> Self {
67 RecordStatsState {
68 usage: StateUsageStats::new(),
69 overlay_stats: sp_state_machine::StateMachineStats::default(),
70 state,
71 block_hash,
72 state_usage,
73 }
74 }
75}
76
77pub struct RawIter<S, B>
78where
79 S: StateBackend<HashingFor<B>>,
80 B: BlockT,
81{
82 inner: <S as StateBackend<HashingFor<B>>>::RawIter,
83}
84
85impl<S, B> StorageIterator<HashingFor<B>> for RawIter<S, B>
86where
87 S: StateBackend<HashingFor<B>>,
88 B: BlockT,
89{
90 type Backend = RecordStatsState<S, B>;
91 type Error = S::Error;
92
93 fn next_key(&mut self, backend: &Self::Backend) -> Option<Result<StorageKey, Self::Error>> {
94 self.inner.next_key(&backend.state)
95 }
96
97 fn next_pair(
98 &mut self,
99 backend: &Self::Backend,
100 ) -> Option<Result<(StorageKey, StorageValue), Self::Error>> {
101 self.inner.next_pair(&backend.state)
102 }
103
104 fn was_complete(&self) -> bool {
105 self.inner.was_complete()
106 }
107}
108
109impl<S: StateBackend<HashingFor<B>>, B: BlockT> StateBackend<HashingFor<B>>
110 for RecordStatsState<S, B>
111{
112 type Error = S::Error;
113 type TrieBackendStorage = S::TrieBackendStorage;
114 type RawIter = RawIter<S, B>;
115
116 fn storage(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
117 let value = self.state.storage(key)?;
118 self.usage.tally_key_read(key, value.as_ref(), false);
119 Ok(value)
120 }
121
122 fn storage_hash(&self, key: &[u8]) -> Result<Option<B::Hash>, Self::Error> {
123 self.state.storage_hash(key)
124 }
125
126 fn child_storage(
127 &self,
128 child_info: &ChildInfo,
129 key: &[u8],
130 ) -> Result<Option<Vec<u8>>, Self::Error> {
131 let key = (child_info.storage_key().to_vec(), key.to_vec());
132 let value = self.state.child_storage(child_info, &key.1)?;
133
134 let value = self.usage.tally_child_key_read(&key, value, false);
136
137 Ok(value)
138 }
139
140 fn child_storage_hash(
141 &self,
142 child_info: &ChildInfo,
143 key: &[u8],
144 ) -> Result<Option<B::Hash>, Self::Error> {
145 self.state.child_storage_hash(child_info, key)
146 }
147
148 fn closest_merkle_value(
149 &self,
150 key: &[u8],
151 ) -> Result<Option<MerkleValue<B::Hash>>, Self::Error> {
152 self.state.closest_merkle_value(key)
153 }
154
155 fn child_closest_merkle_value(
156 &self,
157 child_info: &ChildInfo,
158 key: &[u8],
159 ) -> Result<Option<MerkleValue<B::Hash>>, Self::Error> {
160 self.state.child_closest_merkle_value(child_info, key)
161 }
162
163 fn exists_storage(&self, key: &[u8]) -> Result<bool, Self::Error> {
164 self.state.exists_storage(key)
165 }
166
167 fn exists_child_storage(
168 &self,
169 child_info: &ChildInfo,
170 key: &[u8],
171 ) -> Result<bool, Self::Error> {
172 self.state.exists_child_storage(child_info, key)
173 }
174
175 fn next_storage_key(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
176 self.state.next_storage_key(key)
177 }
178
179 fn next_child_storage_key(
180 &self,
181 child_info: &ChildInfo,
182 key: &[u8],
183 ) -> Result<Option<Vec<u8>>, Self::Error> {
184 self.state.next_child_storage_key(child_info, key)
185 }
186
187 fn storage_root<'a>(
188 &self,
189 delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
190 state_version: StateVersion,
191 ) -> (B::Hash, BackendTransaction<HashingFor<B>>) {
192 self.state.storage_root(delta, state_version)
193 }
194
195 fn child_storage_root<'a>(
196 &self,
197 child_info: &ChildInfo,
198 delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
199 state_version: StateVersion,
200 ) -> (B::Hash, bool, BackendTransaction<HashingFor<B>>) {
201 self.state.child_storage_root(child_info, delta, state_version)
202 }
203
204 fn raw_iter(&self, args: IterArgs) -> Result<Self::RawIter, Self::Error> {
205 self.state.raw_iter(args).map(|inner| RawIter { inner })
206 }
207
208 fn register_overlay_stats(&self, stats: &sp_state_machine::StateMachineStats) {
209 self.overlay_stats.add(stats);
210 }
211
212 fn usage_info(&self) -> sp_state_machine::UsageInfo {
213 let mut info = self.usage.take();
214 info.include_state_machine_states(&self.overlay_stats);
215 info
216 }
217}
218
219impl<S: StateBackend<HashingFor<B>> + AsTrieBackend<HashingFor<B>>, B: BlockT>
220 AsTrieBackend<HashingFor<B>> for RecordStatsState<S, B>
221{
222 type TrieBackendStorage = <S as AsTrieBackend<HashingFor<B>>>::TrieBackendStorage;
223
224 fn as_trie_backend(&self) -> &TrieBackend<Self::TrieBackendStorage, HashingFor<B>> {
225 self.state.as_trie_backend()
226 }
227}