use crate::bloom::BloomFilter;
use crate::LOG_TARGET_CONFLICTS;
use bytes::Bytes;
use papaya::HashSet;
use std::collections::BTreeMap;
use std::sync::Arc;
use tracing::debug;
pub struct Commit {
pub(crate) id: u64,
pub(crate) writeset: Arc<BTreeMap<Bytes, Option<Bytes>>>,
pub(crate) writeset_bloom: BloomFilter,
pub(crate) min_key: Bytes,
pub(crate) max_key: Bytes,
}
pub struct Merge {
pub(crate) id: u64,
pub(crate) writeset: Arc<BTreeMap<Bytes, Option<Bytes>>>,
}
impl Commit {
pub fn is_disjoint_readset_bloom(&self, other: &HashSet<Bytes>, bloom: &BloomFilter) -> bool {
if bloom.is_empty() {
return true;
}
let mut any_possible = false;
for key in self.writeset.keys() {
if bloom.may_contain(key) {
any_possible = true;
break;
}
}
if !any_possible {
return true;
}
self.is_disjoint_readset(other)
}
pub fn is_disjoint_readset(&self, other: &HashSet<Bytes>) -> bool {
let other = other.pin();
if !other.is_empty() {
if other.len() < self.writeset.len() {
for key in other.iter() {
if self.writeset.contains_key(key) {
#[cfg(debug_assertions)]
debug!(target: LOG_TARGET_CONFLICTS, "KeyReadConflict involving {:?}", key);
return false;
}
}
} else {
for key in self.writeset.keys() {
if other.contains(key) {
#[cfg(debug_assertions)]
debug!(target: LOG_TARGET_CONFLICTS, "KeyReadConflict involving {:?}", key);
return false;
}
}
}
}
true
}
pub fn is_disjoint_writeset_bloom(&self, other: &Arc<Commit>) -> bool {
if self.max_key < other.min_key || other.max_key < self.min_key {
return true;
}
let mut any_possible = false;
for key in self.writeset.keys() {
if other.writeset_bloom.may_contain(key) {
any_possible = true;
break;
}
}
if !any_possible {
return true;
}
self.is_disjoint_writeset(other)
}
pub fn may_overlap_range(&self, range_start: &Bytes, range_end: &Bytes) -> bool {
self.min_key < *range_end && self.max_key >= *range_start
}
pub fn is_disjoint_writeset(&self, other: &Arc<Commit>) -> bool {
let mut a = self.writeset.keys();
let mut b = other.writeset.keys();
let mut next_a = a.next();
let mut next_b = b.next();
while let (Some(ka), Some(kb)) = (next_a, next_b) {
match ka.cmp(kb) {
std::cmp::Ordering::Less => next_a = a.next(),
std::cmp::Ordering::Greater => next_b = b.next(),
std::cmp::Ordering::Equal => {
#[cfg(debug_assertions)]
debug!(target: LOG_TARGET_CONFLICTS, "KeyWriteConflict involving {:?}", ka);
return false;
}
}
}
true
}
}