From c9f0003150aa75a2d00eaed87b811b28c738fff8 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Wed, 13 Mar 2024 19:18:57 -0400 Subject: [PATCH] reporting correction and better debug --- veilid-core/src/rpc_processor/fanout_call.rs | 30 +++++++++++++++++++ .../src/rpc_processor/rpc_inspect_value.rs | 6 ++-- veilid-core/src/storage_manager/get_value.rs | 2 +- .../src/storage_manager/inspect_value.rs | 15 ++++++---- .../src/storage_manager/record_store/mod.rs | 20 ++----------- veilid-core/src/storage_manager/set_value.rs | 2 +- veilid-core/src/veilid_api/debug.rs | 16 ++++++++-- .../veilid_api/types/dht/dht_record_report.rs | 15 ++++++++-- veilid-core/src/veilid_api/types/dht/mod.rs | 25 ++++++++++++++++ .../src/veilid_api/types/dht/schema/mod.rs | 26 ++++++++++++++++ 10 files changed, 125 insertions(+), 32 deletions(-) diff --git a/veilid-core/src/rpc_processor/fanout_call.rs b/veilid-core/src/rpc_processor/fanout_call.rs index ed0725db..7b7330ba 100644 --- a/veilid-core/src/rpc_processor/fanout_call.rs +++ b/veilid-core/src/rpc_processor/fanout_call.rs @@ -21,6 +21,36 @@ pub(crate) struct FanoutResult { pub value_nodes: Vec, } +pub(crate) fn debug_fanout_result(result: &FanoutResult) -> String { + let kc = match result.kind { + FanoutResultKind::Timeout => "T", + FanoutResultKind::Finished => "F", + FanoutResultKind::Exhausted => "E", + }; + format!("{}:{}", kc, result.value_nodes.len()) +} + +pub(crate) fn debug_fanout_results(results: &[FanoutResult]) -> String { + let mut col = 0; + let mut out = String::new(); + let mut left = results.len(); + for r in results { + if col == 0 { + out += " "; + } + let sr = debug_fanout_result(r); + out += &sr; + out += ","; + col += 1; + left -= 1; + if col == 32 && left != 0 { + col = 0; + out += "\n" + } + } + out +} + pub(crate) type FanoutCallReturnType = RPCNetworkResult>; pub(crate) type FanoutNodeInfoFilter = Arc bool + Send + Sync>; diff --git a/veilid-core/src/rpc_processor/rpc_inspect_value.rs b/veilid-core/src/rpc_processor/rpc_inspect_value.rs index b7cc66bb..d68f4585 100644 --- a/veilid-core/src/rpc_processor/rpc_inspect_value.rs +++ b/veilid-core/src/rpc_processor/rpc_inspect_value.rs @@ -105,16 +105,16 @@ impl RPCProcessor { let (seqs, peers, descriptor) = inspect_value_a.destructure(); if debug_target_enabled!("dht") { let debug_string_answer = format!( - "OUT <== InspectValueA({} {:?}{} peers={}) <= {}", + "OUT <== InspectValueA({} {} peers={}) <= {} seqs:\n{}", key, - seqs, if descriptor.is_some() { " +desc" } else { "" }, peers.len(), - dest + dest, + debug_seqs(&seqs) ); log_dht!(debug "{}", debug_string_answer); diff --git a/veilid-core/src/storage_manager/get_value.rs b/veilid-core/src/storage_manager/get_value.rs index 6519454c..111479f0 100644 --- a/veilid-core/src/storage_manager/get_value.rs +++ b/veilid-core/src/storage_manager/get_value.rs @@ -199,7 +199,7 @@ impl StorageManager { kind, value_nodes: ctx.value_nodes.clone(), }; - log_dht!(debug "GetValue Fanout: {:?}", fanout_result); + log_network_result!(debug "GetValue Fanout: {:?}", fanout_result); Ok(OutboundGetValueResult { fanout_result, diff --git a/veilid-core/src/storage_manager/inspect_value.rs b/veilid-core/src/storage_manager/inspect_value.rs index 983bd2e4..10941c6f 100644 --- a/veilid-core/src/storage_manager/inspect_value.rs +++ b/veilid-core/src/storage_manager/inspect_value.rs @@ -15,8 +15,7 @@ impl DescriptorInfo { subkeys: &ValueSubkeyRangeSet, ) -> VeilidAPIResult { let schema = descriptor.schema().map_err(RPCError::invalid_format)?; - let subkeys = subkeys.intersect(&ValueSubkeyRangeSet::single_range(0, schema.max_subkey())); - + let subkeys = schema.truncate_subkeys(subkeys, Some(MAX_INSPECT_VALUE_A_SEQS_LEN)); Ok(Self { descriptor, subkeys, @@ -85,6 +84,7 @@ impl StorageManager { // Make do-inspect-value answer context let opt_descriptor_info = if let Some(descriptor) = &local_inspect_result.opt_descriptor { + // Get the descriptor info. This also truncates the subkeys list to what can be returned from the network. Some(DescriptorInfo::new(descriptor.clone(), &subkeys)?) } else { None @@ -127,6 +127,7 @@ impl StorageManager { if let Some(descriptor) = answer.descriptor { let mut ctx = context.lock(); if ctx.opt_descriptor_info.is_none() { + // Get the descriptor info. This also truncates the subkeys list to what can be returned from the network. let descriptor_info = match DescriptorInfo::new(Arc::new(descriptor.clone()), &subkeys) { Ok(v) => v, @@ -172,7 +173,11 @@ impl StorageManager { .map(|s| SubkeySeqCount { seq: *s, // One node has shown us the newest sequence numbers so far - value_nodes: vec![next_node.clone()], + value_nodes: if *s == ValueSeqNum::MAX { + vec![] + } else { + vec![next_node.clone()] + }, }) .collect(); } else { @@ -265,7 +270,7 @@ impl StorageManager { let ctx = context.lock(); let mut fanout_results = vec![]; for cs in &ctx.seqcounts { - let has_consensus = cs.value_nodes.len() > consensus_count; + let has_consensus = cs.value_nodes.len() >= consensus_count; let fanout_result = FanoutResult { kind: if has_consensus { FanoutResultKind::Finished @@ -277,7 +282,7 @@ impl StorageManager { fanout_results.push(fanout_result); } - log_dht!(debug "InspectValue Fanout ({:?}): {:?}", kind, fanout_results.iter().map(|fr| (fr.kind, fr.value_nodes.len())).collect::>()); + log_network_result!(debug "InspectValue Fanout ({:?}):\n{}", kind, debug_fanout_results(&fanout_results)); Ok(OutboundInspectValueResult { fanout_results, diff --git a/veilid-core/src/storage_manager/record_store/mod.rs b/veilid-core/src/storage_manager/record_store/mod.rs index fd3eba42..a8ccb7cd 100644 --- a/veilid-core/src/storage_manager/record_store/mod.rs +++ b/veilid-core/src/storage_manager/record_store/mod.rs @@ -801,23 +801,9 @@ where let Some((subkeys, opt_descriptor)) = self.with_record(key, |record| { // Get number of subkeys from schema and ensure we are getting the // right number of sequence numbers betwen that and what we asked for - let in_schema_subkeys = subkeys.intersect(&ValueSubkeyRangeSet::single_range( - 0, - record.schema().max_subkey(), - )); - - // Cap the number of total subkeys being inspected to the amount we can send across the wire - let truncated_subkeys = if let Some(nth_subkey) = - in_schema_subkeys.nth_subkey(MAX_INSPECT_VALUE_A_SEQS_LEN) - { - in_schema_subkeys.difference(&ValueSubkeyRangeSet::single_range( - nth_subkey, - ValueSubkey::MAX, - )) - } else { - in_schema_subkeys - }; - + let truncated_subkeys = record + .schema() + .truncate_subkeys(&subkeys, Some(MAX_INSPECT_VALUE_A_SEQS_LEN)); ( truncated_subkeys, if want_descriptor { diff --git a/veilid-core/src/storage_manager/set_value.rs b/veilid-core/src/storage_manager/set_value.rs index ed0d6523..f5bb3550 100644 --- a/veilid-core/src/storage_manager/set_value.rs +++ b/veilid-core/src/storage_manager/set_value.rs @@ -183,7 +183,7 @@ impl StorageManager { kind, value_nodes: ctx.value_nodes.clone(), }; - log_dht!(debug "SetValue Fanout: {:?}", fanout_result); + log_network_result!(debug "SetValue Fanout: {:?}", fanout_result); Ok(OutboundSetValueResult { fanout_result, diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 7d7f7c37..2a771ddc 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -149,6 +149,9 @@ fn get_dht_schema(text: &str) -> Option> { if text.is_empty() { return None; } + if let Ok(n) = u16::from_str(text) { + return Some(DHTSchema::dflt(n)); + } Some(deserialize_json::(text)) } @@ -1479,7 +1482,13 @@ impl VeilidAPI { let mut dc = DEBUG_CACHE.lock(); dc.opened_record_contexts.insert(*record.key(), rc); - Ok(format!("Created: {:?} : {:?}", record.key(), record)) + Ok(format!( + "Created: {} {}:{}\n{:?}", + record.key(), + record.owner(), + record.owner_secret().unwrap(), + record + )) } async fn debug_record_open(&self, args: Vec) -> VeilidAPIResult { @@ -1965,7 +1974,10 @@ record list is: ipv4|ipv6 is: public|local is: VLD0 - is: a json dht schema, default is '{"kind":"DFLT","o_cnt":1}' + is: + * a single-quoted json dht schema, or + * an integer number for a DFLT schema subkey count. + default is '{"kind":"DFLT","o_cnt":1}' is: local, syncget, syncset, updateget, updateset is: a number: 2 is: diff --git a/veilid-core/src/veilid_api/types/dht/dht_record_report.rs b/veilid-core/src/veilid_api/types/dht/dht_record_report.rs index 33a8f2a6..84de783e 100644 --- a/veilid-core/src/veilid_api/types/dht/dht_record_report.rs +++ b/veilid-core/src/veilid_api/types/dht/dht_record_report.rs @@ -1,9 +1,7 @@ use super::*; /// DHT Record Report -#[derive( - Debug, Default, Clone, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, JsonSchema, -)] +#[derive(Default, Clone, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[cfg_attr( target_arch = "wasm32", derive(Tsify), @@ -45,6 +43,17 @@ impl DHTRecordReport { } } +impl fmt::Debug for DHTRecordReport { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "DHTRecordReport {{\n subkeys: {:?}\n local_seqs:\n{}\n remote_seqs:\n{}\n}}\n", + &self.subkeys, + &debug_seqs(&self.local_seqs), + &debug_seqs(&self.network_seqs) + ) + } +} /// DHT Record Report Scope #[derive( Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema, diff --git a/veilid-core/src/veilid_api/types/dht/mod.rs b/veilid-core/src/veilid_api/types/dht/mod.rs index d5c9b4cc..693a1c68 100644 --- a/veilid-core/src/veilid_api/types/dht/mod.rs +++ b/veilid-core/src/veilid_api/types/dht/mod.rs @@ -18,3 +18,28 @@ pub type ValueSubkey = u32; /// Value sequence number #[cfg_attr(target_arch = "wasm32", declare)] pub type ValueSeqNum = u32; + +pub(crate) fn debug_seqs(seqs: &[ValueSeqNum]) -> String { + let mut col = 0; + let mut out = String::new(); + let mut left = seqs.len(); + for s in seqs { + if col == 0 { + out += " "; + } + let sc = if *s == ValueSeqNum::MAX { + "-".to_owned() + } else { + s.to_string() + }; + out += ≻ + out += ","; + col += 1; + left -= 1; + if col == 32 && left != 0 { + col = 0; + out += "\n" + } + } + out +} diff --git a/veilid-core/src/veilid_api/types/dht/schema/mod.rs b/veilid-core/src/veilid_api/types/dht/schema/mod.rs index 78138b89..e384e49f 100644 --- a/veilid-core/src/veilid_api/types/dht/schema/mod.rs +++ b/veilid-core/src/veilid_api/types/dht/schema/mod.rs @@ -75,6 +75,32 @@ impl DHTSchema { DHTSchema::SMPL(s) => s.is_member(key), } } + + /// Truncate a subkey range set to the schema + /// Optionally also trim to maximum number of subkeys in the range + pub fn truncate_subkeys( + &self, + subkeys: &ValueSubkeyRangeSet, + opt_max_subkey_len: Option, + ) -> ValueSubkeyRangeSet { + // Get number of subkeys from schema and trim to the bounds of the schema + let in_schema_subkeys = + subkeys.intersect(&ValueSubkeyRangeSet::single_range(0, self.max_subkey())); + + // Cap the number of total subkeys being inspected to the amount we can send across the wire + if let Some(max_subkey_len) = opt_max_subkey_len { + if let Some(nth_subkey) = in_schema_subkeys.nth_subkey(max_subkey_len) { + in_schema_subkeys.difference(&ValueSubkeyRangeSet::single_range( + nth_subkey, + ValueSubkey::MAX, + )) + } else { + in_schema_subkeys + } + } else { + in_schema_subkeys + } + } } impl Default for DHTSchema {