1
1
use crate :: columns:: DBKeyType ;
2
2
use crate :: refcount:: add_positive_refcount;
3
- use crate :: { DBCol , DBTransaction , Database , Store } ;
3
+ use crate :: trie:: TrieRefcountChange ;
4
+ use crate :: { DBCol , DBTransaction , Database , Store , TrieChanges } ;
4
5
5
6
use borsh:: BorshDeserialize ;
7
+ use near_primitives:: shard_layout:: ShardLayout ;
6
8
use near_primitives:: types:: BlockHeight ;
7
9
use std:: collections:: HashMap ;
8
10
use std:: io;
@@ -38,13 +40,14 @@ struct StoreWithCache<'a> {
38
40
pub fn update_cold_db (
39
41
cold_db : & dyn Database ,
40
42
hot_store : & Store ,
43
+ shard_layout : & ShardLayout ,
41
44
height : & BlockHeight ,
42
45
) -> io:: Result < ( ) > {
43
46
let _span = tracing:: debug_span!( target: "store" , "update cold db" , height = height) ;
44
47
45
48
let mut store_with_cache = StoreWithCache { store : hot_store, cache : StoreCache :: new ( ) } ;
46
49
47
- let key_type_to_keys = get_keys_from_store ( & mut store_with_cache, height) ?;
50
+ let key_type_to_keys = get_keys_from_store ( & mut store_with_cache, shard_layout , height) ?;
48
51
for col in DBCol :: iter ( ) {
49
52
if col. is_cold ( ) {
50
53
copy_from_store (
@@ -116,6 +119,10 @@ pub fn test_cold_genesis_update(cold_db: &dyn Database, hot_store: &Store) -> io
116
119
Ok ( ( ) )
117
120
}
118
121
122
+ pub fn test_get_store_reads ( column : DBCol ) -> u64 {
123
+ crate :: metrics:: COLD_MIGRATION_READS . with_label_values ( & [ <& str >:: from ( column) ] ) . get ( )
124
+ }
125
+
119
126
/// Returns HashMap from DBKeyType to possible keys of that type for provided height.
120
127
/// Only constructs keys for key types that are used in cold columns.
121
128
/// The goal is to capture all changes to db made during production of the block at provided height.
@@ -124,6 +131,7 @@ pub fn test_cold_genesis_update(cold_db: &dyn Database, hot_store: &Store) -> io
124
131
/// But for TransactionHash, for example, it is all of the tx hashes in that block.
125
132
fn get_keys_from_store (
126
133
store : & mut StoreWithCache ,
134
+ shard_layout : & ShardLayout ,
127
135
height : & BlockHeight ,
128
136
) -> io:: Result < HashMap < DBKeyType , Vec < StoreKey > > > {
129
137
let mut key_type_to_keys = HashMap :: new ( ) ;
@@ -136,6 +144,35 @@ fn get_keys_from_store(
136
144
key_type,
137
145
match key_type {
138
146
DBKeyType :: BlockHash => vec ! [ block_hash_key. clone( ) ] ,
147
+ DBKeyType :: ShardUId => shard_layout
148
+ . get_shard_uids ( )
149
+ . iter ( )
150
+ . map ( |uid| uid. to_bytes ( ) . to_vec ( ) )
151
+ . collect ( ) ,
152
+ // TODO: don't write values of State column to cache. Write them directly to colddb.
153
+ DBKeyType :: TrieNodeOrValueHash => {
154
+ let mut keys = vec ! [ ] ;
155
+ for shard_uid in shard_layout. get_shard_uids ( ) {
156
+ let shard_uid_key = shard_uid. to_bytes ( ) ;
157
+
158
+ debug_assert_eq ! (
159
+ DBCol :: TrieChanges . key_type( ) ,
160
+ & [ DBKeyType :: BlockHash , DBKeyType :: ShardUId ]
161
+ ) ;
162
+ let trie_changes_option: Option < TrieChanges > = store. get_ser (
163
+ DBCol :: TrieChanges ,
164
+ & join_two_keys ( & block_hash_key, & shard_uid_key) ,
165
+ ) ?;
166
+
167
+ if let Some ( trie_changes) = trie_changes_option {
168
+ for op in trie_changes. insertions ( ) {
169
+ store. insert_state_to_cache_from_op ( op, & shard_uid_key) ;
170
+ keys. push ( op. hash ( ) . as_bytes ( ) . to_vec ( ) ) ;
171
+ }
172
+ }
173
+ }
174
+ keys
175
+ }
139
176
_ => {
140
177
vec ! [ ]
141
178
}
@@ -146,6 +183,10 @@ fn get_keys_from_store(
146
183
Ok ( key_type_to_keys)
147
184
}
148
185
186
+ pub fn join_two_keys ( prefix_key : & [ u8 ] , suffix_key : & [ u8 ] ) -> StoreKey {
187
+ [ prefix_key, suffix_key] . concat ( )
188
+ }
189
+
149
190
/// Returns all possible keys for a column with key represented by a specific sequence of key types.
150
191
/// `key_type_to_value` -- result of `get_keys_from_store`, mapping from KeyType to all possible keys of that type.
151
192
/// `key_types` -- description of a final key, what sequence of key types forms a key, result of `DBCol::key_type`.
@@ -179,9 +220,7 @@ fn combine_keys_with_stop(
179
220
let mut result_keys = vec ! [ ] ;
180
221
for prefix_key in & all_smaller_keys {
181
222
for suffix_key in & key_type_to_keys[ last_kt] {
182
- let mut new_key = prefix_key. clone ( ) ;
183
- new_key. extend ( suffix_key) ;
184
- result_keys. push ( new_key) ;
223
+ result_keys. push ( join_two_keys ( prefix_key, suffix_key) ) ;
185
224
}
186
225
}
187
226
result_keys
@@ -202,6 +241,7 @@ where
202
241
impl StoreWithCache < ' _ > {
203
242
pub fn get ( & mut self , column : DBCol , key : & [ u8 ] ) -> io:: Result < StoreValue > {
204
243
if !self . cache . contains_key ( & ( column, key. to_vec ( ) ) ) {
244
+ crate :: metrics:: COLD_MIGRATION_READS . with_label_values ( & [ <& str >:: from ( column) ] ) . inc ( ) ;
205
245
self . cache . insert (
206
246
( column. clone ( ) , key. to_vec ( ) ) ,
207
247
self . store . get ( column, key) ?. map ( |x| x. as_slice ( ) . to_vec ( ) ) ,
@@ -232,6 +272,17 @@ impl StoreWithCache<'_> {
232
272
) -> io:: Result < T > {
233
273
option_to_not_found ( self . get_ser ( column, key) , format_args ! ( "{:?}: {:?}" , column, key) )
234
274
}
275
+
276
+ pub fn insert_state_to_cache_from_op ( & mut self , op : & TrieRefcountChange , shard_uid_key : & [ u8 ] ) {
277
+ debug_assert_eq ! (
278
+ DBCol :: State . key_type( ) ,
279
+ & [ DBKeyType :: ShardUId , DBKeyType :: TrieNodeOrValueHash ]
280
+ ) ;
281
+ self . cache . insert (
282
+ ( DBCol :: State , join_two_keys ( shard_uid_key, op. hash ( ) . as_bytes ( ) ) ) ,
283
+ Some ( op. payload ( ) . to_vec ( ) ) ,
284
+ ) ;
285
+ }
235
286
}
236
287
237
288
#[ cfg( test) ]
0 commit comments