diff --git a/Cargo.toml b/Cargo.toml index fede9e4..da5f6d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,4 +36,4 @@ num-derive = "0.3" num-traits = "0.2" # not this one, really, really bad dependencies #sysinfo = "0.15.0" -lazy_static = "1.4.0" \ No newline at end of file +lazy_static = "1.4.0" diff --git a/src/db.rs b/src/db.rs index 12390be..788630c 100644 --- a/src/db.rs +++ b/src/db.rs @@ -15,20 +15,19 @@ Like store, */ -use std::fs::{File, OpenOptions}; +use std::{fs::{File, OpenOptions}, marker::PhantomData}; use std::io::{Seek, SeekFrom, Read, Write}; use byteorder::*; use std::collections::*; use std::hash::*; use std::fmt::{Debug}; use std::convert::From; -use crate::helpers; +use crate::helpers::{self, Holder}; use crate::settings::SETTINGS; use crate::LOG; pub (crate) const MAX_BUFFER_LENGTH : u64 = 10 * 1024 * 1024 * 1024; // 10GB - /** Marker trait for readonly datastore records. A record is readonly if it does not support updates, such as CommitInfo - once we have it, there is no way to overwrite its value, unlike for instance project heads. @@ -201,7 +200,7 @@ pub struct Indexer = u64, ID : Id = u64 > name : String, f : File, size : u64, - why_oh_why : std::marker::PhantomData<(T, ID)> + _t : std::marker::PhantomData<(T, ID)> } impl, ID : Id> Indexer { @@ -213,8 +212,8 @@ impl, ID : Id> Indexer { f = OpenOptions::new().read(true).write(true).create(true).open(format!("{}/{}.idx", root, name)).unwrap(); } let size = f.seek(SeekFrom::End(0)).unwrap() / T::SIZE; - return Indexer{ name : name.to_owned(), f, size, why_oh_why : std::marker::PhantomData{} }; - } + return Indexer{ name : name.to_owned(), f, size, _t : std::marker::PhantomData{} }; + } pub fn get(& mut self, id : ID) -> Option { if id.into() < self.size { @@ -260,39 +259,59 @@ impl, ID : Id> Indexer { self.f.seek(SeekFrom::End(0)).unwrap(); } - pub fn iter(& mut self) -> IndexerIterator { + pub fn iter<'a>(&'a mut self) -> impl Iterator + 'a { + self.f.seek(SeekFrom::Start(0)).unwrap(); + return IndexerIterator{indexer: Holder::Ref(self), id : ID::from(0), max_offset: u64::MAX}; + } + + pub fn into_iter<'a>(mut self) -> impl Iterator + 'a where Self: 'a{ + self.f.seek(SeekFrom::Start(0)).unwrap(); + return IndexerIterator{indexer: Holder::Own(self), id : ID::from(0), max_offset: u64::MAX }; + } + + pub fn savepoint_iter<'a>(&'a mut self, sp : & Savepoint) -> impl Iterator + 'a { + let max_offset = sp.limit_for(&self.name); self.f.seek(SeekFrom::Start(0)).unwrap(); - return IndexerIterator{indexer : self, id : 0, max_offset: u64::MAX}; + return IndexerIterator{indexer : Holder::Ref(self), id: ID::from(0), max_offset }; } - pub fn savepoint_iter(& mut self, sp : & Savepoint) -> IndexerIterator { - let max_offset = sp.limit_for(& self.name); + pub fn into_savepoint_iter<'a>(mut self, sp : & Savepoint) ->impl Iterator + 'a where Self: 'a { + let max_offset = sp.limit_for(&self.name); self.f.seek(SeekFrom::Start(0)).unwrap(); - return IndexerIterator{indexer : self, id : 0, max_offset }; + return IndexerIterator{indexer: Holder::Own(self), id: ID::from(0), max_offset }; } } -pub struct IndexerIterator<'a, T : Indexable + Serializable, ID : Id = u64> { - indexer : &'a mut Indexer, - id : u64, - max_offset : u64, +pub struct IndexerIterator<'a, T, ID> +where + T: Indexable + Serializable, + ID: Id, +{ + indexer: Holder<'a, Indexer>, + id: ID, + max_offset: u64, } -impl<'a, T : Indexable + Serializable, ID : Id> Iterator for IndexerIterator<'a, T, ID> { +impl<'a, T, ID> Iterator for IndexerIterator<'a, T, ID> +where + T: Indexable + Serializable, + ID: Id, +{ type Item = (ID, T); - fn next(& mut self) -> Option<(ID, T)> { + fn next(&mut self) -> Option<(ID, T)> { + let uid = >::into(self.id); loop { if self.indexer.f.seek(SeekFrom::Current(0)).unwrap() >= self.max_offset { return None; - } else if self.id == self.indexer.len() as u64 { + } else if uid == self.indexer.len() as u64 { return None; } else { - let id = ID::from(self.id); - let result = T::deserialize(& mut self.indexer.f); - self.id += 1; - return Some((id, result)); + let nid = self.id; + let result = T::deserialize(&mut self.indexer.f); + self.id = ID::from(uid + 1u64); + return Some((nid, result)); } } } @@ -302,14 +321,21 @@ impl<'a, T : Indexable + Serializable, ID : Id> Iterator for IndexerIt Store is an indexed updatable container that keeps history of updates. */ -pub struct Store, ID : Id = u64> { +pub struct Store +where + T: Serializable, + ID: Id +{ pub (crate) indexer : Indexer, pub (crate) f : File, - why_oh_why : std::marker::PhantomData, + _t : std::marker::PhantomData, } -impl, ID : Id> Store { - +impl, ID : Id> Store +where + T: Serializable, + ID: Id +{ pub fn new(root : & str, name : & str, readonly : bool) -> Store { let f; if readonly { @@ -320,7 +346,7 @@ impl, ID : Id> Store { let mut result = Store{ indexer : Indexer::new(root, name, readonly), f, - why_oh_why : std::marker::PhantomData{} + _t : std::marker::PhantomData{} }; LOG!(" {}: indices {}, size {}", name, result.indexer.len(), result.f.seek(SeekFrom::End(0)).unwrap()); return result; @@ -432,23 +458,46 @@ impl, ID : Id> Store { Returns the latest stored value for every id. The ids are guaranteed to be increasing. */ - pub fn iter(& mut self) -> StoreIter { - return StoreIter::new(& mut self. f, & mut self.indexer); + pub fn iter<'a>(&'a mut self) -> impl Iterator + 'a { + StoreIter::new(Holder::Ref(&mut self.f), self.indexer.iter()) + } + + /** Iterates over the stored values. + + Returns the latest stored value for every id. The ids are guaranteed to be increasing. + */ + pub fn into_iter<'a>(self) -> impl Iterator + 'a where Self: 'a{ + StoreIter::new(Holder::Own(self.f), self.indexer.into_iter()) } /** Iterates over all stored values. Iterates over *all* stored values, returning them in the order they were added to the store. Multiple values may be returned for single id, the last value returned is the valid one. */ - pub fn iter_all(& mut self) -> StoreIterAll { + pub fn iter_all<'a>(&'a mut self) -> impl Iterator + 'a { self.f.seek(SeekFrom::Start(0)).unwrap(); - return StoreIterAll{ store : self, max_offset : u64::MAX }; + return StoreIterAll{ store: Holder::Ref(self), max_offset : u64::MAX }; } - pub fn savepoint_iter_all(& mut self, sp : & Savepoint) -> StoreIterAll { + /** Iterates over all stored values. + + Iterates over *all* stored values, returning them in the order they were added to the store. Multiple values may be returned for single id, the last value returned is the valid one. + */ + pub fn into_iter_all<'a>(mut self) -> impl Iterator + 'a where Self: 'a{ + self.f.seek(SeekFrom::Start(0)).unwrap(); + return StoreIterAll{ store: Holder::Own(self), max_offset : u64::MAX }; + } + + pub fn savepoint_iter_all<'a>(&'a mut self, sp : & Savepoint) -> impl Iterator + 'a { + let max_offset = sp.limit_for(& format!("{}.store", self.name())); + self.f.seek(SeekFrom::Start(0)).unwrap(); + return StoreIterAll{store: Holder::Ref(self), max_offset }; + } + + pub fn into_savepoint_iter_all<'a>(mut self, sp: &Savepoint) -> impl Iterator + 'a where Self: 'a{ let max_offset = sp.limit_for(& format!("{}.store", self.name())); self.f.seek(SeekFrom::Start(0)).unwrap(); - return StoreIterAll{ store : self, max_offset }; + return StoreIterAll{ store: Holder::Own(self), max_offset }; } /** Reads the record from a file. @@ -471,31 +520,47 @@ impl, ID : Id> Store { } } + /** Latest store iterator does not support savepoints since the indices can be udpated. */ -pub struct StoreIter<'a, T: Serializable, ID : Id> { - f : &'a mut File, - iiter : IndexerIterator<'a, u64,ID>, - why_oh_why : std::marker::PhantomData, + pub struct StoreIter<'a, I, T, ID> + where + I: Iterator, + T: Serializable, + ID: Id, +{ + file: Holder<'a, File>, + iiter:I, + _t: PhantomData, } -impl<'a, T : Serializable, ID : Id> StoreIter<'a, T, ID> { - fn new(f : &'a mut File, indexer : &'a mut Indexer) -> StoreIter<'a, T, ID> { - return StoreIter{ - f : f, - iiter : indexer.iter(), - why_oh_why : std::marker::PhantomData{} - }; +impl<'a, I, T, ID> StoreIter<'a, I, T, ID> +where + I: Iterator, + T: Serializable, + ID: Id + { + fn new(file: Holder<'a, File>, iiter: I) -> StoreIter<'a, I, T, ID>{ + StoreIter{ + file, + iiter, + _t: PhantomData + } } } -impl<'a, T : Serializable, ID : Id> Iterator for StoreIter<'a, T, ID> { +impl<'a, I, T, ID> Iterator for StoreIter<'a, I, T, ID> +where + I: Iterator, + T: Serializable, + ID: Id + { type Item = (ID, T); fn next(& mut self) -> Option<(ID, T)> { if let Some((id, offset)) = self.iiter.next() { - self.f.seek(SeekFrom::Start(offset)).unwrap(); - let (store_id, value) = Store::::read_record(self.f).unwrap(); + self.file.seek(SeekFrom::Start(offset)).unwrap(); + let (store_id, value) = Store::::read_record(&mut self.file).unwrap(); assert_eq!(id, store_id, "Corrupted store or its indexing"); return Some((id, value)); } else { @@ -504,23 +569,34 @@ impl<'a, T : Serializable, ID : Id> Iterator for StoreIter<'a, T, ID> } } -pub struct StoreIterAll<'a, T : Serializable, ID : Id> { - store : &'a mut Store, + + +pub struct StoreIterAll<'a, T, ID> +where + T: Serializable, + ID: Id +{ + store: Holder<'a, Store>, max_offset : u64, } -impl<'a, T : Serializable, ID : Id> Iterator for StoreIterAll<'a, T, ID> { +impl<'a, T, ID> Iterator for StoreIterAll<'a, T, ID> +where + T: Serializable, + ID: Id +{ type Item = (ID, T); fn next(& mut self) -> Option<(ID, T)> { if self.store.f.seek(SeekFrom::Current(0)).unwrap() >= self.max_offset { return None; } else { - return Store::::read_record(& mut self.store.f); + return Store::::read_record(&mut self.store.f); } } } + /** Linked store implementation. Store is an indexed updatable container that keeps history of updates. @@ -530,7 +606,7 @@ impl<'a, T : Serializable, ID : Id> Iterator for StoreIterAll<'a, T, I pub struct LinkedStore, ID : Id = u64> { pub (crate) indexer : Indexer, pub (crate) f : File, - why_oh_why : std::marker::PhantomData, + _t : std::marker::PhantomData, } impl, ID : Id> LinkedStore { @@ -545,7 +621,7 @@ impl, ID : Id> LinkedStore { let mut result = LinkedStore{ indexer : Indexer::new(root, name, readonly), f, - why_oh_why : std::marker::PhantomData{} + _t : std::marker::PhantomData{} }; LOG!(" {}: indices {}, size {}", name, result.indexer.len(), result.f.seek(SeekFrom::End(0)).unwrap()); return result; @@ -672,32 +748,64 @@ impl, ID : Id> LinkedStore { Returns the latest stored value for every id. The ids are guaranteed to be increasing. */ - pub fn iter(& mut self) -> LinkedStoreIter { - return LinkedStoreIter::new(& mut self. f, & mut self.indexer); + pub fn iter<'a>(&'a mut self) -> impl Iterator + 'a { + LinkedStoreIter::new(Holder::Ref(&mut self.f), self.indexer.iter()) + } + + /** Iterates over the stored values. + + Returns the latest stored value for every id. The ids are guaranteed to be increasing. + */ + pub fn into_iter<'a>(self) -> impl Iterator + 'a where Self: 'a{ + LinkedStoreIter::new(Holder::Own(self.f), self.indexer.into_iter()) + } + + /** Iterates over all stored values. + + Iterates over *all* stored values, returning them in the order they were added to the store. Multiple values may be returned for single id, the last value returned is the valid one. + */ + pub fn iter_all<'a>(&'a mut self) -> impl Iterator + 'a { + self.f.seek(SeekFrom::Start(0)).unwrap(); + LinkedStoreIterAll{ store: Holder::Ref(self), max_offset: u64::MAX } } /** Iterates over all stored values. Iterates over *all* stored values, returning them in the order they were added to the store. Multiple values may be returned for single id, the last value returned is the valid one. */ - pub fn iter_all(& mut self) -> LinkedStoreIterAll { + pub fn into_iter_all<'a>(mut self) -> impl Iterator + 'a where Self: 'a{ + self.f.seek(SeekFrom::Start(0)).unwrap(); + LinkedStoreIterAll{ store: Holder::Own(self), max_offset: u64::MAX } + } + + pub fn savepoint_iter_all<'a>(&'a mut self, sp: &Savepoint) -> impl Iterator + 'a { + let max_offset = sp.limit_for(&format!("{}.store",self.name())); self.f.seek(SeekFrom::Start(0)).unwrap(); - return LinkedStoreIterAll{ store : self, max_offset : u64::MAX }; + LinkedStoreIterAll{ store : Holder::Ref(self), max_offset } } - pub fn savepoint_iter_all(& mut self, sp : & Savepoint) -> LinkedStoreIterAll { - let max_offset = sp.limit_for(& format!("{}.store",self.name())); + pub fn into_savepoint_iter_all<'a>(mut self, sp: &Savepoint) -> impl Iterator + 'a where Self: 'a{ + let max_offset = sp.limit_for(&format!("{}.store",self.name())); self.f.seek(SeekFrom::Start(0)).unwrap(); - return LinkedStoreIterAll{ store : self, max_offset }; + LinkedStoreIterAll{ store: Holder::Own(self), max_offset } } /** Given an id, returns an iterator over all values ever stored for it. The values are returned in the reverse order they were added, i.e. latest value first. */ - pub fn iter_id(& mut self, id : ID) -> LinkedStoreIterId { + pub fn iter_id<'a>(&'a mut self, id : ID) -> impl Iterator + 'a { let offset = self.indexer.get(id); - return LinkedStoreIterId{ store : self, offset }; + LinkedStoreIterId{ store: Holder::Ref(self), offset } + } + + /** Given an id, returns an iterator over all values ever stored for it. + + The values are returned in the reverse order they were added, i.e. latest value first. + */ + pub fn into_iter_id<'a>(mut self, id : ID) -> impl Iterator + 'a where Self: 'a { + let offset = self.indexer.get(id); + return LinkedStoreIterId{ store: Holder::Own(self), offset }; } /** Reads the record from a file. @@ -725,29 +833,44 @@ impl, ID : Id> LinkedStore { } } -pub struct LinkedStoreIter<'a, T: Serializable, ID : Id> { - f : &'a mut File, - iiter : IndexerIterator<'a, u64, ID>, - why_oh_why : std::marker::PhantomData, +pub struct LinkedStoreIter<'a, I, T, ID> +where + I: Iterator, + T: Serializable, + ID: Id, +{ + iiter: I, + file: Holder<'a, File>, + _t: std::marker::PhantomData, } -impl<'a, T : Serializable, ID : Id> LinkedStoreIter<'a, T, ID> { - fn new(f : &'a mut File, indexer : &'a mut Indexer) -> LinkedStoreIter<'a, T, ID> { +impl<'a, I, T, ID> LinkedStoreIter<'a, I, T, ID> +where + I: Iterator, + T: Serializable, + ID: Id, +{ + fn new(file: Holder<'a, File>, iiter: I) -> LinkedStoreIter<'a, I, T, ID> { return LinkedStoreIter{ - f : f, - iiter : indexer.iter(), - why_oh_why : std::marker::PhantomData{} + iiter, + file, + _t: std::marker::PhantomData{} }; } } -impl<'a, T : Serializable, ID : Id> Iterator for LinkedStoreIter<'a, T, ID> { +impl<'a, I, T, ID> Iterator for LinkedStoreIter<'a, I, T, ID> +where + I: Iterator, + T: Serializable, + ID: Id, +{ type Item = (ID, T); fn next(& mut self) -> Option<(ID, T)> { if let Some((id, offset)) = self.iiter.next() { - self.f.seek(SeekFrom::Start(offset)).unwrap(); - let (store_id, _, value) = LinkedStore::::read_record(self.f).unwrap(); + self.file.seek(SeekFrom::Start(offset)).unwrap(); + let (store_id, _, value) = LinkedStore::::read_record(&mut self.file).unwrap(); assert_eq!(id, store_id, "Corrupted store or its indexing"); return Some((id, value)); } else { @@ -756,40 +879,56 @@ impl<'a, T : Serializable, ID : Id> Iterator for LinkedStoreIter<'a, T } } -pub struct LinkedStoreIterAll<'a, T : Serializable, ID : Id> { - store : &'a mut LinkedStore, - max_offset : u64, + + +pub struct LinkedStoreIterAll<'a, T, ID> +where + T: Serializable, + ID: Id +{ + store: Holder<'a, LinkedStore>, + max_offset: u64, } -impl<'a, T : Serializable, ID : Id> Iterator for LinkedStoreIterAll<'a, T, ID> { +impl<'a, T, ID> Iterator for LinkedStoreIterAll<'a, T, ID> +where + T: Serializable, + ID: Id +{ type Item = (ID, T); fn next(& mut self) -> Option<(ID, T)> { if self.store.f.seek(SeekFrom::Current(0)).unwrap() >= self.max_offset { return None; } else { - match LinkedStore::::read_record(& mut self.store.f) { + match LinkedStore::::read_record(&mut self.store.f) { Some((id, _, value)) => Some((id, value)), None => None } } } - } - -pub struct LinkedStoreIterId<'a, T : Serializable, ID : Id> { - store : &'a mut LinkedStore, - offset : Option, +pub struct LinkedStoreIterId<'a, T, ID> +where + T: Serializable, + ID: Id, +{ + store: Holder<'a, LinkedStore>, + offset: Option, } -impl<'a, T : Serializable, ID : Id> Iterator for LinkedStoreIterId<'a, T, ID> { +impl<'a, T, ID> Iterator for LinkedStoreIterId<'a, T, ID> +where + T: Serializable, + ID: Id, +{ type Item = T; - fn next(& mut self) -> Option { + fn next(&mut self) -> Option { match self.offset { Some(offset) => { self.store.f.seek(SeekFrom::Start(offset)).unwrap(); - let (_, previous_offset, value) = LinkedStore::::read_record(& mut self.store.f).unwrap(); + let (_, previous_offset, value) = LinkedStore::::read_record(&mut self.store.f).unwrap(); self.offset = previous_offset; return Some(value); }, @@ -798,6 +937,7 @@ impl<'a, T : Serializable, ID : Id> Iterator for LinkedStoreIterId<'a, } } + /** Mapping from values to ids. Unlike store, mapping does not allow updates to added values. @@ -867,11 +1007,11 @@ impl + Eq + Hash + Clone, ID : Id> Mapping + Eq + Hash + Clone, ID : Id> Mapping MappingIter { + pub fn iter<'a>(&'a mut self) -> impl Iterator + 'a { self.f.seek(SeekFrom::Start(0)).unwrap(); - return MappingIter{f : & mut self.f, index : 0, size : self.size, why_oh_why : std::marker::PhantomData{} }; + let size = self.size; + MappingIter{file: Holder::Ref(&mut self.f), index: 0, size, _t: PhantomData } } - pub fn savepoint_iter(& mut self, sp : & Savepoint) -> MappingIter { - let max_offset = sp.limit_for(& format!("{}.mapping", self.name())); + pub fn savepoint_iter<'a>(&'a mut self, sp : &Savepoint) -> impl Iterator + 'a { + let max_offset = + sp.limit_for(& format!("{}.mapping", self.name())) / (std::mem::size_of::() as u64); self.f.seek(SeekFrom::Start(0)).unwrap(); - return MappingIter{f : & mut self.f, index : 0, size : max_offset / (std::mem::size_of::() as u64), why_oh_why : std::marker::PhantomData{} }; + MappingIter{file: Holder::Ref(&mut self.f), index : 0, size: max_offset, _t: PhantomData } + } + + pub fn into_iter<'a>(mut self) -> impl Iterator + 'a where Self: 'a{ + self.f.seek(SeekFrom::Start(0)).unwrap(); + let size = self.size; + MappingIter{file: Holder::Own(self.f), index: 0, size, _t: PhantomData } + } + + pub fn into_savepoint_iter<'a>(mut self, sp : &Savepoint) -> impl Iterator + 'a where Self: 'a{ + let max_offset = + sp.limit_for(& format!("{}.mapping", self.name())) / (std::mem::size_of::() as u64); + self.f.seek(SeekFrom::Start(0)).unwrap(); + MappingIter{file: Holder::Own(self.f), index : 0, size: max_offset, _t: PhantomData } } } -pub struct MappingIter<'a, T : FixedSizeSerializable + Eq + Hash + Clone, ID : Id = u64> { - f : &'a mut File, - index : u64, - size : u64, - why_oh_why : std::marker::PhantomData<(T, ID)> +pub struct MappingIter<'a, T, ID> +where + T: FixedSizeSerializable + Eq + Hash + Clone, + ID: Id +{ + file: Holder<'a, File>, + index: u64, + size: u64, + _t: std::marker::PhantomData<(T, ID)>, } -impl<'a, T : FixedSizeSerializable + Eq + Hash + Clone, ID : Id> Iterator for MappingIter<'a, T, ID> { +impl Iterator for MappingIter<'_, T, ID> +where + T: FixedSizeSerializable + Eq + Hash + Clone, + ID: Id +{ type Item = (ID, T); - fn next(& mut self) -> Option<(ID, T)> { + fn next(&mut self) -> Option<(ID, T)> { if self.index == self.size { return None; } else { - let value = T::deserialize(self.f); + let value = T::deserialize(&mut self.file); let id = ID::from(self.index); self.index += 1; return Some((id, value)); @@ -971,14 +1134,24 @@ impl<'a, T : FixedSizeSerializable + Eq + Hash + Clone, ID : Id> Itera } } + + /** Mapping from values to ids where the values require indexing. */ -pub struct IndirectMapping + Eq + Hash + Clone, ID : Id = u64> { +pub struct IndirectMapping +where + T : Serializable + Eq + Hash + Clone, + ID : Id, +{ pub (crate) store : Store, mapping : HashMap } -impl + Eq + Hash + Clone, ID : Id> IndirectMapping { +impl IndirectMapping +where + T : Serializable + Eq + Hash + Clone, + ID : Id, +{ /** Creates new mapping. */ @@ -1054,12 +1227,20 @@ impl + Eq + Hash + Clone, ID : Id> IndirectMapping StoreIterAll { - return self.store.iter_all(); + pub fn iter<'a>(&'a mut self) -> impl Iterator + 'a { + self.store.iter_all() + } + + pub fn into_iter<'a>(self) -> impl Iterator + 'a where Self: 'a{ + self.store.into_iter_all() } - pub fn savepoint_iter(& mut self, sp : & Savepoint) -> StoreIterAll { - return self.store.savepoint_iter_all(sp); + pub fn savepoint_iter<'a> (&'a mut self, sp: &Savepoint) -> impl Iterator + 'a { + self.store.savepoint_iter_all(sp) + } + + pub fn into_savepoint_iter<'a>(self, sp: &Savepoint) -> impl Iterator + 'a where Self: 'a { + self.store.into_savepoint_iter_all(sp) } } @@ -1086,12 +1267,12 @@ pub trait SplitKind : FixedSizeSerializable + Eq + Debug { */ pub struct SplitKindIter { i : u64, - why_oh_why : std::marker::PhantomData, + _t : std::marker::PhantomData, } impl SplitKindIter { pub fn new() -> SplitKindIter { - return SplitKindIter{i : 0, why_oh_why : std::marker::PhantomData{} }; + return SplitKindIter{i : 0, _t : std::marker::PhantomData{} }; } } @@ -1152,11 +1333,16 @@ impl> Indexable for SplitOffset { /** Split store contains single index, but multiple files that store the data based on its kind. */ -pub struct SplitStore, KIND : SplitKind, ID : Id = u64> { +pub struct SplitStore +where + T: Serializable, + KIND : SplitKind, + ID: Id, +{ name : String, pub (crate) indexer : Indexer, ID>, pub (crate) files : Vec, - why_oh_why : std::marker::PhantomData + _t : std::marker::PhantomData } impl, KIND: SplitKind, ID : Id> SplitStore { @@ -1176,7 +1362,7 @@ impl, KIND: SplitKind, ID : Id> SplitSto name : name.to_owned(), indexer : Indexer::new(root, name, readonly), files, - why_oh_why : std::marker::PhantomData{} + _t : std::marker::PhantomData{} }; LOG!(" {}: indices {}, splits {}", name, result.indexer.len(), result.files.len()); return result; @@ -1306,31 +1492,47 @@ impl, KIND: SplitKind, ID : Id> SplitSto return self.indexer.len(); } - pub fn savepoint_iter(& mut self, sp : & Savepoint) -> SplitStoreIterAll { + pub fn savepoint_iter<'a>(&'a mut self, sp: &Savepoint) -> impl Iterator + 'a { let mut max_offsets = Vec::new(); - let mut i = 0; - for _f in self.files.iter_mut() { - max_offsets.push(sp.limit_for(& format!("{}-{}.store", self.name, i))); - i += 1; + for i in 0..self.files.len() { + max_offsets.push(sp.limit_for(&format!("{}-{}.store", self.name, i))); } self.files[0].seek(SeekFrom::Start(0)).unwrap(); - return SplitStoreIterAll{ store : self, max_offsets, split : 0 } + return SplitStoreIterAll{ store: Holder::Ref(self), max_offsets, split: 0 }; } - // TODO add iterators - + pub fn into_savepoint_iter<'a>(mut self, sp: &Savepoint) -> impl Iterator + 'a where Self: 'a{ + let mut max_offsets = Vec::new(); + for i in 0..self.files.len() { + max_offsets.push(sp.limit_for(&format!("{}-{}.store", self.name, i))); + } + self.files[0].seek(SeekFrom::Start(0)).unwrap(); + + SplitStoreIterAll{ store: Holder::Own(self), max_offsets, split: 0 } + } } -pub struct SplitStoreIterAll<'a, T : Serializable, KIND: SplitKind, ID : Id> { - store: &'a mut SplitStore, + +pub struct SplitStoreIterAll<'a, T, KIND, ID> +where + T: Serializable, + KIND: SplitKind, + ID: Id, +{ + store: Holder<'a, SplitStore>, max_offsets : Vec, split : usize, } -impl<'a, T : Serializable, KIND: SplitKind, ID : Id> Iterator for SplitStoreIterAll<'a, T, KIND, ID> { +impl<'a, T, KIND, ID> Iterator for SplitStoreIterAll<'a, T, KIND, ID> +where + T: Serializable, + KIND: SplitKind, + ID: Id, +{ type Item = (ID, KIND, T); - fn next(& mut self) -> Option<(ID, KIND, T)> { + fn next(&mut self) -> Option<(ID, KIND, T)> { loop { if self.store.files[self.split].seek(SeekFrom::Current(0)).unwrap() >= self.max_offsets[self.split] { self.split += 1; @@ -1347,6 +1549,7 @@ impl<'a, T : Serializable, KIND: SplitKind, ID : Id> Iter } } + /** Savepoint for the entire datastore. */ diff --git a/src/helpers.rs b/src/helpers.rs index 91937c4..d089d05 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,6 +1,33 @@ use std::time::{SystemTime, UNIX_EPOCH, Duration}; use std::str; +use std::ops::{Deref, DerefMut}; + +/// Used in lieu of &mut T +pub enum Holder<'a, T>{ + Ref(&'a mut T), + Own(T), +} + +impl<'a, T> Deref for Holder<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + match self { + Holder::Ref(r) => r, + Holder::Own(t) => t, + } + } +} + +impl<'a, T> DerefMut for Holder<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + Holder::Ref(r) => r, + Holder::Own(t) => t, + } + } +} pub fn pct(value : usize, max : usize) -> String { if max == 0 { diff --git a/src/lib.rs b/src/lib.rs index e1a2fa1..5dfc60d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ extern crate lazy_static; mod helpers; #[allow(dead_code)] -mod db; +pub mod db; #[allow(dead_code)] mod records; #[allow(dead_code)] @@ -507,8 +507,8 @@ pub struct StoreView<'a, T : db::Serializable, ID : db::Id = u64> { } impl<'a, T : db::Serializable, ID : db::Id > StoreView<'a, T, ID> { - pub fn iter(& mut self, sp : & Savepoint) -> db::StoreIterAll { - return self.guard.savepoint_iter_all(sp); + pub fn iter<'b>(&'b mut self, sp : & Savepoint) -> impl Iterator + 'b { + self.guard.savepoint_iter_all(sp) } } @@ -527,8 +527,8 @@ pub struct LinkedStoreView<'a, T : db::Serializable, ID : db::Id> { } impl<'a, T : db::Serializable, ID : db::Id > LinkedStoreView<'a, T, ID> { - pub fn iter(& mut self, sp : & Savepoint) -> db::LinkedStoreIterAll { - return self.guard.savepoint_iter_all(sp); + pub fn iter<'b>(&'b mut self, sp : & Savepoint) -> impl Iterator + 'b { + self.guard.savepoint_iter_all(sp) } } @@ -547,7 +547,7 @@ pub struct MappingView<'a, T : db::FixedSizeSerializable + Eq + Hash + } impl<'a, T : db::FixedSizeSerializable + Eq + Hash + Clone, ID : db::Id> MappingView<'a, T, ID> { - pub fn iter(& mut self, sp : & Savepoint) -> db::MappingIter { + pub fn iter<'b>(&'b mut self, sp : & Savepoint) -> impl Iterator + 'b { return self.guard.savepoint_iter(sp); } @@ -566,8 +566,8 @@ pub struct IndirectMappingView<'a, T : db::Serializable + Eq + Hash + } impl<'a, T : db::Serializable + Eq + Hash + Clone, ID : db::Id> IndirectMappingView<'a, T, ID> { - pub fn iter(& mut self, sp : & Savepoint) -> db::StoreIterAll { - return self.guard.savepoint_iter(sp); + pub fn iter<'b>(&'b mut self, sp : & Savepoint) -> impl Iterator + 'b { + self.guard.savepoint_iter(sp) } pub fn get(& mut self, id : ID) -> Option { @@ -588,8 +588,8 @@ pub struct SplitStoreView<'a, T : db::Serializable, KIND : db::SplitKi impl<'a, T : db::Serializable, KIND : db::SplitKind, ID : db::Id> SplitStoreView<'a, T, KIND, ID> { - pub fn iter(& mut self, sp : & Savepoint) -> db::SplitStoreIterAll { - return self.guard.savepoint_iter(sp); + pub fn iter<'b>(&'b mut self, sp : & Savepoint) -> impl Iterator + 'b { + self.guard.savepoint_iter(sp) } } @@ -606,8 +606,8 @@ pub struct SavepointsView<'a> { } impl<'a> SavepointsView<'a> { - pub fn iter(& mut self) -> db::LinkedStoreIterAll { - return self.guard.iter_all(); + pub fn iter<'b>(&'b mut self) -> impl Iterator + 'b { + self.guard.iter_all() } }