@@ -31,7 +31,75 @@ fn handle_err<T>(result: std::io::Result<T>) -> T {
3131 }
3232}
3333
34- /// Wrap RocksDb database into a trait object that implements `sp_database::Database`
34+ /// Read the reference counter for a key.
35+ fn read_counter (
36+ db : & dyn KeyValueDB ,
37+ col : ColumnId ,
38+ key : & [ u8 ] ,
39+ ) -> error:: Result < ( Vec < u8 > , Option < u32 > ) > {
40+ let mut counter_key = key. to_vec ( ) ;
41+ counter_key. push ( 0 ) ;
42+ Ok ( match db. get ( col, & counter_key) . map_err ( |e| error:: DatabaseError ( Box :: new ( e) ) ) ? {
43+ Some ( data) => {
44+ let mut counter_data = [ 0 ; 4 ] ;
45+ if data. len ( ) != 4 {
46+ return Err ( error:: DatabaseError ( Box :: new ( std:: io:: Error :: new (
47+ std:: io:: ErrorKind :: Other ,
48+ format ! ( "Unexpected counter len {}" , data. len( ) ) ,
49+ ) ) ) )
50+ }
51+ counter_data. copy_from_slice ( & data) ;
52+ let counter = u32:: from_le_bytes ( counter_data) ;
53+ ( counter_key, Some ( counter) )
54+ } ,
55+ None => ( counter_key, None ) ,
56+ } )
57+ }
58+
59+ /// Commit a transaction to a KeyValueDB.
60+ fn commit_impl < H : Clone + AsRef < [ u8 ] > > (
61+ db : & dyn KeyValueDB ,
62+ transaction : Transaction < H > ,
63+ ) -> error:: Result < ( ) > {
64+ let mut tx = DBTransaction :: new ( ) ;
65+ for change in transaction. 0 . into_iter ( ) {
66+ match change {
67+ Change :: Set ( col, key, value) => tx. put_vec ( col, & key, value) ,
68+ Change :: Remove ( col, key) => tx. delete ( col, & key) ,
69+ Change :: Store ( col, key, value) => match read_counter ( db, col, key. as_ref ( ) ) ? {
70+ ( counter_key, Some ( mut counter) ) => {
71+ counter += 1 ;
72+ tx. put ( col, & counter_key, & counter. to_le_bytes ( ) ) ;
73+ } ,
74+ ( counter_key, None ) => {
75+ let d = 1u32 . to_le_bytes ( ) ;
76+ tx. put ( col, & counter_key, & d) ;
77+ tx. put_vec ( col, key. as_ref ( ) , value) ;
78+ } ,
79+ } ,
80+ Change :: Reference ( col, key) => {
81+ if let ( counter_key, Some ( mut counter) ) = read_counter ( db, col, key. as_ref ( ) ) ? {
82+ counter += 1 ;
83+ tx. put ( col, & counter_key, & counter. to_le_bytes ( ) ) ;
84+ }
85+ } ,
86+ Change :: Release ( col, key) => {
87+ if let ( counter_key, Some ( mut counter) ) = read_counter ( db, col, key. as_ref ( ) ) ? {
88+ counter -= 1 ;
89+ if counter == 0 {
90+ tx. delete ( col, & counter_key) ;
91+ tx. delete ( col, key. as_ref ( ) ) ;
92+ } else {
93+ tx. put ( col, & counter_key, & counter. to_le_bytes ( ) ) ;
94+ }
95+ }
96+ } ,
97+ }
98+ }
99+ db. write ( tx) . map_err ( |e| error:: DatabaseError ( Box :: new ( e) ) )
100+ }
101+
102+ /// Wrap generic kvdb-based database into a trait object that implements [`Database`].
35103pub fn as_database < D , H > ( db : D ) -> std:: sync:: Arc < dyn Database < H > >
36104where
37105 D : KeyValueDB + ' static ,
@@ -40,72 +108,28 @@ where
40108 std:: sync:: Arc :: new ( DbAdapter ( db) )
41109}
42110
43- impl < D : KeyValueDB > DbAdapter < D > {
44- // Returns counter key and counter value if it exists.
45- fn read_counter ( & self , col : ColumnId , key : & [ u8 ] ) -> error:: Result < ( Vec < u8 > , Option < u32 > ) > {
46- // Add a key suffix for the counter
47- let mut counter_key = key. to_vec ( ) ;
48- counter_key. push ( 0 ) ;
49- Ok ( match self . 0 . get ( col, & counter_key) . map_err ( |e| error:: DatabaseError ( Box :: new ( e) ) ) ? {
50- Some ( data) => {
51- let mut counter_data = [ 0 ; 4 ] ;
52- if data. len ( ) != 4 {
53- return Err ( error:: DatabaseError ( Box :: new ( std:: io:: Error :: new (
54- std:: io:: ErrorKind :: Other ,
55- format ! ( "Unexpected counter len {}" , data. len( ) ) ,
56- ) ) ) )
57- }
58- counter_data. copy_from_slice ( & data) ;
59- let counter = u32:: from_le_bytes ( counter_data) ;
60- ( counter_key, Some ( counter) )
61- } ,
62- None => ( counter_key, None ) ,
63- } )
111+ impl < D : KeyValueDB , H : Clone + AsRef < [ u8 ] > > Database < H > for DbAdapter < D > {
112+ fn commit ( & self , transaction : Transaction < H > ) -> error:: Result < ( ) > {
113+ commit_impl ( & self . 0 , transaction)
114+ }
115+
116+ fn get ( & self , col : ColumnId , key : & [ u8 ] ) -> Option < Vec < u8 > > {
117+ handle_err ( self . 0 . get ( col, key) )
118+ }
119+
120+ fn contains ( & self , col : ColumnId , key : & [ u8 ] ) -> bool {
121+ handle_err ( self . 0 . has_key ( col, key) )
64122 }
65123}
66124
67- impl < D : KeyValueDB , H : Clone + AsRef < [ u8 ] > > Database < H > for DbAdapter < D > {
125+ /// RocksDB-specific adapter that implements `optimize_db` via `force_compact`.
126+ #[ cfg( feature = "rocksdb" ) ]
127+ pub struct RocksDbAdapter ( kvdb_rocksdb:: Database ) ;
128+
129+ #[ cfg( feature = "rocksdb" ) ]
130+ impl < H : Clone + AsRef < [ u8 ] > > Database < H > for RocksDbAdapter {
68131 fn commit ( & self , transaction : Transaction < H > ) -> error:: Result < ( ) > {
69- let mut tx = DBTransaction :: new ( ) ;
70- for change in transaction. 0 . into_iter ( ) {
71- match change {
72- Change :: Set ( col, key, value) => tx. put_vec ( col, & key, value) ,
73- Change :: Remove ( col, key) => tx. delete ( col, & key) ,
74- Change :: Store ( col, key, value) => match self . read_counter ( col, key. as_ref ( ) ) ? {
75- ( counter_key, Some ( mut counter) ) => {
76- counter += 1 ;
77- tx. put ( col, & counter_key, & counter. to_le_bytes ( ) ) ;
78- } ,
79- ( counter_key, None ) => {
80- let d = 1u32 . to_le_bytes ( ) ;
81- tx. put ( col, & counter_key, & d) ;
82- tx. put_vec ( col, key. as_ref ( ) , value) ;
83- } ,
84- } ,
85- Change :: Reference ( col, key) => {
86- if let ( counter_key, Some ( mut counter) ) =
87- self . read_counter ( col, key. as_ref ( ) ) ?
88- {
89- counter += 1 ;
90- tx. put ( col, & counter_key, & counter. to_le_bytes ( ) ) ;
91- }
92- } ,
93- Change :: Release ( col, key) => {
94- if let ( counter_key, Some ( mut counter) ) =
95- self . read_counter ( col, key. as_ref ( ) ) ?
96- {
97- counter -= 1 ;
98- if counter == 0 {
99- tx. delete ( col, & counter_key) ;
100- tx. delete ( col, key. as_ref ( ) ) ;
101- } else {
102- tx. put ( col, & counter_key, & counter. to_le_bytes ( ) ) ;
103- }
104- }
105- } ,
106- }
107- }
108- self . 0 . write ( tx) . map_err ( |e| error:: DatabaseError ( Box :: new ( e) ) )
132+ commit_impl ( & self . 0 , transaction)
109133 }
110134
111135 fn get ( & self , col : ColumnId , key : & [ u8 ] ) -> Option < Vec < u8 > > {
@@ -115,4 +139,17 @@ impl<D: KeyValueDB, H: Clone + AsRef<[u8]>> Database<H> for DbAdapter<D> {
115139 fn contains ( & self , col : ColumnId , key : & [ u8 ] ) -> bool {
116140 handle_err ( self . 0 . has_key ( col, key) )
117141 }
142+
143+ fn optimize_db_col ( & self , col : ColumnId ) -> error:: Result < ( ) > {
144+ self . 0 . force_compact ( col) . map_err ( |e| error:: DatabaseError ( Box :: new ( e) ) )
145+ }
146+ }
147+
148+ /// Wrap RocksDB database into a trait object with `optimize_db` support.
149+ #[ cfg( feature = "rocksdb" ) ]
150+ pub fn as_rocksdb_database < H > ( db : kvdb_rocksdb:: Database ) -> std:: sync:: Arc < dyn Database < H > >
151+ where
152+ H : Clone + AsRef < [ u8 ] > ,
153+ {
154+ std:: sync:: Arc :: new ( RocksDbAdapter ( db) )
118155}
0 commit comments