mirror of
https://github.com/aljazceru/pubky-core.git
synced 2025-12-31 21:04:34 +01:00
fix: ref_count overflow
This commit is contained in:
@@ -192,15 +192,24 @@ fn hash(bytes: &[u8]) -> Hash {
|
||||
hasher.finalize()
|
||||
}
|
||||
|
||||
enum RefCountDiff {
|
||||
Increment,
|
||||
Decrement,
|
||||
}
|
||||
|
||||
fn increment_ref_count(child: Option<Hash>, 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<Hash>, 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<Hash>, ref_diff: i8, table: &mut Table<&[u8], (u64, &[u8])>) {
|
||||
fn update_ref_count(
|
||||
child: Option<Hash>,
|
||||
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<Hash>, 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<Hash>, 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user