use std::collections::HashMap;
use std::collections::btree_map::{BTreeMap, Range, Iter as BtmIter, IntoIter as BtmIntoIter};
use std::collections::hash_map::{Iter as HmIter, IntoIter as HmIntoIter, Entry as HmEntry};
use std::collections::Bound::*;
use std::cmp::Ordering::*;
use std::iter::{Peekable, Iterator as StdIterator};
use super::Result;
use self::NextIterValue::*;
#[derive(Debug, Clone)]
pub struct Changes {
data: BTreeMap<Vec<u8>, Change>,
}
impl Changes {
fn new() -> Self {
Self { data: BTreeMap::new() }
}
pub fn iter(&self) -> BtmIter<Vec<u8>, Change> {
self.data.iter()
}
}
#[derive(Debug)]
pub struct ChangesIterator {
inner: BtmIntoIter<Vec<u8>, Change>,
}
impl StdIterator for ChangesIterator {
type Item = (Vec<u8>, Change);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
impl IntoIterator for Changes {
type Item = (Vec<u8>, Change);
type IntoIter = ChangesIterator;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter { inner: self.data.into_iter() }
}
}
#[derive(Debug, Clone)]
pub struct Patch {
changes: HashMap<String, Changes>,
}
impl Patch {
fn new() -> Self {
Self { changes: HashMap::new() }
}
fn changes(&self, name: &str) -> Option<&Changes> {
self.changes.get(name)
}
fn changes_mut(&mut self, name: &str) -> Option<&mut Changes> {
self.changes.get_mut(name)
}
fn changes_entry(&mut self, name: String) -> HmEntry<String, Changes> {
self.changes.entry(name)
}
fn insert_changes(&mut self, name: String, changes: Changes) {
self.changes.insert(name, changes);
}
pub fn iter(&self) -> HmIter<String, Changes> {
self.changes.iter()
}
pub fn len(&self) -> usize {
self.changes.iter().fold(0, |acc, (_, changes)| {
acc + changes.data.len()
})
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[derive(Debug)]
pub struct PatchIterator {
inner: HmIntoIter<String, Changes>,
}
impl StdIterator for PatchIterator {
type Item = (String, Changes);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
impl IntoIterator for Patch {
type Item = (String, Changes);
type IntoIter = PatchIterator;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter { inner: self.changes.into_iter() }
}
}
pub type Iter<'a> = Box<Iterator + 'a>;
#[derive(Debug, Clone, PartialEq)]
pub enum Change {
Put(Vec<u8>),
Delete,
}
pub struct Fork {
snapshot: Box<Snapshot>,
patch: Patch,
changelog: Vec<(String, Vec<u8>, Option<Change>)>,
logged: bool,
}
struct ForkIter<'a> {
snapshot: Iter<'a>,
changes: Option<Peekable<Range<'a, Vec<u8>, Change>>>,
}
#[derive(Debug, PartialEq, Eq)]
enum NextIterValue {
Stored,
Replaced,
Inserted,
Deleted,
MissDeleted,
Finished,
}
pub trait Database: Send + Sync + 'static {
fn snapshot(&self) -> Box<Snapshot>;
fn fork(&self) -> Fork {
Fork {
snapshot: self.snapshot(),
patch: Patch::new(),
changelog: Vec::new(),
logged: false,
}
}
fn merge(&self, patch: Patch) -> Result<()>;
fn merge_sync(&self, patch: Patch) -> Result<()>;
}
pub trait Snapshot: 'static {
fn get(&self, name: &str, key: &[u8]) -> Option<Vec<u8>>;
fn contains(&self, name: &str, key: &[u8]) -> bool {
self.get(name, key).is_some()
}
fn iter<'a>(&'a self, name: &str, from: &[u8]) -> Iter<'a>;
}
pub trait Iterator {
fn next(&mut self) -> Option<(&[u8], &[u8])>;
fn peek(&mut self) -> Option<(&[u8], &[u8])>;
}
impl Snapshot for Fork {
fn get(&self, name: &str, key: &[u8]) -> Option<Vec<u8>> {
if let Some(changes) = self.patch.changes(name) {
if let Some(change) = changes.data.get(key) {
match *change {
Change::Put(ref v) => return Some(v.clone()),
Change::Delete => return None,
}
}
}
self.snapshot.get(name, key)
}
fn contains(&self, name: &str, key: &[u8]) -> bool {
if let Some(changes) = self.patch.changes(name) {
if let Some(change) = changes.data.get(key) {
match *change {
Change::Put(..) => return true,
Change::Delete => return false,
}
}
}
self.snapshot.contains(name, key)
}
fn iter<'a>(&'a self, name: &str, from: &[u8]) -> Iter<'a> {
let range = (Included(from), Unbounded);
let changes = match self.patch.changes(name) {
Some(changes) => Some(changes.data.range::<[u8], _>(range).peekable()),
None => None,
};
Box::new(ForkIter {
snapshot: self.snapshot.iter(name, from),
changes,
})
}
}
impl Fork {
pub fn checkpoint(&mut self) {
if self.logged {
panic!("call checkpoint before rollback or commit");
}
self.logged = true;
}
pub fn commit(&mut self) {
if !self.logged {
panic!("call commit before checkpoint");
}
self.changelog.clear();
self.logged = false;
}
pub fn rollback(&mut self) {
if !self.logged {
panic!("call rollback before checkpoint");
}
for (name, k, c) in self.changelog.drain(..).rev() {
if let Some(changes) = self.patch.changes_mut(&name) {
match c {
Some(change) => changes.data.insert(k, change),
None => changes.data.remove(&k),
};
}
}
self.logged = false;
}
pub fn put(&mut self, name: &str, key: Vec<u8>, value: Vec<u8>) {
let changes = self.patch.changes_entry(name.to_string()).or_insert_with(
Changes::new,
);
if self.logged {
self.changelog.push((
name.to_string(),
key.clone(),
changes.data.insert(key, Change::Put(value)),
));
} else {
changes.data.insert(key, Change::Put(value));
}
}
pub fn remove(&mut self, name: &str, key: Vec<u8>) {
let changes = self.patch.changes_entry(name.to_string()).or_insert_with(
Changes::new,
);
if self.logged {
self.changelog.push((
name.to_string(),
key.clone(),
changes.data.insert(key, Change::Delete),
));
} else {
changes.data.insert(key, Change::Delete);
}
}
pub fn remove_by_prefix(&mut self, name: &str, prefix: Option<&Vec<u8>>) {
let changes = self.patch.changes_entry(name.to_string()).or_insert_with(
Changes::new,
);
if let Some(prefix) = prefix {
let keys = changes
.data
.range::<Vec<u8>, _>((Included(prefix), Unbounded))
.map(|(k, _)| k.to_vec())
.take_while(|k| k.starts_with(prefix))
.collect::<Vec<_>>();
for k in keys {
changes.data.remove(&k);
}
} else {
changes.data.clear();
}
let mut iter = self.snapshot.iter(
name,
prefix.map_or(&[], |k| k.as_slice()),
);
while let Some((k, ..)) = iter.next() {
let change = changes.data.insert(k.to_vec(), Change::Delete);
if self.logged {
self.changelog.push((name.to_string(), k.to_vec(), change));
}
}
}
pub fn into_patch(self) -> Patch {
self.patch
}
pub fn patch(&self) -> &Patch {
&self.patch
}
pub fn merge(&mut self, patch: Patch) {
if self.logged {
panic!("call merge before commit or rollback");
}
for (name, changes) in patch {
if let Some(in_changes) = self.patch.changes_mut(&name) {
in_changes.data.extend(changes.into_iter());
continue;
}
{
self.patch.insert_changes(name.to_owned(), changes);
}
}
}
}
impl AsRef<Snapshot> for Snapshot + 'static {
fn as_ref(&self) -> &Snapshot {
self
}
}
impl AsRef<Snapshot> for Fork {
fn as_ref(&self) -> &Snapshot {
self
}
}
impl ::std::fmt::Debug for Fork {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fork(..)")
}
}
impl<'a> ForkIter<'a> {
fn step(&mut self) -> NextIterValue {
if let Some(ref mut changes) = self.changes {
match changes.peek() {
Some(&(k, change)) => {
match self.snapshot.peek() {
Some((key, ..)) => {
match *change {
Change::Put(..) => {
match k[..].cmp(key) {
Equal => Replaced,
Less => Inserted,
Greater => Stored,
}
}
Change::Delete => {
match k[..].cmp(key) {
Equal => Deleted,
Less => MissDeleted,
Greater => Stored,
}
}
}
}
None => {
match *change {
Change::Put(..) => Inserted,
Change::Delete => MissDeleted,
}
}
}
}
None => {
match self.snapshot.peek() {
Some(..) => Stored,
None => Finished,
}
}
}
} else {
match self.snapshot.peek() {
Some(..) => Stored,
None => Finished,
}
}
}
}
impl<'a> Iterator for ForkIter<'a> {
fn next(&mut self) -> Option<(&[u8], &[u8])> {
loop {
match self.step() {
Stored => return self.snapshot.next(),
Replaced => {
self.snapshot.next();
return self.changes.as_mut().unwrap().next().map(|(key, change)| {
(
key.as_slice(),
match *change {
Change::Put(ref value) => value.as_slice(),
Change::Delete => unreachable!(),
},
)
});
}
Inserted => {
return self.changes.as_mut().unwrap().next().map(|(key, change)| {
(
key.as_slice(),
match *change {
Change::Put(ref value) => value.as_slice(),
Change::Delete => unreachable!(),
},
)
})
}
Deleted => {
self.changes.as_mut().unwrap().next();
self.snapshot.next();
}
MissDeleted => {
self.changes.as_mut().unwrap().next();
}
Finished => return None,
}
}
}
fn peek(&mut self) -> Option<(&[u8], &[u8])> {
loop {
match self.step() {
Stored => return self.snapshot.peek(),
Replaced | Inserted => {
return self.changes.as_mut().unwrap().peek().map(|&(key, change)| {
(
key.as_slice(),
match *change {
Change::Put(ref value) => value.as_slice(),
Change::Delete => unreachable!(),
},
)
})
}
Deleted => {
self.changes.as_mut().unwrap().next();
self.snapshot.next();
}
MissDeleted => {
self.changes.as_mut().unwrap().next();
}
Finished => return None,
}
}
}
}
impl<T: Database> From<T> for Box<Database> {
fn from(db: T) -> Self {
Box::new(db) as Box<Database>
}
}