Skip to content

Commit 9b7f6b4

Browse files
add get_proof function to AdsCore
1 parent 34aa582 commit 9b7f6b4

File tree

7 files changed

+230
-56
lines changed

7 files changed

+230
-56
lines changed

qmdb/examples/v1_fuzz/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ fn run_fuzz_single_round(
111111
let task_count = task_list.len() as i64;
112112
println!("AA height={} task_count={:#08x}", height, task_count);
113113
let last_task_id = (height << IN_BLOCK_IDX_BITS) | (task_count - 1);
114-
let success = ads.start_block(height, Arc::new(TasksManager::new(task_list, last_task_id)));
114+
let (success, _) =
115+
ads.start_block(height, Arc::new(TasksManager::new(task_list, last_task_id)));
115116
if !success {
116117
unsafe {
117118
if ROOT_BEFORE_SET[0] == [0u8; 32] {

qmdb/src/def.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub const DEFAULT_ENTRY_SIZE: usize = 300;
1717
pub const SENTRY_COUNT: usize = (1 << 16) / SHARD_COUNT;
1818

1919
pub const PRUNE_EVERY_NBLOCKS: i64 = 500;
20+
pub const MAX_PROOF_REQ: usize = 1000;
2021

2122
pub const JOB_COUNT: usize = 2000;
2223
pub const SUB_JOB_RESERVE_COUNT: usize = 50;

qmdb/src/flusher.rs

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
use crate::def::{LEAF_COUNT_IN_TWIG, MIN_PRUNE_COUNT, PRUNE_EVERY_NBLOCKS, TWIG_SHIFT};
1+
use crate::def::{
2+
LEAF_COUNT_IN_TWIG, MAX_PROOF_REQ, MIN_PRUNE_COUNT, PRUNE_EVERY_NBLOCKS, SHARD_COUNT,
3+
TWIG_SHIFT,
4+
};
25
use crate::entryfile::{EntryBufferReader, EntryFile};
6+
use crate::merkletree::proof::ProofPath;
37
use crate::merkletree::Tree;
4-
use crate::metadb::MetaDB;
8+
#[cfg(feature = "slow_hashing")]
9+
use crate::merkletree::UpperTree;
10+
use crate::metadb::{MetaDB, MetaInfo};
511
use parking_lot::RwLock;
6-
use std::sync::mpsc::SyncSender;
7-
use std::sync::{Arc, Barrier};
12+
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
13+
use std::sync::{Arc, Barrier, Condvar, Mutex};
814
use std::thread;
915

1016
type RocksMetaDB = MetaDB;
@@ -23,12 +29,14 @@ impl BarrierSet {
2329
}
2430
}
2531

32+
pub type ProofReqElem = Arc<(Mutex<(u64, Option<Result<ProofPath, String>>)>, Condvar)>;
33+
2634
pub struct Flusher {
2735
shards: Vec<Box<FlusherShard>>,
2836
meta: Arc<RwLock<RocksMetaDB>>,
2937
curr_height: i64,
3038
max_kept_height: i64,
31-
end_block_chan: SyncSender<i64>,
39+
end_block_chan: SyncSender<Arc<MetaInfo>>,
3240
}
3341

3442
impl Flusher {
@@ -37,7 +45,7 @@ impl Flusher {
3745
meta: Arc<RwLock<RocksMetaDB>>,
3846
curr_height: i64,
3947
max_kept_height: i64,
40-
end_block_chan: SyncSender<i64>,
48+
end_block_chan: SyncSender<Arc<MetaInfo>>,
4149
) -> Self {
4250
Self {
4351
shards,
@@ -48,6 +56,14 @@ impl Flusher {
4856
}
4957
}
5058

59+
pub fn get_proof_req_senders(&self) -> Vec<SyncSender<ProofReqElem>> {
60+
let mut v = Vec::with_capacity(SHARD_COUNT);
61+
for i in 0..SHARD_COUNT {
62+
v.push(self.shards[i].proof_req_sender.clone());
63+
}
64+
v
65+
}
66+
5167
pub fn flush(&mut self, shard_count: usize) {
5268
loop {
5369
self.curr_height += 1;
@@ -82,36 +98,56 @@ pub struct FlusherShard {
8298
tree: Tree,
8399
last_compact_done_sn: u64,
84100
shard_id: usize,
101+
proof_req_sender: SyncSender<ProofReqElem>,
102+
proof_req_receiver: Receiver<ProofReqElem>,
85103
#[cfg(feature = "slow_hashing")]
86-
upper_tree_sender: SyncSender<crate::merkletree::UpperTree>,
104+
upper_tree_sender: SyncSender<UpperTree>,
87105
#[cfg(feature = "slow_hashing")]
88-
upper_tree_receiver: std::sync::mpsc::Receiver<crate::merkletree::UpperTree>,
106+
upper_tree_receiver: Receiver<UpperTree>,
89107
}
90108

91109
impl FlusherShard {
92110
pub fn new(tree: Tree, oldest_active_sn: u64, shard_id: usize) -> Self {
93111
#[cfg(feature = "slow_hashing")]
94-
let (ut_sender, ut_receiver) = std::sync::mpsc::sync_channel(2);
112+
let (ut_sender, ut_receiver) = sync_channel(2);
113+
let (pr_sender, pr_receiver) = sync_channel(MAX_PROOF_REQ);
95114

96115
Self {
97116
buf_read: None,
98117
tree,
99118
last_compact_done_sn: oldest_active_sn,
100119
shard_id,
120+
proof_req_sender: pr_sender,
121+
proof_req_receiver: pr_receiver,
101122
#[cfg(feature = "slow_hashing")]
102123
upper_tree_sender: ut_sender,
103124
#[cfg(feature = "slow_hashing")]
104125
upper_tree_receiver: ut_receiver,
105126
}
106127
}
107128

129+
pub fn handle_proof_req(&self) {
130+
loop {
131+
let pair = self.proof_req_receiver.try_recv();
132+
if pair.is_err() {
133+
break;
134+
}
135+
let pair = pair.unwrap();
136+
let (lock, cvar) = &*pair;
137+
let mut sn_proof = lock.lock().unwrap();
138+
let proof = self.tree.get_proof(sn_proof.0);
139+
sn_proof.1 = Some(proof);
140+
cvar.notify_one();
141+
}
142+
}
143+
108144
pub fn flush(
109145
&mut self,
110146
prune_to_height: i64,
111147
curr_height: i64,
112148
meta: Arc<RwLock<RocksMetaDB>>,
113149
bar_set: Arc<BarrierSet>,
114-
end_block_chan: SyncSender<i64>,
150+
end_block_chan: SyncSender<Arc<MetaInfo>>,
115151
) {
116152
let buf_read = self.buf_read.as_mut().unwrap();
117153
loop {
@@ -172,7 +208,7 @@ impl FlusherShard {
172208

173209
let youngest_twig_id = self.tree.youngest_twig_id;
174210
let shard_id = self.shard_id;
175-
let mut upper_tree = crate::merkletree::UpperTree::empty();
211+
let mut upper_tree = UpperTree::empty();
176212
std::mem::swap(&mut self.tree.upper_tree, &mut upper_tree);
177213
let upper_tree_sender = self.upper_tree_sender.clone();
178214
thread::spawn(move || {
@@ -191,6 +227,7 @@ impl FlusherShard {
191227
edge_nodes_bytes =
192228
upper_tree.prune_nodes(start_twig_id, end_twig_id, youngest_twig_id);
193229
}
230+
194231
//shard#0 must wait other shards to finish
195232
if shard_id == 0 {
196233
bar_set.metadb_bar.wait();
@@ -218,9 +255,9 @@ impl FlusherShard {
218255

219256
if shard_id == 0 {
220257
meta.set_curr_height(curr_height);
221-
meta.commit();
258+
let meta_info = meta.commit();
222259
drop(meta);
223-
match end_block_chan.send(curr_height) {
260+
match end_block_chan.send(meta_info) {
224261
Ok(_) => {
225262
//println!("{} end block", curr_height);
226263
}
@@ -290,6 +327,8 @@ impl FlusherShard {
290327
upper_tree.prune_nodes(start_twig_id, end_twig_id, youngest_twig_id);
291328
}
292329

330+
self.handle_proof_req();
331+
293332
//shard#0 must wait other shards to finish
294333
if shard_id == 0 {
295334
bar_set.metadb_bar.wait();
@@ -317,9 +356,9 @@ impl FlusherShard {
317356

318357
if shard_id == 0 {
319358
meta.set_curr_height(curr_height);
320-
meta.commit();
359+
let meta_info = meta.commit();
321360
drop(meta);
322-
match end_block_chan.send(curr_height) {
361+
match end_block_chan.send(meta_info) {
323362
Ok(_) => {
324363
//println!("{} end block", curr_height);
325364
}
@@ -468,7 +507,7 @@ mod flusher_tests {
468507
);
469508
assert_eq!(recovered_root, root);
470509
check_hash_consistency(&tree);
471-
let mut proof_path = tree.get_proof(SENTRY_COUNT as u64);
510+
let mut proof_path = tree.get_proof(SENTRY_COUNT as u64).unwrap();
472511
check_proof(&mut proof_path).unwrap();
473512
}
474513
}

qmdb/src/lib.rs

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ pub mod test_helper;
2323
use aes_gcm::{Aes256Gcm, Key, KeyInit};
2424
use byteorder::{BigEndian, ByteOrder};
2525
use entryfile::entrybuffer;
26+
use merkletree::proof::ProofPath;
2627
use parking_lot::RwLock;
2728
use std::collections::VecDeque;
2829
use std::fs;
2930
use std::path::Path;
3031
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
31-
use std::sync::Arc;
32+
use std::sync::{Arc, Condvar, Mutex};
3233
use std::thread;
3334
use threadpool::ThreadPool;
3435

@@ -38,13 +39,13 @@ use crate::def::{
3839
TWIG_SHIFT,
3940
};
4041
use crate::entryfile::{entry::sentry_entry, EntryBz, EntryCache, EntryFile};
41-
use crate::flusher::{Flusher, FlusherShard};
42+
use crate::flusher::{Flusher, FlusherShard, ProofReqElem};
4243
use crate::indexer::Indexer;
4344
use crate::merkletree::{
4445
recover::{bytes_to_edge_nodes, recover_tree},
4546
Tree,
4647
};
47-
use crate::metadb::MetaDB;
48+
use crate::metadb::{MetaDB, MetaInfo};
4849
use log::{debug, error, info};
4950

5051
#[cfg(all(target_os = "linux", feature = "directio"))]
@@ -65,6 +66,7 @@ pub struct AdsCore {
6566
entry_files: Vec<Arc<EntryFile>>,
6667
meta: Arc<RwLock<MetaDB>>,
6768
wrbuf_size: usize,
69+
proof_req_senders: Vec<SyncSender<ProofReqElem>>,
6870
}
6971

7072
fn get_ciphers(
@@ -112,7 +114,7 @@ impl AdsCore {
112114
pub fn new(
113115
task_hub: Arc<dyn TaskHub>,
114116
config: &config::Config,
115-
) -> (Self, Receiver<i64>, Flusher) {
117+
) -> (Self, Receiver<Arc<MetaInfo>>, Flusher) {
116118
#[cfg(feature = "tee_cipher")]
117119
assert!(config.aes_keys.unwrap().len() == 96);
118120

@@ -133,7 +135,7 @@ impl AdsCore {
133135
file_segment_size: usize,
134136
with_twig_file: bool,
135137
aes_keys: &Option<[u8; 96]>,
136-
) -> (Self, Receiver<i64>, Flusher) {
138+
) -> (Self, Receiver<Arc<MetaInfo>>, Flusher) {
137139
let (ciphers, idx_cipher, meta_db_cipher) = get_ciphers(aes_keys);
138140
let (data_dir, meta_dir, _indexer_dir) = Self::get_sub_dirs(dir);
139141

@@ -185,10 +187,35 @@ impl AdsCore {
185187
entry_files,
186188
meta: meta.clone(),
187189
wrbuf_size,
190+
proof_req_senders: flusher.get_proof_req_senders(),
188191
};
189192
(ads_core, eb_receiver, flusher)
190193
}
191194

195+
pub fn get_proof(&self, shard_id: usize, sn: u64) -> Result<ProofPath, String> {
196+
if cfg!(feature = "slow_hashing") {
197+
return Err("do not support proof in slow hashing mode".to_owned());
198+
}
199+
200+
let pair = Arc::new((Mutex::new((sn, Option::None)), Condvar::new()));
201+
202+
if let Err(er) = self.proof_req_senders[shard_id].send(Arc::clone(&pair)) {
203+
return Err(format!("send proof request failed: {:?}", er));
204+
}
205+
206+
// wait for the request to be handled
207+
let (lock, cvar) = &*pair;
208+
let mut sn_proof = lock.lock().unwrap();
209+
while sn_proof.1.is_none() {
210+
sn_proof = cvar.wait(sn_proof).unwrap();
211+
}
212+
213+
if let Err(er) = sn_proof.1.as_ref().unwrap() {
214+
return Err(format!("get proof failed: {:?}", er));
215+
}
216+
sn_proof.1.take().unwrap()
217+
}
218+
192219
pub fn get_entry_files(&self) -> Vec<Arc<EntryFile>> {
193220
let mut res = Vec::with_capacity(self.entry_files.len());
194221
for ef in self.entry_files.iter() {
@@ -401,7 +428,7 @@ impl AdsCore {
401428
meta.set_next_serial_num(shard_id, SENTRY_COUNT as u64);
402429
}
403430
meta.insert_extra_data(0, "".to_owned());
404-
meta.commit()
431+
meta.commit();
405432
}
406433

407434
pub fn check_entry(key_hash: &[u8], key: &[u8], entry_bz: &EntryBz) -> bool {
@@ -598,7 +625,8 @@ pub struct AdsWrap<T: Task> {
598625
ads: Arc<AdsCore>,
599626
cache: Arc<EntryCache>,
600627
cache_list: Vec<Arc<EntryCache>>,
601-
end_block_chan: Receiver<i64>, // when ads finish the prev block disk job, there will receive something.
628+
// when ads finish the prev block disk job, end_block_chan will receive MetaInfo
629+
end_block_chan: Receiver<Arc<MetaInfo>>,
602630
stop_height: i64,
603631
}
604632

@@ -689,11 +717,18 @@ impl<T: Task + 'static> AdsWrap<T> {
689717
self.ads.get_entry_files()
690718
}
691719

692-
pub fn flush(&mut self) {
720+
pub fn get_proof(&self, shard_id: usize, sn: u64) -> Result<ProofPath, String> {
721+
self.ads.get_proof(shard_id, sn)
722+
}
723+
724+
pub fn flush(&mut self) -> Vec<Arc<MetaInfo>> {
725+
let mut v = Vec::with_capacity(2);
693726
while self.task_hub.free_slot_count() < 2 {
694-
let height = self.end_block_chan.recv().unwrap();
695-
self.task_hub.end_block(height);
727+
let meta_info = self.end_block_chan.recv().unwrap();
728+
self.task_hub.end_block(meta_info.curr_height);
729+
v.push(meta_info);
696730
}
731+
v
697732
}
698733

699734
fn allocate_cache(&mut self) -> Arc<EntryCache> {
@@ -718,21 +753,27 @@ impl<T: Task + 'static> AdsWrap<T> {
718753
self.stop_height = height;
719754
}
720755

721-
pub fn start_block(&mut self, height: i64, tasks_manager: Arc<TasksManager<T>>) -> bool {
756+
pub fn start_block(
757+
&mut self,
758+
height: i64,
759+
tasks_manager: Arc<TasksManager<T>>,
760+
) -> (bool, Option<Arc<MetaInfo>>) {
722761
if height == self.stop_height + 1 {
723-
return false;
762+
return (false, Option::None);
724763
}
725764
self.cache = self.allocate_cache();
726765

766+
let mut meta_info = Option::None;
727767
if self.task_hub.free_slot_count() == 0 {
728768
// adscore and task_hub are busy, wait for them to finish an old block
729-
let height = self.end_block_chan.recv().unwrap();
730-
self.task_hub.end_block(height);
769+
let _meta_info = self.end_block_chan.recv().unwrap();
770+
self.task_hub.end_block(_meta_info.curr_height);
771+
meta_info = Some(_meta_info);
731772
}
732773

733774
self.task_hub
734775
.start_block(height, tasks_manager, self.cache.clone());
735-
true
776+
(true, meta_info)
736777
}
737778

738779
pub fn get_shared(&self) -> SharedAdsWrap {

0 commit comments

Comments
 (0)