1
1
use std:: fs:: File ;
2
- use std:: io:: { BufReader , Read , Write } ;
3
- use std:: ops:: Deref ;
2
+ use std:: io:: { BufReader , BufWriter , Read , Write } ;
4
3
use std:: path:: Path ;
5
4
use std:: sync:: Arc ;
6
5
use std:: { fmt, io} ;
@@ -53,31 +52,26 @@ impl Store {
53
52
Store { storage }
54
53
}
55
54
56
- pub fn get ( & self , column : DBCol , key : & [ u8 ] ) -> Result < Option < Vec < u8 > > , io :: Error > {
57
- self . storage . get ( column, key) . map_err ( |e| e . into ( ) )
55
+ pub fn get ( & self , column : DBCol , key : & [ u8 ] ) -> io :: Result < Option < Vec < u8 > > > {
56
+ self . storage . get ( column, key) . map_err ( io :: Error :: from )
58
57
}
59
58
60
- pub fn get_ser < T : BorshDeserialize > (
61
- & self ,
62
- column : DBCol ,
63
- key : & [ u8 ] ,
64
- ) -> Result < Option < T > , io:: Error > {
65
- match self . storage . get ( column, key) {
66
- Ok ( Some ( bytes) ) => match T :: try_from_slice ( bytes. as_ref ( ) ) {
59
+ pub fn get_ser < T : BorshDeserialize > ( & self , column : DBCol , key : & [ u8 ] ) -> io:: Result < Option < T > > {
60
+ match self . get ( column, key) ? {
61
+ Some ( bytes) => match T :: try_from_slice ( & bytes) {
67
62
Ok ( result) => Ok ( Some ( result) ) ,
68
63
Err ( e) => Err ( e) ,
69
64
} ,
70
- Ok ( None ) => Ok ( None ) ,
71
- Err ( e) => Err ( e. into ( ) ) ,
65
+ None => Ok ( None ) ,
72
66
}
73
67
}
74
68
75
- pub fn exists ( & self , column : DBCol , key : & [ u8 ] ) -> Result < bool , io:: Error > {
76
- self . storage . get ( column, key) . map ( |value| value. is_some ( ) ) . map_err ( |e| e . into ( ) )
69
+ pub fn exists ( & self , column : DBCol , key : & [ u8 ] ) -> io:: Result < bool > {
70
+ self . get ( column, key) . map ( |value| value. is_some ( ) )
77
71
}
78
72
79
73
pub fn store_update ( & self ) -> StoreUpdate {
80
- StoreUpdate :: new ( self . storage . clone ( ) )
74
+ StoreUpdate :: new ( Arc :: clone ( & self . storage ) )
81
75
}
82
76
83
77
pub fn iter < ' a > (
@@ -106,16 +100,15 @@ impl Store {
106
100
& ' a self ,
107
101
column : DBCol ,
108
102
key_prefix : & ' a [ u8 ] ,
109
- ) -> Box < dyn Iterator < Item = Result < ( Vec < u8 > , T ) , io:: Error > > + ' a > {
110
- Box :: new (
111
- self . storage
112
- . iter_prefix ( column, key_prefix)
113
- . map ( |( key, value) | Ok ( ( key. to_vec ( ) , T :: try_from_slice ( value. as_ref ( ) ) ?) ) ) ,
114
- )
103
+ ) -> impl Iterator < Item = io:: Result < ( Box < [ u8 ] > , T ) > > + ' a {
104
+ self . storage
105
+ . iter_prefix ( column, key_prefix)
106
+ . map ( |( key, value) | Ok ( ( key, T :: try_from_slice ( value. as_ref ( ) ) ?) ) )
115
107
}
116
108
117
- pub fn save_to_file ( & self , column : DBCol , filename : & Path ) -> Result < ( ) , std:: io:: Error > {
118
- let mut file = File :: create ( filename) ?;
109
+ pub fn save_to_file ( & self , column : DBCol , filename : & Path ) -> io:: Result < ( ) > {
110
+ let file = File :: create ( filename) ?;
111
+ let mut file = BufWriter :: new ( file) ;
119
112
for ( key, value) in self . storage . iter_without_rc_logic ( column) {
120
113
file. write_u32 :: < LittleEndian > ( key. len ( ) as u32 ) ?;
121
114
file. write_all ( & key) ?;
@@ -125,7 +118,7 @@ impl Store {
125
118
Ok ( ( ) )
126
119
}
127
120
128
- pub fn load_from_file ( & self , column : DBCol , filename : & Path ) -> Result < ( ) , std :: io :: Error > {
121
+ pub fn load_from_file ( & self , column : DBCol , filename : & Path ) -> io :: Result < ( ) > {
129
122
let file = File :: open ( filename) ?;
130
123
let mut file = BufReader :: new ( file) ;
131
124
let mut transaction = self . storage . transaction ( ) ;
@@ -134,7 +127,7 @@ impl Store {
134
127
loop {
135
128
let key_len = match file. read_u32 :: < LittleEndian > ( ) {
136
129
Ok ( key_len) => key_len as usize ,
137
- Err ( ref err) if err. kind ( ) == std :: io:: ErrorKind :: UnexpectedEof => break ,
130
+ Err ( err) if err. kind ( ) == io:: ErrorKind :: UnexpectedEof => break ,
138
131
Err ( err) => return Err ( err) ,
139
132
} ;
140
133
key. resize ( key_len, 0 ) ;
@@ -146,7 +139,7 @@ impl Store {
146
139
147
140
transaction. put ( column, & key, & value) ;
148
141
}
149
- self . storage . write ( transaction) . map_err ( |e| e . into ( ) )
142
+ self . storage . write ( transaction) . map_err ( io :: Error :: from )
150
143
}
151
144
152
145
pub fn get_rocksdb ( & self ) -> Option < & RocksDB > {
@@ -173,7 +166,7 @@ impl StoreUpdate {
173
166
}
174
167
175
168
pub fn new_with_tries ( tries : ShardTries ) -> Self {
176
- let storage = tries. get_store ( ) . storage . clone ( ) ;
169
+ let storage = Arc :: clone ( & tries. get_store ( ) . storage ) ;
177
170
let transaction = storage. transaction ( ) ;
178
171
StoreUpdate { storage, transaction, tries : Some ( tries) }
179
172
}
@@ -193,7 +186,7 @@ impl StoreUpdate {
193
186
column : DBCol ,
194
187
key : & [ u8 ] ,
195
188
value : & T ,
196
- ) -> Result < ( ) , io :: Error > {
189
+ ) -> io :: Result < ( ) > {
197
190
debug_assert ! ( !column. is_rc( ) ) ;
198
191
let data = value. try_to_vec ( ) ?;
199
192
self . set ( column, key, & data) ;
@@ -210,19 +203,17 @@ impl StoreUpdate {
210
203
211
204
/// Merge another store update into this one.
212
205
pub fn merge ( & mut self , other : StoreUpdate ) {
213
- if let Some ( tries) = other. tries {
214
- if self . tries . is_none ( ) {
215
- self . tries = Some ( tries) ;
216
- } else {
217
- debug_assert ! ( self . tries. as_ref( ) . unwrap( ) . is_same( & tries) ) ;
218
- }
206
+ match ( & self . tries , other. tries ) {
207
+ ( None | Some ( _) , None ) => ( ) ,
208
+ ( None , Some ( tries) ) => self . tries = Some ( tries) ,
209
+ ( Some ( t1) , Some ( t2) ) => debug_assert ! ( t1. is_same( & t2) ) ,
219
210
}
220
211
221
212
self . merge_transaction ( other. transaction ) ;
222
213
}
223
214
224
215
/// Merge DB Transaction.
225
- pub fn merge_transaction ( & mut self , transaction : DBTransaction ) {
216
+ fn merge_transaction ( & mut self , transaction : DBTransaction ) {
226
217
for op in transaction. ops {
227
218
match op {
228
219
DBOp :: Insert { col, key, value } => self . transaction . put ( col, & key, & value) ,
@@ -235,18 +226,18 @@ impl StoreUpdate {
235
226
}
236
227
}
237
228
238
- pub fn commit ( self ) -> Result < ( ) , io :: Error > {
229
+ pub fn commit ( self ) -> io :: Result < ( ) > {
239
230
debug_assert ! (
240
231
{
241
232
let non_refcount_keys = self
242
233
. transaction
243
234
. ops
244
235
. iter( )
245
236
. filter_map( |op| match op {
246
- DBOp :: Insert { col, key, .. } => Some ( ( * col as u8 , key) ) ,
247
- DBOp :: Delete { col , key } => Some ( ( * col as u8 , key) ) ,
248
- DBOp :: UpdateRefcount { .. } => None ,
249
- DBOp :: DeleteAll { .. } => None ,
237
+ DBOp :: Insert { col, key, .. } | DBOp :: Delete { col , key } => {
238
+ Some ( ( * col as u8 , key) )
239
+ }
240
+ DBOp :: UpdateRefcount { .. } | DBOp :: DeleteAll { .. } => None ,
250
241
} )
251
242
. collect:: <Vec <_>>( ) ;
252
243
non_refcount_keys. len( )
@@ -256,13 +247,13 @@ impl StoreUpdate {
256
247
self
257
248
) ;
258
249
if let Some ( tries) = self . tries {
259
- assert_eq ! (
260
- tries . get_store ( ) . storage . deref ( ) as * const _ ,
261
- self . storage . deref ( ) as * const _
262
- ) ;
250
+ // Note: avoid comparing wide pointers here to work-around
251
+ // https://github.com/rust-lang/rust/issues/69757
252
+ let addr = |arc| Arc :: as_ptr ( arc ) as * const u8 ;
253
+ assert_eq ! ( addr ( & tries . get_store ( ) . storage ) , addr ( & self . storage ) , ) ;
263
254
tries. update_cache ( & self . transaction ) ?;
264
255
}
265
- self . storage . write ( self . transaction ) . map_err ( |e| e . into ( ) )
256
+ self . storage . write ( self . transaction ) . map_err ( io :: Error :: from )
266
257
}
267
258
}
268
259
@@ -289,22 +280,18 @@ pub fn read_with_cache<'a, T: BorshDeserialize + 'a>(
289
280
cache : & ' a mut LruCache < Vec < u8 > , T > ,
290
281
key : & [ u8 ] ,
291
282
) -> io:: Result < Option < & ' a T > > {
292
- let key_vec = key. to_vec ( ) ;
293
- if cache. get ( & key_vec) . is_some ( ) {
294
- return Ok ( Some ( cache. get ( & key_vec) . unwrap ( ) ) ) ;
283
+ // Note: Due to `&mut -> &` conversions, it's not possible to avoid double
284
+ // hash map lookups here.
285
+ if cache. contains ( key) {
286
+ return Ok ( cache. get ( key) ) ;
295
287
}
296
288
if let Some ( result) = storage. get_ser ( col, key) ? {
297
289
cache. put ( key. to_vec ( ) , result) ;
298
- return Ok ( cache. get ( & key_vec ) ) ;
290
+ return Ok ( cache. get ( key ) ) ;
299
291
}
300
292
Ok ( None )
301
293
}
302
294
303
- pub fn create_store ( path : & Path ) -> Store {
304
- let db = Arc :: new ( RocksDB :: new ( path) . expect ( "Failed to open the database" ) ) ;
305
- Store :: new ( db)
306
- }
307
-
308
295
#[ derive( Default , Debug ) ]
309
296
pub struct StoreConfig {
310
297
/// Attempted writes to the DB will fail. Doesn't require a `LOCK` file.
@@ -314,17 +301,19 @@ pub struct StoreConfig {
314
301
pub enable_statistics : bool ,
315
302
}
316
303
304
+ pub fn create_store ( path : & Path ) -> Store {
305
+ create_store_with_config ( path, StoreConfig :: default ( ) )
306
+ }
307
+
317
308
pub fn create_store_with_config ( path : & Path , store_config : StoreConfig ) -> Store {
318
309
let mut opts = RocksDBOptions :: default ( ) ;
319
310
if store_config. enable_statistics {
320
311
opts = opts. enable_statistics ( ) ;
321
312
}
322
313
323
- let db = Arc :: new (
324
- ( if store_config. read_only { opts. read_only ( path) } else { opts. read_write ( path) } )
325
- . expect ( "Failed to open the database" ) ,
326
- ) ;
327
- Store :: new ( db)
314
+ let db = if store_config. read_only { opts. read_only ( path) } else { opts. read_write ( path) }
315
+ . expect ( "Failed to open the database" ) ;
316
+ Store :: new ( Arc :: new ( db) )
328
317
}
329
318
330
319
/// Reads an object from Trie.
@@ -334,18 +323,15 @@ pub fn get<T: BorshDeserialize>(
334
323
state_update : & TrieUpdate ,
335
324
key : & TrieKey ,
336
325
) -> Result < Option < T > , StorageError > {
337
- state_update. get ( key) . and_then ( |opt| {
338
- opt. map_or_else (
339
- || Ok ( None ) ,
340
- |data| {
341
- T :: try_from_slice ( & data)
342
- . map_err ( |_| {
343
- StorageError :: StorageInconsistentState ( "Failed to deserialize" . to_string ( ) )
344
- } )
345
- . map ( Some )
346
- } ,
347
- )
348
- } )
326
+ match state_update. get ( key) ? {
327
+ None => Ok ( None ) ,
328
+ Some ( data) => match T :: try_from_slice ( & data) {
329
+ Err ( _err) => {
330
+ Err ( StorageError :: StorageInconsistentState ( "Failed to deserialize" . to_string ( ) ) )
331
+ }
332
+ Ok ( value) => Ok ( Some ( value) ) ,
333
+ } ,
334
+ }
349
335
}
350
336
351
337
/// Writes an object into Trie.
@@ -509,11 +495,11 @@ pub fn remove_account(
509
495
Ok ( ( ) )
510
496
}
511
497
512
- pub fn get_genesis_state_roots ( store : & Store ) -> Result < Option < Vec < StateRoot > > , std :: io :: Error > {
498
+ pub fn get_genesis_state_roots ( store : & Store ) -> io :: Result < Option < Vec < StateRoot > > > {
513
499
store. get_ser :: < Vec < StateRoot > > ( DBCol :: ColBlockMisc , GENESIS_STATE_ROOTS_KEY )
514
500
}
515
501
516
- pub fn get_genesis_hash ( store : & Store ) -> Result < Option < CryptoHash > , std :: io :: Error > {
502
+ pub fn get_genesis_hash ( store : & Store ) -> io :: Result < Option < CryptoHash > > {
517
503
store. get_ser :: < CryptoHash > ( DBCol :: ColBlockMisc , GENESIS_JSON_HASH_KEY )
518
504
}
519
505
@@ -538,13 +524,13 @@ pub struct StoreCompiledContractCache {
538
524
/// Key must take into account VM being used and its configuration, so that
539
525
/// we don't cache non-gas metered binaries, for example.
540
526
impl CompiledContractCache for StoreCompiledContractCache {
541
- fn put ( & self , key : & [ u8 ] , value : & [ u8 ] ) -> Result < ( ) , std :: io :: Error > {
527
+ fn put ( & self , key : & [ u8 ] , value : & [ u8 ] ) -> io :: Result < ( ) > {
542
528
let mut store_update = self . store . store_update ( ) ;
543
529
store_update. set ( DBCol :: ColCachedContractCode , key, value) ;
544
530
store_update. commit ( )
545
531
}
546
532
547
- fn get ( & self , key : & [ u8 ] ) -> Result < Option < Vec < u8 > > , std :: io :: Error > {
533
+ fn get ( & self , key : & [ u8 ] ) -> io :: Result < Option < Vec < u8 > > > {
548
534
self . store . get ( DBCol :: ColCachedContractCode , key)
549
535
}
550
536
}
0 commit comments