From 33d83ce435fb6dd0480cce89adbfa9bf02fa64d0 Mon Sep 17 00:00:00 2001 From: nazeh Date: Tue, 19 Dec 2023 23:05:35 +0300 Subject: [PATCH] fix: ref_count overflow --- mast/src/node.rs | 31 +++++++-- mast/src/treap.rs | 159 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 174 insertions(+), 16 deletions(-) diff --git a/mast/src/node.rs b/mast/src/node.rs index bcf2477..550eb00 100644 --- a/mast/src/node.rs +++ b/mast/src/node.rs @@ -192,15 +192,24 @@ fn hash(bytes: &[u8]) -> Hash { hasher.finalize() } +enum RefCountDiff { + Increment, + Decrement, +} + fn increment_ref_count(child: Option, table: &mut Table<&[u8], (u64, &[u8])>) { - update_ref_count(child, 1, table); + update_ref_count(child, RefCountDiff::Increment, table); } fn decrement_ref_count(child: Option, table: &mut Table<&[u8], (u64, &[u8])>) { - update_ref_count(child, -1, table); + update_ref_count(child, RefCountDiff::Decrement, table); } -fn update_ref_count(child: Option, ref_diff: i8, table: &mut Table<&[u8], (u64, &[u8])>) { +fn update_ref_count( + child: Option, + ref_diff: RefCountDiff, + table: &mut Table<&[u8], (u64, &[u8])>, +) { if let Some(hash) = child { let mut existing = table .get(hash.as_bytes().as_slice()) @@ -213,6 +222,17 @@ fn update_ref_count(child: Option, ref_diff: i8, table: &mut Table<&[u8], }; drop(existing); + let ref_count = match ref_diff { + RefCountDiff::Increment => ref_count + 1, + RefCountDiff::Decrement => { + if ref_count > 0 { + ref_count - 1 + } else { + ref_count + } + } + }; + match ref_count { 0 => { // TODO: This doesn't seem to work yet. @@ -226,10 +246,7 @@ fn update_ref_count(child: Option, ref_diff: i8, table: &mut Table<&[u8], table.remove(hash.as_bytes().as_slice()); } _ => { - table.insert( - hash.as_bytes().as_slice(), - (ref_count + ref_diff as u64, bytes.as_slice()), - ); + table.insert(hash.as_bytes().as_slice(), (ref_count, bytes.as_slice())); } } } diff --git a/mast/src/treap.rs b/mast/src/treap.rs index 6bb586c..6f9d4e2 100644 --- a/mast/src/treap.rs +++ b/mast/src/treap.rs @@ -268,15 +268,156 @@ mod test { let mut treap = HashTreap::new(&db); - let mut keys = ["A", "C", "D", "F", "G", "H", "M", "P", "X", "Y"]; - // let mut keys = [ - // "D", "N", "P", "X", "F", "Z", "Y", "A", "G", "C", "M", "H", "I", "J", - // ]; - let mut keys = ["A", "B", "C"]; - // let mut keys = ["A", "B"]; - // let mut keys = ["A"]; - // keys.reverse(); - // keys.reverse(); // Overflowing stack! damn recursion. + let mut keys = [ + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", + "R", "S", "T", "U", "V", "W", "X", "Y", "Z", // + "A0", "B0", "C0", "D0", "E0", "F0", "G0", "H0", "I0", "J0", "K0", "L0", "M0", "N0", + "O0", "P0", "Q0", "R0", "S0", "T0", "U0", "V0", "W0", "X0", "Y0", "Z0", // + "A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1", "I1", "J1", "K1", "L1", "M1", "N1", + "O1", "P1", "Q1", "R1", "S1", "T1", "U1", "V1", "W1", "X1", "Y1", "Z1", + ]; + let mut keys = [ + "abacus", + "abdomen", + "abdominal", + "abide", + "abiding", + "ability", + "ablaze", + "able", + "abnormal", + "abrasion", + "abrasive", + "abreast", + "abridge", + "abroad", + "abruptly", + "absence", + "absentee", + "absently", + "absinthe", + "absolute", + "absolve", + "abstain", + "abstract", + "absurd", + "accent", + "acclaim", + "acclimate", + "accompany", + "account", + "accuracy", + "accurate", + "accustom", + "acetone", + "achiness", + "aching", + "acid", + "acorn", + "acquaint", + "acquire", + "acre", + "acrobat", + "acronym", + "acting", + "action", + "activate", + "activator", + "active", + "activism", + "activist", + "activity", + "actress", + "acts", + "acutely", + "acuteness", + "aeration", + "aerobics", + "aerosol", + "aerospace", + "afar", + "affair", + "affected", + "affecting", + "affection", + "affidavit", + "affiliate", + "affirm", + "affix", + "afflicted", + "affluent", + "afford", + "affront", + "aflame", + "afloat", + "aflutter", + "afoot", + "afraid", + "afterglow", + "afterlife", + "aftermath", + "aftermost", + "afternoon", + "aged", + "ageless", + "agency", + "agenda", + "agent", + "aggregate", + "aghast", + "agile", + "agility", + "aging", + "agnostic", + "agonize", + "agonizing", + "agony", + "agreeable", + "agreeably", + "agreed", + "agreeing", + "agreement", + "aground", + "ahead", + "ahoy", + "aide", + "aids", + "aim", + "ajar", + "alabaster", + "alarm", + "albatross", + "album", + "alfalfa", + "algebra", + "algorithm", + "alias", + "alibi", + "alienable", + "alienate", + "aliens", + "alike", + ]; + + for key in keys.iter() { + treap.insert(key.as_bytes(), b"0"); + } + + assert!(treap.verify_ranks()); + println!("{}", treap.as_mermaid_graph()) + } + + fn failin_cases() { + // Create an in-memory database + let file = tempfile::NamedTempFile::new().unwrap(); + let db = Database::create(file.path()).unwrap(); + + let mut treap = HashTreap::new(&db); + + // TODO: fix this cases + let mut keys = [ + "D", "N", "P", "X", "F", "Z", "Y", "A", "G", "C", "M", "H", "I", "J", + ]; for key in keys.iter() { treap.insert(key.as_bytes(), b"0");