pub struct Persy { /* private fields */ }
Expand description
Main structure to operate persy storage files
Implementations§
source§impl Persy
impl Persy
sourcepub fn create<P: AsRef<Path>>(path: P) -> Result<(), PE<CreateError>>
pub fn create<P: AsRef<Path>>(path: P) -> Result<(), PE<CreateError>>
Create a new database file.
Errors
Fails if the file already exists.
Example
use std::path::Path;
use persy::{Persy, Config};
let path = Path::new("target/created.db");
Persy::create(path)?;
let persy = Persy::open(path, Config::new())?;
Examples found in repository?
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
pub fn open_or_create_with<P, F>(path: P, config: Config, prepare: F) -> Result<Persy, PE<OpenError>>
where
P: AsRef<Path>,
F: FnOnce(&Persy) -> Result<(), Box<dyn std::error::Error>> + 'static,
{
let path = path.as_ref();
let persy;
if !path.exists() {
Persy::create(path).map_err(|e| PE::PE(OpenError::from(e.error())))?;
persy = Persy::open(path, config)?;
prepare(&persy).map_err(|e| OpenError::InitError(format!("{}", e)))?;
} else {
persy = Persy::open(path, config)?;
}
Ok(persy)
}
sourcepub fn create_from_file(file: File) -> Result<(), PE<CreateError>>
pub fn create_from_file(file: File) -> Result<(), PE<CreateError>>
sourcepub fn open<P: AsRef<Path>>(
path: P,
config: Config
) -> Result<Persy, PE<OpenError>>
pub fn open<P: AsRef<Path>>(
path: P,
config: Config
) -> Result<Persy, PE<OpenError>>
Open a database file.
The file should have been created with Persy::create
Errors
Fails if the file does not exist.
Examples found in repository?
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
pub fn open_or_create_with<P, F>(path: P, config: Config, prepare: F) -> Result<Persy, PE<OpenError>>
where
P: AsRef<Path>,
F: FnOnce(&Persy) -> Result<(), Box<dyn std::error::Error>> + 'static,
{
let path = path.as_ref();
let persy;
if !path.exists() {
Persy::create(path).map_err(|e| PE::PE(OpenError::from(e.error())))?;
persy = Persy::open(path, config)?;
prepare(&persy).map_err(|e| OpenError::InitError(format!("{}", e)))?;
} else {
persy = Persy::open(path, config)?;
}
Ok(persy)
}
sourcepub fn open_with_recover<P: AsRef<Path>, C>(
path: P,
config: Config,
recover: C
) -> Result<Persy, PE<OpenError>>where
C: Fn(&TransactionId) -> bool,
pub fn open_with_recover<P: AsRef<Path>, C>(
path: P,
config: Config,
recover: C
) -> Result<Persy, PE<OpenError>>where
C: Fn(&TransactionId) -> bool,
Open a database file from a path with a recover function.
The file should have been created with Persy::create
Errors
Fails if the file does not exist.
sourcepub fn recover<P: AsRef<Path>>(
path: P,
config: Config
) -> Result<Recover, PE<OpenError>>
pub fn recover<P: AsRef<Path>>(
path: P,
config: Config
) -> Result<Recover, PE<OpenError>>
Open a database file from a path and return a recover structure that allow to select the transactions to commit and recover them.
The file should have been created with Persy::create
Errors
Fails if the file does not exist.
sourcepub fn open_from_file(path: File, config: Config) -> Result<Persy, PE<OpenError>>
pub fn open_from_file(path: File, config: Config) -> Result<Persy, PE<OpenError>>
Open a database file from a direct file handle.
The file should have been created with Persy::create
Errors
Fails if the file does not exist.
sourcepub fn open_from_file_with_recover<C>(
file: File,
config: Config,
recover: C
) -> Result<Persy, PE<OpenError>>where
C: Fn(&TransactionId) -> bool,
pub fn open_from_file_with_recover<C>(
file: File,
config: Config,
recover: C
) -> Result<Persy, PE<OpenError>>where
C: Fn(&TransactionId) -> bool,
Open a database file, from a direct file handle and a transaction recover function.
The file should have been created with Persy::create
Errors
Fails if the file does not exist.
sourcepub fn open_or_create_with<P, F>(
path: P,
config: Config,
prepare: F
) -> Result<Persy, PE<OpenError>>where
P: AsRef<Path>,
F: FnOnce(&Persy) -> Result<(), Box<dyn Error>> + 'static,
pub fn open_or_create_with<P, F>(
path: P,
config: Config,
prepare: F
) -> Result<Persy, PE<OpenError>>where
P: AsRef<Path>,
F: FnOnce(&Persy) -> Result<(), Box<dyn Error>> + 'static,
Open an existing database or create it if it does not exist yet,
calling the prepare
function just after the creation.
Example
use std::path::Path;
use persy::{Persy, Config, PersyId, ValueMode};
let path = Path::new("target/open_or_create.db");
let config = Config::new();
let persy = Persy::open_or_create_with(path, config, |persy| {
// this closure is only called on database creation
let mut tx = persy.begin()?;
tx.create_segment("data")?;
tx.create_index::<u64, PersyId>("index", ValueMode::Replace)?;
let prepared = tx.prepare()?;
prepared.commit()?;
println!("Segment and Index successfully created");
Ok(())
})?;
sourcepub fn begin(&self) -> Result<Transaction, PE<BeginTransactionError>>
pub fn begin(&self) -> Result<Transaction, PE<BeginTransactionError>>
sourcepub fn begin_with(
&self,
config: TransactionConfig
) -> Result<Transaction, PE<BeginTransactionError>>
pub fn begin_with(
&self,
config: TransactionConfig
) -> Result<Transaction, PE<BeginTransactionError>>
Begin a new transaction specifying parameters for the transaction.
The transaction isolation level is ‘read_committed’.
for commit call prepare
and commit
Example
let tx_id = vec![2;2];
let mut tx = persy.begin_with(TransactionConfig::new().set_transaction_id(tx_id))?;
// ...
tx.prepare()?.commit()?;
sourcepub fn exists_segment(&self, segment: &str) -> Result<bool, PE<GenericError>>
pub fn exists_segment(&self, segment: &str) -> Result<bool, PE<GenericError>>
Check if a segment already exist in the storage
Example
let mut tx = persy.begin()?;
tx.create_segment("my_new_segment")?;
let prepared = tx.prepare()?;
prepared.commit()?;
assert!(persy.exists_segment("my_new_segment")?);
sourcepub fn solve_segment_id(
&self,
segment: impl ToSegmentId
) -> Result<SegmentId, PE<SegmentError>>
pub fn solve_segment_id(
&self,
segment: impl ToSegmentId
) -> Result<SegmentId, PE<SegmentError>>
Resolves the segment to a SegmentId
Example
let mut tx = persy.begin()?;
tx.create_segment("my_new_segment")?;
let prepared = tx.prepare()?;
prepared.commit()?;
let segment_id = persy.solve_segment_id("my_new_segment")?;
Examples found in repository?
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
pub fn read(&self, segment: impl ToSegmentId, id: &PersyId) -> Result<Option<Vec<u8>>, PE<ReadError>> {
let segment_id = self
.solve_segment_id(segment)
.map_err(|PE::PE(e)| PE::PE(ReadError::from(e)))?;
Ok(self.persy_impl.read(segment_id, &id.0)?)
}
/// Scan a segment for persistent records
///
/// # Example
///
/// ```rust
/// # use persy::{Persy,Config};
/// # use persy::{OpenOptions};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let persy = OpenOptions::new().memory()?;
/// let mut tx = persy.begin()?;
/// # tx.create_segment("seg")?;
/// let data = vec![1;20];
/// let id = tx.insert("seg", &data)?;
/// let prepared = tx.prepare()?;
/// prepared.commit()?;
/// let mut count = 0;
/// for (id,content) in persy.scan("seg")? {
/// println!("record size:{}",content.len());
/// count+=1;
/// }
/// assert_eq!(count,1);
/// # Ok(())
/// # }
/// ```
pub fn scan(&self, segment: impl ToSegmentId) -> Result<SegmentIter, PE<SegmentError>> {
let segment_id = self.solve_segment_id(segment)?;
Ok(SegmentIter::new(
self.persy_impl.scan(segment_id)?,
self.persy_impl.clone(),
))
}
sourcepub fn solve_index_id(
&self,
index: impl ToIndexId
) -> Result<IndexId, PE<IndexError>>
pub fn solve_index_id(
&self,
index: impl ToIndexId
) -> Result<IndexId, PE<IndexError>>
Resolves the index to a IndexId, this has no public use as today, may be used in future.
Example
let mut tx = persy.begin()?;
tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
let prepared = tx.prepare()?;
prepared.commit()?;
let index_id = persy.solve_index_id("my_new_index")?;
Examples found in repository?
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
pub fn get<K, V>(&self, index_name: &str, k: &K) -> Result<ValueIter<V>, PE<IndexOpsError>>
where
K: IndexType,
V: IndexType,
{
let index_id = self
.solve_index_id(index_name)
.map_err(|e| PE::PE(IndexOpsError::from(e.error())))?;
Ok(ValueIter::from(
self.persy_impl
.get::<K::Wrapper, V::Wrapper>(index_id, &k.clone().wrap())?,
))
}
/// Get one value or none from a key.
///
/// # Example
///
/// ```rust
/// # use persy::{ValueMode, OpenOptions};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let persy = OpenOptions::new().memory()?;
/// # let mut tx = persy.begin()?;
/// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
/// # tx.put::<u8,u8>("my_new_index",10,10)?;
/// # let prepared = tx.prepare()?;
/// # prepared.commit()?;
/// if let Some(value) = persy.one::<u8,u8>("my_new_index",&10)? {
/// //...
/// }
/// # Ok(())
/// # }
/// ```
pub fn one<K, V>(&self, index_name: &str, k: &K) -> Result<Option<V>, PE<IndexOpsError>>
where
K: IndexType,
V: IndexType,
{
Ok(self.get(index_name, k)?.next())
}
/// Browse a range of keys and values from and index.
///
/// # Example
///
/// ```rust
/// # use persy::{OpenOptions,ValueMode, IndexIter};
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let persy = OpenOptions::new().memory()?;
/// # let mut tx = persy.begin()?;
/// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
/// # tx.put::<u8,u8>("my_new_index",10,10)?;
/// # let prepared = tx.prepare()?;
/// # prepared.commit()?;
/// let iter:IndexIter<u8,u8> = persy.range("my_new_index",10..12)?;
/// for (k,values) in iter {
/// for value in values {
/// //...
/// }
/// }
/// # Ok(())
/// # }
/// ```
pub fn range<K, V, R>(&self, index_name: &str, range: R) -> Result<IndexIter<K, V>, PE<IndexOpsError>>
where
K: IndexType,
V: IndexType,
R: RangeBounds<K>,
{
let index_id = self
.solve_index_id(index_name)
.map_err(|e| PE::PE(IndexOpsError::from(e.error())))?;
let rr = PersyImpl::map_index_range_bounds(range);
let (_, raw) = self.persy_impl.range(index_id, rr)?;
Ok(IndexIter::new(raw, self.persy_impl.clone()))
}
sourcepub fn read(
&self,
segment: impl ToSegmentId,
id: &PersyId
) -> Result<Option<Vec<u8>>, PE<ReadError>>
pub fn read(
&self,
segment: impl ToSegmentId,
id: &PersyId
) -> Result<Option<Vec<u8>>, PE<ReadError>>
Read the record content from persistent data.
Example
let mut tx = persy.begin()?;
let data = vec![1;20];
let id = tx.insert("seg", &data)?;
let prepared = tx.prepare()?;
prepared.commit()?;
let read = persy.read("seg", &id)?.expect("record exits");
assert_eq!(data,read);
sourcepub fn scan(
&self,
segment: impl ToSegmentId
) -> Result<SegmentIter, PE<SegmentError>>
pub fn scan(
&self,
segment: impl ToSegmentId
) -> Result<SegmentIter, PE<SegmentError>>
Scan a segment for persistent records
Example
let mut tx = persy.begin()?;
let data = vec![1;20];
let id = tx.insert("seg", &data)?;
let prepared = tx.prepare()?;
prepared.commit()?;
let mut count = 0;
for (id,content) in persy.scan("seg")? {
println!("record size:{}",content.len());
count+=1;
}
assert_eq!(count,1);
sourcepub fn exists_index(&self, index_name: &str) -> Result<bool, PE<GenericError>>
pub fn exists_index(&self, index_name: &str) -> Result<bool, PE<GenericError>>
Check if a segment already exist in the storage
Example
let mut tx = persy.begin()?;
tx.create_index::<u8,u8>("my_new_index", ValueMode::Replace)?;
let prepared = tx.prepare()?;
prepared.commit()?;
assert!(persy.exists_index("my_new_index")?);
sourcepub fn get<K, V>(
&self,
index_name: &str,
k: &K
) -> Result<ValueIter<V>, PE<IndexOpsError>>where
K: IndexType,
V: IndexType,
pub fn get<K, V>(
&self,
index_name: &str,
k: &K
) -> Result<ValueIter<V>, PE<IndexOpsError>>where
K: IndexType,
V: IndexType,
Get a value or a group of values from a key.
Example
let values = persy.get::<u8,u8>("my_new_index",&10)?;
for value in values {
//...
}
sourcepub fn one<K, V>(
&self,
index_name: &str,
k: &K
) -> Result<Option<V>, PE<IndexOpsError>>where
K: IndexType,
V: IndexType,
pub fn one<K, V>(
&self,
index_name: &str,
k: &K
) -> Result<Option<V>, PE<IndexOpsError>>where
K: IndexType,
V: IndexType,
Get one value or none from a key.
Example
if let Some(value) = persy.one::<u8,u8>("my_new_index",&10)? {
//...
}
sourcepub fn range<K, V, R>(
&self,
index_name: &str,
range: R
) -> Result<IndexIter<K, V>, PE<IndexOpsError>>where
K: IndexType,
V: IndexType,
R: RangeBounds<K>,
pub fn range<K, V, R>(
&self,
index_name: &str,
range: R
) -> Result<IndexIter<K, V>, PE<IndexOpsError>>where
K: IndexType,
V: IndexType,
R: RangeBounds<K>,
Browse a range of keys and values from and index.
Example
let iter:IndexIter<u8,u8> = persy.range("my_new_index",10..12)?;
for (k,values) in iter {
for value in values {
//...
}
}
sourcepub fn list_segments(
&self
) -> Result<Vec<(String, SegmentId)>, PE<GenericError>>
pub fn list_segments(
&self
) -> Result<Vec<(String, SegmentId)>, PE<GenericError>>
List all the existing segments.
Example
let mut tx = persy.begin()?;
tx.create_segment("seg")?;
let prepared = tx.prepare()?;
prepared.commit()?;
let segments = persy.list_segments()?;
let names = segments.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
assert!(names.contains(&"seg".to_string()));
sourcepub fn list_indexes(&self) -> Result<Vec<(String, IndexInfo)>, PE<GenericError>>
pub fn list_indexes(&self) -> Result<Vec<(String, IndexInfo)>, PE<GenericError>>
List all the existing indexes.
Example
let mut tx = persy.begin()?;
tx.create_index::<u8,u8>("index", ValueMode::Cluster)?;
let prepared = tx.prepare()?;
prepared.commit()?;
let indexes = persy.list_indexes()?;
let names = indexes.into_iter().map(|(name,_info)|name).collect::<Vec<String>>();
assert!(names.contains(&"index".to_string()));