make next_entries() smarter about fitting Transactions into a Blob
This commit is contained in:
@ -78,33 +78,58 @@ pub fn next_entries_mut(
|
|||||||
cur_hashes: &mut u64,
|
cur_hashes: &mut u64,
|
||||||
transactions: Vec<Transaction>,
|
transactions: Vec<Transaction>,
|
||||||
) -> Vec<Entry> {
|
) -> Vec<Entry> {
|
||||||
if transactions.is_empty() {
|
// TODO: find a magic number that works better than | ?
|
||||||
|
// V
|
||||||
|
if transactions.is_empty() || transactions.len() == 1 {
|
||||||
vec![Entry::new_mut(start_hash, cur_hashes, transactions, false)]
|
vec![Entry::new_mut(start_hash, cur_hashes, transactions, false)]
|
||||||
} else {
|
} else {
|
||||||
let mut chunk_len = transactions.len();
|
let mut start = 0;
|
||||||
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
// check for fit, make sure they can be serialized
|
while start < transactions.len() {
|
||||||
while !Entry::will_fit(transactions[0..chunk_len].to_vec()) {
|
let mut chunk_end = transactions.len();
|
||||||
chunk_len /= 2;
|
let mut upper = chunk_end;
|
||||||
}
|
let mut lower = start;
|
||||||
|
let mut next = chunk_end; // be optimistic that all will fit
|
||||||
|
|
||||||
let mut num_chunks = if transactions.len() % chunk_len == 0 {
|
// binary search for how many transactions will fit in an Entry (i.e. a BLOB)
|
||||||
transactions.len() / chunk_len
|
loop {
|
||||||
} else {
|
debug!(
|
||||||
transactions.len() / chunk_len + 1
|
"chunk_end {}, upper {} lower {} next {} transactions.len() {}",
|
||||||
};
|
chunk_end,
|
||||||
|
upper,
|
||||||
let mut entries = Vec::with_capacity(num_chunks);
|
lower,
|
||||||
|
next,
|
||||||
for chunk in transactions.chunks(chunk_len) {
|
transactions.len()
|
||||||
num_chunks -= 1;
|
);
|
||||||
|
if Entry::will_fit(transactions[start..chunk_end].to_vec()) {
|
||||||
|
next = (upper + chunk_end) / 2;
|
||||||
|
lower = chunk_end;
|
||||||
|
debug!(
|
||||||
|
"chunk_end {} fits, maybe too well? trying {}",
|
||||||
|
chunk_end, next
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
next = (lower + chunk_end) / 2;
|
||||||
|
upper = chunk_end;
|
||||||
|
debug!("chunk_end {} doesn't fit! trying {}", chunk_end, next);
|
||||||
|
}
|
||||||
|
// same as last time
|
||||||
|
if next == chunk_end {
|
||||||
|
debug!("converged on chunk_end {}", chunk_end);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chunk_end = next;
|
||||||
|
}
|
||||||
entries.push(Entry::new_mut(
|
entries.push(Entry::new_mut(
|
||||||
start_hash,
|
start_hash,
|
||||||
cur_hashes,
|
cur_hashes,
|
||||||
chunk.to_vec(),
|
transactions[start..chunk_end].to_vec(),
|
||||||
num_chunks > 0,
|
transactions.len() - chunk_end > 0,
|
||||||
));
|
));
|
||||||
|
start = chunk_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
entries
|
entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,7 +242,7 @@ mod tests {
|
|||||||
transactions.extend(large_transactions);
|
transactions.extend(large_transactions);
|
||||||
|
|
||||||
let entries0 = next_entries(&id, 0, transactions.clone());
|
let entries0 = next_entries(&id, 0, transactions.clone());
|
||||||
assert_eq!(entries0.len(), 5);
|
assert!(entries0.len() > 2);
|
||||||
assert!(entries0[0].has_more);
|
assert!(entries0[0].has_more);
|
||||||
assert!(!entries0[entries0.len() - 1].has_more);
|
assert!(!entries0[entries0.len() - 1].has_more);
|
||||||
assert!(entries0.verify(&id));
|
assert!(entries0.verify(&id));
|
||||||
|
Reference in New Issue
Block a user