1
1
use anyhow:: Result ;
2
2
use imbl:: OrdMap ;
3
3
use rand:: prelude:: * ;
4
- use std:: { collections :: BTreeMap , time:: Duration } ;
4
+ use std:: time:: Duration ;
5
5
use tempfile:: TempDir ;
6
6
use tokio:: time:: { error:: Elapsed , timeout} ;
7
7
use tokio_util:: sync:: CancellationToken ;
@@ -48,10 +48,7 @@ impl Biases {
48
48
struct Snapshot {
49
49
sync_seqn : u32 ,
50
50
/// The state of the database at this snapshot.
51
- ///
52
- /// The key is the key of the key-value pair. Instead of using the 32 bytes of the key, we
53
- /// save the index of the key in the `WorkloadState::mentions` vector.
54
- state : OrdMap < u32 , Option < Vec < u8 > > > ,
51
+ state : OrdMap < [ u8 ; 32 ] , Option < Vec < u8 > > > ,
55
52
}
56
53
57
54
impl Snapshot {
@@ -73,11 +70,6 @@ struct WorkloadState {
73
70
random_size : bool ,
74
71
/// The values that were committed.
75
72
committed : Snapshot ,
76
- /// All keys that were generated during this run.
77
- ///
78
- /// It's extremely unlikely to find any duplicates in there. Each key is very likely to store
79
- /// a value.
80
- mentions : Vec < [ u8 ; 32 ] > ,
81
73
}
82
74
83
75
impl WorkloadState {
@@ -88,7 +80,6 @@ impl WorkloadState {
88
80
size,
89
81
random_size,
90
82
committed : Snapshot :: empty ( ) ,
91
- mentions : Vec :: with_capacity ( 32 * 1024 ) ,
92
83
}
93
84
}
94
85
@@ -112,47 +103,55 @@ impl WorkloadState {
112
103
// Commiting requires using only the unique keys. To ensure that we deduplicate the keys
113
104
// using a hash set.
114
105
let mut used_keys = std:: collections:: HashSet :: with_capacity ( num_changes) ;
115
- for _ in 0 ..num_changes {
116
- // Generate a key until unique.
117
- let key_index = loop {
118
- let ki = self . gen_key ( ) ;
119
- if used_keys. insert ( ki) {
120
- break ki;
121
- }
122
- } ;
123
-
124
- if self . rng . gen_bool ( self . biases . delete ) {
125
- snapshot. state . insert ( key_index, None ) ;
126
- let key = self . mentions [ key_index as usize ] ;
127
- changes. push ( KeyValueChange :: Delete ( key) ) ;
128
- } else {
129
- let value = self . gen_value ( ) ;
130
- snapshot. state . insert ( key_index, Some ( value. clone ( ) ) ) ;
131
- let key = self . mentions [ key_index as usize ] ;
132
- changes. push ( KeyValueChange :: Insert ( key, value) ) ;
133
- } ;
106
+ loop {
107
+ let change = self . gen_key_value_change ( ) ;
108
+ if used_keys. contains ( change. key ( ) ) {
109
+ continue ;
110
+ }
111
+
112
+ snapshot. state . insert ( * change. key ( ) , change. value ( ) ) ;
113
+ used_keys. insert ( * change. key ( ) ) ;
114
+ changes. push ( change) ;
115
+
116
+ if used_keys. len ( ) >= num_changes {
117
+ break ;
118
+ }
134
119
}
135
120
136
121
changes. sort_by ( |a, b| a. key ( ) . cmp ( & b. key ( ) ) ) ;
137
122
138
123
( snapshot, changes)
139
124
}
140
125
141
- /// Returns a key that was generated before or a new key. The returned value is an index in the
142
- /// `mentions` vector.
143
- fn gen_key ( & mut self ) -> u32 {
126
+ /// Returns a KeyValueChange with a new key, a deleted or a modified one.
127
+ fn gen_key_value_change ( & mut self ) -> KeyValueChange {
144
128
// TODO: sophisticated key generation.
145
129
//
146
130
// - Pick a key that was already generated before, but generate a key that shares some bits.
147
- if self . mentions . is_empty ( ) || self . rng . gen_bool ( self . biases . new_key ) {
148
- let mut key = [ 0 ; 32 ] ;
131
+ let mut key = [ 0 ; 32 ] ;
132
+ if !self . committed . state . is_empty ( ) && self . rng . gen_bool ( self . biases . delete ) {
133
+ loop {
134
+ self . rng . fill_bytes ( & mut key) ;
135
+ if let Some ( ( next_key, Some ( _) ) ) = self . committed . state . get_next ( & key) {
136
+ return KeyValueChange :: Delete ( * next_key) ;
137
+ }
138
+ }
139
+ }
140
+
141
+ if self . committed . state . is_empty ( ) || self . rng . gen_bool ( self . biases . new_key ) {
142
+ loop {
143
+ self . rng . fill_bytes ( & mut key) ;
144
+ if !self . committed . state . contains_key ( & key) {
145
+ return KeyValueChange :: Insert ( key, self . gen_value ( ) ) ;
146
+ }
147
+ }
148
+ }
149
+
150
+ loop {
149
151
self . rng . fill_bytes ( & mut key) ;
150
- let ix = self . mentions . len ( ) as u32 ;
151
- self . mentions . push ( key. clone ( ) ) ;
152
- ix
153
- } else {
154
- let ix = self . rng . gen_range ( 0 ..self . mentions . len ( ) ) ;
155
- ix as u32
152
+ if let Some ( ( next_key, _) ) = self . committed . state . get_next ( & key) {
153
+ return KeyValueChange :: Insert ( * next_key, self . gen_value ( ) ) ;
154
+ }
156
155
}
157
156
}
158
157
0 commit comments