Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_hash/tests/map.rs

3.8 KiB, 28 runs

created by r1870400018:367, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use oxedyne_fe2o3_core::{
2 prelude::*,
3 map::MapMut,
4 rand::Rand,
5};
6use oxedyne_fe2o3_hash::{
7 hash::HashScheme,
8 map::ShardMap,
9};
10use oxedyne_fe2o3_iop_hash::{
11 api::{
12 Hasher,
13 HashForm,
14 },
15};
16
17use std::{
18 collections::BTreeMap,
19 fmt::Debug,
20 sync::Arc,
21 thread,
22};
23
24const MAX_SHARDS: usize = 20;
25const N1: u32 = 4;
26const N2: u32 = 13;
27const N_THREADS: usize = 5;
28const KEY_LEN: usize = 4;
29const VALS_PER_THREAD: u8 = 10;
30const SALT_SIZE: usize = 5;
31const SALT: [u8; SALT_SIZE] = [1u8, 2, 3, 4, 5];
32const STACK_SIZE: usize = 2 * 1024 * 1024;
33
34#[derive(Clone, Debug, Eq, PartialEq)]
35struct TestStruct {
36 ord: u8,
37 thread: usize,
38}
39
40fn dump_shards<
41 const C: usize,
42 const S: usize,
43 V: Clone + Debug,
44 M: MapMut<HashForm, V> + Clone + Debug,
45 H: Hasher + Send + Sync + 'static,
46>(
47 shardmap: &ShardMap<C, S, V, M, H>,
48)
49 -> Outcome<()>
50{
51 for i in 0..shardmap.n {
52 if let Some(locked_map) = &shardmap.shards[i] {
53 let unlocked_map = lock_read!(locked_map);
54 debug!("Map {}, len {}", i, unlocked_map.len());
55 for (k, v) in (*unlocked_map).iter() {
56 debug!(" k={:02x?} v={:?}", k, v);
57 }
58 }
59 }
60 Ok(())
61}
62
63fn doer<
64 const C: usize,
65 const S: usize,
66 M: MapMut<HashForm, TestStruct> + Clone + Debug,
67 H: Hasher + Send + Sync + 'static,
68>(
69 t: usize,
70 shardmap: Arc<ShardMap<C, S, TestStruct, M, H>>,
71)
72 -> Outcome<Vec<(Vec<u8>, TestStruct)>>
73{
74 let mut data = Vec::new();
75 for j in 0..VALS_PER_THREAD {
76 let mut p = [0u8; KEY_LEN];
77 Rand::fill_u8(&mut p);
78 let v = TestStruct { ord: j, thread: t };
79 res!((*shardmap).insert(&p, v.clone()));
80 data.push((p.to_vec(), v));
81 }
82 test!("Thread {} finished doing.", t);
83 Ok(data)
84}
85
86pub fn test_map(filter: &'static str) -> Outcome<()> {
87
88 match filter {
89 "all" | "shardmap" => {
90 let shardmap = Arc::new(res!(ShardMap::<MAX_SHARDS, SALT_SIZE, _, _, _>::new(
91 N1,
92 SALT,
93 BTreeMap::<_, TestStruct>::new(),
94 HashScheme::new_seahash(),
95 )));
96 let mut handles = Vec::new();
97 for t in 0..N_THREADS {
98 let builder = thread::Builder::new()
99 .name(fmt!("maps_test"))
100 .stack_size(STACK_SIZE);
101 let shardmap_clone = shardmap.clone();
102 handles.push(res!(builder.spawn( move || doer(t, shardmap_clone) )));
103 }
104
105 let mut data = Vec::new();
106 for handle in handles {
107 let thread_data = match handle.join() {
108 Ok(outcome) => res!(outcome),
109 Err(_) => return Err(err!(
110 "A ShardMap worker thread panicked."; Test, Thread)),
111 };
112 for pair in thread_data {
113 data.push(pair);
114 }
115 }
116
117 res!(dump_shards(&shardmap));
118 req!(data.len(), N_THREADS * (VALS_PER_THREAD as usize));
119 for (p, v) in &data {
120 let locked_map = res!(shardmap.get_shard(p));
121 let unlocked_map = lock_read!(locked_map);
122 req!(unlocked_map.get(&shardmap.key(p)), Some(v));
123 }
124 let maps2 = res!(shardmap.remap(N2));
125 test!("Remap from {} to {} shards...", N1, N2);
126 res!(dump_shards(&maps2));
127 // Every key must still be found after the remapping.
128 for (p, v) in &data {
129 req!(res!(maps2.get_clone(p)), Some(v.clone()));
130 }
131 },
132 _ => (),
133 }
134
135 Ok(())
136}