massa_event_cache/
rocksdb_operator.rs1use rocksdb::MergeOperands;
2
3pub fn counter_merge(
4 _key: &[u8],
5 existing_val: Option<&[u8]>,
6 operands: &MergeOperands,
7) -> Option<Vec<u8>> {
8 let counter_current_value = if let Some(existing_val) = existing_val {
9 u64::from_be_bytes(existing_val.try_into().unwrap())
10 } else {
11 0
12 };
13
14 let counter_value = operands.iter().fold(counter_current_value, |mut acc, x| {
15 let incr_value = i64::from_be_bytes(x.try_into().unwrap());
16 acc = acc.saturating_add_signed(incr_value);
17 acc
18 });
19
20 Some(counter_value.to_be_bytes().to_vec())
21}
22
23#[cfg(test)]
24mod tests {
25 use super::*;
26 use rocksdb::{Options, DB};
29 use serial_test::serial;
30 use tempfile::TempDir;
31
32 #[test]
33 #[serial]
34 fn test_operator() {
35 let tmp_path = TempDir::new().unwrap().path().to_path_buf();
36 let options = {
37 let mut opts = Options::default();
38 opts.create_if_missing(true);
39 opts.set_merge_operator_associative("counter merge operator", counter_merge);
40 opts
41 };
42 let db = DB::open(&options, tmp_path).unwrap();
43 let key_1 = "foo1";
44 let key_2 = "baz42";
45 db.put(key_1, 0u64.to_be_bytes()).unwrap();
46 db.put(key_2, 0u64.to_be_bytes()).unwrap();
47
48 let value = db.get(key_1).unwrap().unwrap();
49 assert_eq!(u64::from_be_bytes(value.try_into().unwrap()), 0);
50 let value2 = db.get(key_2).unwrap().unwrap();
51 assert_eq!(u64::from_be_bytes(value2.try_into().unwrap()), 0);
52
53 db.merge(key_1, 1i64.to_be_bytes()).unwrap();
55
56 let value = db.get(key_1).unwrap().unwrap();
57 assert_eq!(u64::from_be_bytes(value.try_into().unwrap()), 1);
58 let value2 = db.get(key_2).unwrap().unwrap();
59 assert_eq!(u64::from_be_bytes(value2.try_into().unwrap()), 0);
60
61 db.merge(key_2, 9i64.to_be_bytes()).unwrap();
63 db.merge(key_2, 1i64.to_be_bytes()).unwrap();
65 db.merge(key_2, 32i64.to_be_bytes()).unwrap();
67
68 let value = db.get(key_1).unwrap().unwrap();
69 assert_eq!(u64::from_be_bytes(value.try_into().unwrap()), 1);
70 let value2 = db.get(key_2).unwrap().unwrap();
71 assert_eq!(u64::from_be_bytes(value2.try_into().unwrap()), 42);
72 }
73
74 #[test]
75 #[serial]
76 fn test_operator_2() {
77 let tmp_path = TempDir::new().unwrap().path().to_path_buf();
78 let options = {
79 let mut opts = Options::default();
80 opts.create_if_missing(true);
81 opts.set_merge_operator_associative("counter merge operator", counter_merge);
82 opts
83 };
84 let db = DB::open(&options, tmp_path).unwrap();
85 let key_1 = "foo1";
86 let key_2 = "baz42";
87 db.put(key_1, 0u64.to_be_bytes()).unwrap();
88 db.put(key_2, 0u64.to_be_bytes()).unwrap();
89
90 let value = db.get(key_1).unwrap().unwrap();
91 assert_eq!(u64::from_be_bytes(value.try_into().unwrap()), 0);
92 let value2 = db.get(key_2).unwrap().unwrap();
93 assert_eq!(u64::from_be_bytes(value2.try_into().unwrap()), 0);
94
95 db.merge(key_1, 1i64.to_be_bytes()).unwrap();
97
98 let value = db.get(key_1).unwrap().unwrap();
99 assert_eq!(u64::from_be_bytes(value.try_into().unwrap()), 1);
100 let value2 = db.get(key_2).unwrap().unwrap();
101 assert_eq!(u64::from_be_bytes(value2.try_into().unwrap()), 0);
102
103 db.merge(key_1, (-3i64).to_be_bytes()).unwrap();
104
105 let value = db.get(key_1).unwrap().unwrap();
106 assert_eq!(u64::from_be_bytes(value.try_into().unwrap()), 0);
107 let value2 = db.get(key_2).unwrap().unwrap();
108 assert_eq!(u64::from_be_bytes(value2.try_into().unwrap()), 0);
109 }
110}