Struct persy::Persy

source ·
pub struct Persy { /* private fields */ }
Expand description

Main structure to operate persy storage files

Implementations§

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?
src/lib.rs (line 271)
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)
    }

Create a new database file.

Errors

Fails if the file already exists.

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?
src/lib.rs (line 272)
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)
    }

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.

Examples found in repository?
src/lib.rs (line 161)
160
161
162
    pub fn open<P: AsRef<Path>>(path: P, config: Config) -> Result<Persy, PE<OpenError>> {
        Persy::open_with_recover(path, config, |_| true)
    }

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.

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.

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.

Examples found in repository?
src/lib.rs (line 178)
173
174
175
176
177
178
179
    pub fn open_with_recover<P: AsRef<Path>, C>(path: P, config: Config, recover: C) -> Result<Persy, PE<OpenError>>
    where
        C: Fn(&TransactionId) -> bool,
    {
        let f = fs::OpenOptions::new().write(true).read(true).open(path)?;
        Persy::open_from_file_with_recover(f, config, recover)
    }

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(())
})?;

Begin a new transaction.

The transaction isolation level is ‘read_committed’. for commit call prepare and commit

Example
let mut tx = persy.begin()?;
// ...
tx.prepare()?.commit()?;

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()?;
Examples found in repository?
src/lib.rs (line 302)
301
302
303
    pub fn begin(&self) -> Result<Transaction, PE<BeginTransactionError>> {
        self.begin_with(TransactionConfig::new())
    }

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")?);

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?
src/lib.rs (line 417)
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(),
        ))
    }

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?
src/lib.rs (line 500)
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()))
    }

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);

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);

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")?);

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 {
    //...
}
Examples found in repository?
src/lib.rs (line 532)
527
528
529
530
531
532
533
    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())
    }

Get one value or none from a key.

Example
if let Some(value) = persy.one::<u8,u8>("my_new_index",&10)? {
    //...
}

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 {
        //...
    }
}

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()));

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()));

Create a read snapshot at the current data status.

// ... More logic
let snapshot = persy.snapshot()?;
// .. Access data from the snapshot

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.