1
//! # Persy - Transactional Persistence Engine
2
//!
3
//! Simple single file, durable, paginated, transactional persistence engine, based on copy on write, write
4
//! ahead log, two phase commit.
5
//!
6
//! # Example
7
//!
8
//! ```rust
9
//! use persy::{Persy,Config};
10
//! //...
11
//! # use persy::PRes;
12
//! # fn foo() -> PRes<()> {
13
//! Persy::create("./open.persy")?;
14
//! let persy = Persy::open("./open.persy",Config::new())?;
15
//! let mut tx = persy.begin()?;
16
//! tx.create_segment("seg")?;
17
//! let data = vec![1;20];
18
//! tx.insert("seg", &data)?;
19
//! let prepared = tx.prepare()?;
20
//! prepared.commit()?;
21
//! for (_id,content) in persy.scan("seg")? {
22
//!     assert_eq!(content[0], 20);
23
//!     //....
24
//! }
25
//! # Ok(())
26
//! # }
27
//! ```
28
//!
29
//!
30

31
mod address;
32
mod allocator;
33
mod config;
34
mod discref;
35
mod error;
36
mod flush_checksum;
37
mod id;
38
mod index;
39
mod io;
40
mod journal;
41
mod locks;
42
mod persy;
43
mod record_scanner;
44
mod segment;
45
mod snapshot;
46
mod transaction;
47

48
#[cfg(feature = "background_ops")]
49
mod background;
50

51
pub use crate::{
52
    config::{Config, TransactionConfig, TxStrategy},
53
    error::{PRes, PersyError},
54
    id::{IndexId, PersyId, SegmentId, ToIndexId, ToSegmentId},
55
    index::config::{ByteVec, IndexType, IndexTypeId, ValueMode},
56
    index::nodes::Value,
57
    persy::{IndexInfo, RecoverStatus},
58
};
59
use crate::{
60
    index::keeper::{IndexRawIter, TxIndexRawIter},
61
    persy::{PersyImpl, RecoverImpl, TxFinalize},
62
    record_scanner::{SegmentRawIter, SegmentSnapshotRawIter, TxSegmentRawIter},
63
    snapshot::SnapshotId,
64
};
65

66
use fs2::FileExt;
67
use std::{
68
    fs::{self, File},
69
    mem::replace,
70
    ops::RangeBounds,
71
    path::Path,
72
    sync::Arc,
73
};
74

75
/// Transaction container, it include all the changes done in a transaction.
76
pub struct Transaction {
77
    persy_impl: Arc<PersyImpl>,
78
    tx: Option<transaction::Transaction>,
79
}
80
/// Custom identifier to track the transaction in the recover phase
81
pub type TransactionId = Vec<u8>;
82

83
/// Main structure to operate persy storage files
84
///
85 1
#[derive(Clone)]
86
pub struct Persy {
87 1
    persy_impl: Arc<PersyImpl>,
88
}
89

90
/// Options, flags, configs which can be used
91
/// to configure how a persy database is opened.
92
///
93
/// ```
94
/// use persy::{OpenOptions, Persy, PersyId, PRes, ValueMode};
95
///
96
/// # fn main() -> PRes<()> {
97
/// // This function will only be called on database creation
98
/// fn init(persy: &Persy) -> PRes<()> {
99
///     let mut tx = persy.begin()?;
100
///
101
///     tx.create_segment("data")?;
102
///     tx.create_index::<u64, PersyId>("index", ValueMode::REPLACE)?;
103
///
104
///     let prepared = tx.prepare()?;
105
///     prepared.commit()?;
106
///
107
///     println!("Segment and Index successfully created");
108
///     Ok(())
109
/// }
110
///
111
/// let persy = OpenOptions::new().create(true).prepare_with(init).open("target/persy.db")?;
112
/// # std::fs::remove_file("target/persy.db")?;
113
/// # Ok(())
114
/// # }
115
/// ```
116
pub struct OpenOptions {
117
    truncate: bool,
118
    create: bool,
119
    create_new: bool,
120
    config: Config,
121
    prepare: Option<Box<dyn Fn(&Persy) -> PRes<()>>>,
122
    recover: Option<Box<dyn Fn(&Vec<u8>) -> bool>>,
123
}
124

125
impl OpenOptions {
126 1
    pub fn new() -> OpenOptions {
127 1
        OpenOptions {
128
            truncate: false,
129
            create: false,
130
            create_new: false,
131 1
            config: Config::new(),
132 1
            prepare: None,
133 1
            recover: None,
134
        }
135 1
    }
136
    /// Truncate the file on open removing all the persistent data
137 1
    pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
138 1
        self.truncate = truncate;
139
        self
140 1
    }
141

142
    /// Create a new file if not exists
143 1
    pub fn create(&mut self, create: bool) -> &mut OpenOptions {
144 1
        self.create = create;
145
        self
146 1
    }
147

148
    /// Create a new file if exists fail
149 1
    pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions {
150 1
        self.create_new = create_new;
151
        self
152 1
    }
153

154
    /// Provide a function for initialize the storage in case did not existed
155
    ///
156 1
    pub fn prepare_with<F>(&mut self, prepare: F) -> &mut OpenOptions
157
    where
158
        F: Fn(&Persy) -> PRes<()> + 'static,
159
    {
160 1
        self.prepare = Some(Box::new(prepare));
161
        self
162 1
    }
163

164
    /// Provide a function for check if a transaction must be committed or rollback in case of
165
    /// recover from crash
166
    pub fn recover_with<F>(&mut self, recover: F) -> &mut OpenOptions
167
    where
168
        F: Fn(&Vec<u8>) -> bool + 'static,
169
    {
170
        self.recover = Some(Box::new(recover));
171
        self
172
    }
173

174
    /// Provide general storage configurations
175
    pub fn config(&mut self, config: Config) -> &mut OpenOptions {
176
        self.config = config;
177
        self
178
    }
179

180
    /// Open a file to a recover structure to list pending transactions and select witch commit and
181
    /// rollback
182 1
    pub fn recover<P>(&mut self, path: P) -> PRes<Recover>
183
    where
184
        P: AsRef<Path>,
185
    {
186 1
        let path = path.as_ref();
187 1
        let must_prepare = !path.exists() || self.truncate;
188

189 1
        let file = fs::OpenOptions::new()
190
            .read(true)
191
            .write(true)
192 1
            .create(self.create)
193 1
            .create_new(self.create_new)
194 1
            .open(path)?;
195

196 1
        let config = self.config.clone();
197

198
        // according to the dup2 documentation any acquired lock
199
        // is shared with duplicated file descriptors (try_clone).
200
        // https://www.mkssoftware.com/docs/man3/dup2.3.asp
201 1
        file.try_lock_exclusive()?;
202

203 1
        if self.truncate {
204 1
            file.set_len(0)?;
205
        }
206

207 1
        if must_prepare {
208 1
            let file2 = file.try_clone()?;
209 1
            Persy::create_from_file(file)?;
210 1
            let (persy_impl, recov) = PersyImpl::open_recover(file2, config)?;
211 1
            let p = Arc::new(persy_impl);
212 1
            if let Some(prepare) = &mut self.prepare {
213 1
                let persy = Persy { persy_impl: p.clone() };
214 1
                (prepare)(&persy)?;
215 1
            }
216 1
            Ok(Recover::new(recov, p))
217 1
        } else if let Some(recover) = &self.recover {
218 0
            let (persy_impl, mut recov) = PersyImpl::open_recover(file, config)?;
219 0
            recov.apply(recover)?;
220 0
            Ok(Recover::new(recov, Arc::new(persy_impl)))
221 0
        } else {
222 1
            let (persy_impl, recov) = PersyImpl::open_recover(file, config)?;
223 1
            Ok(Recover::new(recov, Arc::new(persy_impl)))
224 1
        }
225 1
    }
226

227
    /// Open a file from the given path with the current options
228 1
    pub fn open<P>(&mut self, path: P) -> PRes<Persy>
229
    where
230
        P: AsRef<Path>,
231
    {
232 1
        let recover = self.recover(path)?;
233 1
        recover.finalize()
234 1
    }
235

236
    /// Create a persy instance backed by a `Vec<u8>` with no persistence
237 1
    pub fn memory(&mut self) -> PRes<Persy> {
238 1
        let config = self.config.clone();
239 1
        let persy_impl = PersyImpl::memory(config)?;
240 1
        let persy = Persy {
241 1
            persy_impl: Arc::new(persy_impl),
242
        };
243 1
        if let Some(prepare) = &mut self.prepare {
244 0
            (prepare)(&persy)?;
245
        }
246 1
        Ok(persy)
247 1
    }
248
}
249

250
impl Default for OpenOptions {
251
    fn default() -> OpenOptions {
252
        OpenOptions::new()
253
    }
254
}
255
/// Intermediate recover status to select witch transactions to commit or rollback and list witch
256
/// transactions are in a intermediate state
257
///
258
/// # Example
259
///
260
///
261
/// ```rust
262
/// # use persy::{Persy,Config,PRes};
263
/// # fn foo() -> PRes<()> {
264
/// # Persy::create("./recover_example.persy")?;
265
/// let mut recover = Persy::recover("./recover_example.persy", Config::new())?;
266
/// for (tx_id,status) in recover.list_transactions()? {
267
///     // Check the transaction if can be committed using the tx_id
268
///     if true {
269
///         // if so commit the tx
270
///         recover.commit(tx_id)?;
271
///     } else {
272
///         // otherwise roll back it
273
///         recover.rollback(tx_id)?;
274
///     }
275
///     // finalize all the transaction marked to finalize and get a persy instance.
276
/// }
277
/// let persy = recover.finalize()?;
278
/// # Ok(())
279
/// # }
280
/// ```
281

282
///
283
///
284
pub struct Recover {
285
    recover_impl: RecoverImpl,
286
    persy_impl: Arc<PersyImpl>,
287
}
288

289
impl Recover {
290 1
    fn new(recover_impl: RecoverImpl, persy_impl: Arc<PersyImpl>) -> Recover {
291 1
        Recover {
292 1
            recover_impl,
293
            persy_impl,
294
        }
295 1
    }
296
    /// List all the transactions found in the log with the current status
297 1
    pub fn list_transactions(&self) -> PRes<Vec<(TransactionId, RecoverStatus)>> {
298 1
        self.recover_impl.list_transactions()
299 1
    }
300
    /// Mark to commit a transaction in the log with state prepared commit
301 1
    pub fn commit(&mut self, tx_id: TransactionId) -> PRes<()> {
302 1
        self.recover_impl.commit(tx_id)
303 1
    }
304
    /// Mark to rollback a transaction that is not yet committed
305 1
    pub fn rollback(&mut self, tx_id: TransactionId) -> PRes<()> {
306 1
        self.recover_impl.rollback(tx_id)
307 1
    }
308
    /// Read the status of a transaction in the log
309
    pub fn status(&self, tx_id: TransactionId) -> PRes<Option<RecoverStatus>> {
310
        self.recover_impl.status(tx_id)
311
    }
312
    /// Recover all the prepared committed transactions that are not marked to rollback
313 1
    pub fn finalize(self) -> PRes<Persy> {
314 1
        self.persy_impl.final_recover(self.recover_impl)?;
315 1
        Ok(Persy {
316 1
            persy_impl: self.persy_impl,
317
        })
318 1
    }
319
}
320

321
/// prepared transaction state
322
#[must_use]
323
pub struct TransactionFinalize {
324
    persy_impl: Arc<PersyImpl>,
325
    finalize: Option<TxFinalize>,
326
}
327

328
impl TransactionFinalize {
329
    /// Rollback a prepared commit.
330
    ///
331
    /// All the modification are rolled back and all the used resources are put released
332
    ///
333
    /// # Example
334
    ///
335
    /// ```rust
336
    /// # use persy::{Persy,Config,PRes};
337
    /// # fn foo() -> PRes<()> {
338
    /// # Persy::create("./open.persy")?;
339
    /// # let persy = Persy::open("./open.persy",Config::new())?;
340
    /// let mut tx = persy.begin()?;
341
    /// //Do what ever operations on the records
342
    /// let data = vec![1;20];
343
    /// tx.insert("seg", &data)?;
344
    /// let prepared = tx.prepare()?;
345
    /// prepared.rollback()?;
346
    /// # Ok(())
347
    /// # }
348
    /// ```
349 1
    pub fn rollback(mut self) -> PRes<()> {
350 1
        if let Some(mut finalize) = replace(&mut self.finalize, None) {
351 1
            self.persy_impl.rollback_prepared(&mut finalize)?;
352 1
        }
353 1
        Ok(())
354 1
    }
355

356
    /// Finalize the commit result of a prepared commit.
357
    ///
358
    /// All the operation done on the transaction are finalized all the lock released, all the
359
    /// old resources are released for reuse.
360
    ///
361
    /// # Example
362
    ///
363
    /// ```rust
364
    /// # use persy::{Persy,Config,PRes};
365
    /// # fn foo() -> PRes<()> {
366
    /// # Persy::create("./open.persy")?;
367
    /// # let persy = Persy::open("./open.persy",Config::new())?;
368
    /// let mut tx = persy.begin()?;
369
    /// let prepared = tx.prepare()?;
370
    /// prepared.commit()?;
371
    /// # Ok(())
372
    /// # }
373
    /// ```
374 1
    pub fn commit(mut self) -> PRes<()> {
375 1
        if let Some(mut finalize) = replace(&mut self.finalize, None) {
376 1
            self.persy_impl.commit(&mut finalize)?;
377 1
        }
378 1
        Ok(())
379 1
    }
380
}
381

382
impl Drop for TransactionFinalize {
383 1
    fn drop(&mut self) {
384 1
        if let Some(mut finalize) = replace(&mut self.finalize, None) {
385 1
            self.persy_impl.rollback_prepared(&mut finalize).unwrap();
386 1
        }
387 1
    }
388
}
389

390
/// Index Iterator implementation for iterating on a range of keys
391
pub struct IndexIter<K: IndexType, V: IndexType> {
392
    iter_impl: IndexRawIter<K, V>,
393
    persy_impl: Arc<PersyImpl>,
394
}
395

396
impl<K: IndexType, V: IndexType> IndexIter<K, V> {
397 1
    fn new(iter_impl: IndexRawIter<K, V>, persy_impl: Arc<PersyImpl>) -> IndexIter<K, V> {
398 1
        IndexIter { iter_impl, persy_impl }
399 1
    }
400
}
401

402
impl<K, V> Iterator for IndexIter<K, V>
403
where
404
    K: IndexType,
405
    V: IndexType,
406
{
407
    type Item = (K, Value<V>);
408

409 1
    fn next(&mut self) -> Option<Self::Item> {
410 1
        self.iter_impl.next(&self.persy_impl)
411 1
    }
412
}
413
impl<K, V> DoubleEndedIterator for IndexIter<K, V>
414
where
415
    K: IndexType,
416
    V: IndexType,
417
{
418 1
    fn next_back(&mut self) -> Option<Self::Item> {
419 1
        self.iter_impl.next_back(&self.persy_impl)
420 1
    }
421
}
422

423
impl<K, V> Drop for IndexIter<K, V>
424
where
425
    K: IndexType,
426
    V: IndexType,
427
{
428 1
    fn drop(&mut self) {
429 1
        self.iter_impl.release(&self.persy_impl).unwrap()
430 1
    }
431
}
432

433
/// Index Iterator implementation for iterating on a range of keys
434
pub struct TxIndexIter<'a, K: IndexType, V: IndexType> {
435
    iter_impl: TxIndexRawIter<K, V>,
436
    tx: &'a mut Transaction,
437
}
438

439
impl<'a, K: IndexType, V: IndexType> TxIndexIter<'a, K, V> {
440 1
    fn new(iter_impl: TxIndexRawIter<K, V>, tx: &'a mut Transaction) -> TxIndexIter<'a, K, V> {
441 1
        TxIndexIter { iter_impl, tx }
442 1
    }
443

444
    /// get the next element in the iterator giving the access on the transaction owned by the
445
    /// iterator
446 1
    pub fn next_tx(&mut self) -> Option<(K, Value<V>, &mut Transaction)> {
447 1
        if let Some((k, v)) = self.iter_impl.next(&self.tx.persy_impl, self.tx.tx.as_mut().unwrap()) {
448 1
            Some((k, v, self.tx))
449
        } else {
450 1
            None
451
        }
452 1
    }
453

454
    /// Direct access to the transaction owned by the iterator
455 1
    pub fn tx(&mut self) -> &mut Transaction {
456 1
        self.tx
457 1
    }
458
}
459

460
impl<'a, K, V> Iterator for TxIndexIter<'a, K, V>
461
where
462
    K: IndexType,
463
    V: IndexType,
464
{
465
    type Item = (K, Value<V>);
466

467 1
    fn next(&mut self) -> Option<Self::Item> {
468 1
        self.iter_impl.next(&self.tx.persy_impl, self.tx.tx.as_mut().unwrap())
469 1
    }
470
}
471

472
impl<'a, K, V> DoubleEndedIterator for TxIndexIter<'a, K, V>
473
where
474
    K: IndexType,
475
    V: IndexType,
476
{
477 1
    fn next_back(&mut self) -> Option<Self::Item> {
478 1
        self.iter_impl
479 1
            .next_back(&self.tx.persy_impl, self.tx.tx.as_mut().unwrap())
480 1
    }
481
}
482

483
/// Iterator implementation to scan a segment
484
pub struct SegmentIter {
485
    iter_impl: SegmentRawIter,
486
    persy_impl: Arc<PersyImpl>,
487
}
488

489
impl SegmentIter {
490 1
    fn new(iter_impl: SegmentRawIter, persy_impl: Arc<PersyImpl>) -> SegmentIter {
491 1
        SegmentIter { iter_impl, persy_impl }
492 1
    }
493
}
494

495
impl Iterator for SegmentIter {
496
    type Item = (PersyId, Vec<u8>);
497

498 1
    fn next(&mut self) -> Option<Self::Item> {
499 1
        self.iter_impl.next(&self.persy_impl)
500 1
    }
501
}
502

503
impl Drop for SegmentIter {
504 1
    fn drop(&mut self) {
505 1
        self.iter_impl.release(&self.persy_impl).unwrap()
506 1
    }
507
}
508

509
struct RawIterDrop {
510
    iter_impl: TxSegmentRawIter,
511
    persy_impl: Arc<PersyImpl>,
512
}
513

514
impl<'a> Drop for RawIterDrop {
515 1
    fn drop(&mut self) {
516 1
        self.iter_impl.release(&self.persy_impl).unwrap()
517 1
    }
518
}
519

520
/// Iterator implementation to scan a segment considering in transaction changes.
521
pub struct TxSegmentIter<'a> {
522
    iter_impl: RawIterDrop,
523
    tx: &'a mut Transaction,
524
}
525

526
impl<'a> TxSegmentIter<'a> {
527 1
    fn new(iter_impl: TxSegmentRawIter, tx: &'a mut Transaction) -> TxSegmentIter<'a> {
528 1
        TxSegmentIter {
529 1
            iter_impl: RawIterDrop {
530 1
                iter_impl,
531 1
                persy_impl: tx.persy_impl.clone(),
532 0
            },
533
            tx,
534
        }
535 1
    }
536

537
    /// get the next element in the iterator giving the access on the transaction owned by the
538
    /// iterator
539 1
    pub fn next_tx(&mut self) -> Option<(PersyId, Vec<u8>, &mut Transaction)> {
540 1
        if let Some((id, rec, _)) = self
541
            .iter_impl
542
            .iter_impl
543 1
            .next(&self.tx.persy_impl, &self.tx.tx.as_mut().unwrap())
544
        {
545 1
            Some((id, rec, self.tx))
546
        } else {
547 1
            None
548
        }
549 1
    }
550

551
    /// Direct access to the transaction owned by the iterator
552 1
    pub fn tx(&mut self) -> &mut Transaction {
553 1
        self.tx
554 1
    }
555
}
556

557
impl<'a> Iterator for TxSegmentIter<'a> {
558
    type Item = (PersyId, Vec<u8>);
559

560 1
    fn next(&mut self) -> Option<Self::Item> {
561 1
        self.iter_impl
562
            .iter_impl
563 1
            .next(&self.tx.persy_impl, &self.tx.tx.as_mut().unwrap())
564 1
            .map(|(id, content, _)| (id, content))
565 1
    }
566
}
567

568
impl Persy {
569
    /// Create a new database file.
570
    ///
571
    /// # Errors
572
    ///
573
    /// Fails if the file already exists.
574
    ///
575 1
    pub fn create<P: AsRef<Path>>(path: P) -> PRes<()> {
576 1
        PersyImpl::create(path.as_ref())
577 0
    }
578

579
    /// Create a new database file.
580
    ///
581
    /// # Errors
582
    ///
583
    /// Fails if the file already exists.
584
    ///
585 1
    pub fn create_from_file(file: File) -> PRes<()> {
586 1
        PersyImpl::create_from_file(file)
587 1
    }
588

589
    /// Open a database file.
590
    ///
591
    /// The file should have been created with [`Persy::create`]
592
    ///
593
    /// # Errors
594
    ///
595
    /// Fails if the file does not exist.
596
    ///
597
    /// [`Persy::create`]: struct.Persy.html#method.create
598 1
    pub fn open<P: AsRef<Path>>(path: P, config: Config) -> PRes<Persy> {
599 1
        Persy::open_with_recover(path, config, |_| true)
600 1
    }
601

602
    /// Open a database file from a path with a recover function.
603
    ///
604
    /// The file should have been created with [`Persy::create`]
605
    ///
606
    /// # Errors
607
    ///
608
    /// Fails if the file does not exist.
609
    ///
610
    /// [`Persy::create`]: struct.Persy.html#method.create
611 1
    pub fn open_with_recover<P: AsRef<Path>, C>(path: P, config: Config, recover: C) -> PRes<Persy>
612
    where
613
        C: Fn(&TransactionId) -> bool,
614
    {
615 1
        let f = fs::OpenOptions::new().write(true).read(true).open(path)?;
616 1
        Persy::open_from_file_with_recover(f, config, recover)
617 1
    }
618

619
    /// Open a database file from a path and return a recover structure that allow to select the
620
    /// transactions to commit and recover them.
621
    ///
622
    /// The file should have been created with [`Persy::create`]
623
    ///
624
    /// # Errors
625
    ///
626
    /// Fails if the file does not exist.
627
    ///
628
    /// [`Persy::create`]: struct.Persy.html#method.create
629 1
    pub fn recover<P: AsRef<Path>>(path: P, config: Config) -> PRes<Recover> {
630 1
        let f = fs::OpenOptions::new().write(true).read(true).open(path)?;
631 1
        let (persy_impl, recover) = PersyImpl::open_recover(f, config)?;
632 1
        Ok(Recover::new(recover, Arc::new(persy_impl)))
633 1
    }
634

635
    /// Open a database file from a direct file handle.
636
    ///
637
    /// The file should have been created with [`Persy::create`]
638
    ///
639
    /// # Errors
640
    ///
641
    /// Fails if the file does not exist.
642
    ///
643
    /// [`Persy::create`]: struct.Persy.html#method.create
644 1
    pub fn open_from_file(path: File, config: Config) -> PRes<Persy> {
645 1
        let (persy_impl, recover) = PersyImpl::open_recover(path, config)?;
646 1
        persy_impl.final_recover(recover)?;
647 1
        Ok(Persy {
648 1
            persy_impl: Arc::new(persy_impl),
649
        })
650 1
    }
651

652
    /// Open a database file, from a direct file handle and a transaction recover function.
653
    ///
654
    /// The file should have been created with [`Persy::create`]
655
    ///
656
    /// # Errors
657
    ///
658
    /// Fails if the file does not exist.
659
    ///
660
    /// [`Persy::create`]: struct.Persy.html#method.create
661 1
    pub fn open_from_file_with_recover<C>(path: File, config: Config, recover: C) -> PRes<Persy>
662
    where
663
        C: Fn(&TransactionId) -> bool,
664
    {
665 1
        let (persy_impl, mut recov) = PersyImpl::open_recover(path, config)?;
666 1
        recov.apply(recover)?;
667 1
        persy_impl.final_recover(recov)?;
668 1
        Ok(Persy {
669 1
            persy_impl: Arc::new(persy_impl),
670
        })
671 1
    }
672

673
    /// Open an existing database or create it if it does not exist yet,
674
    /// calling the `prepare` function just after the creation.
675
    ///
676
    /// # Example
677
    ///
678
    /// ```rust
679
    /// use std::path::Path;
680
    /// use persy::{Persy, Config, PersyId, ValueMode};
681
    /// # use persy::PRes;
682
    ///
683
    /// # fn main() -> PRes<()> {
684
    /// let path = Path::new("target/open_or_create.db");
685
    /// let config = Config::new();
686
    ///
687
    /// let persy = Persy::open_or_create_with(path, config, |persy| {
688
    ///     // this closure is only called on database creation
689
    ///     let mut tx = persy.begin()?;
690
    ///     tx.create_segment("data")?;
691
    ///     tx.create_index::<u64, PersyId>("index", ValueMode::REPLACE)?;
692
    ///     let prepared = tx.prepare()?;
693
    ///     prepared.commit()?;
694
    ///     println!("Segment and Index successfully created");
695
    ///     Ok(())
696
    /// })?;
697
    /// # std::fs::remove_file("target/open_or_create.db")?;
698
    /// # Ok(())
699
    /// # }
700
    /// ```
701
    pub fn open_or_create_with<P, F>(path: P, config: Config, prepare: F) -> PRes<Persy>
702
    where
703
        P: AsRef<Path>,
704
        F: FnOnce(&Persy) -> PRes<()>,
705
    {
706
        let path = path.as_ref();
707
        let persy;
708

709
        if !path.exists() {
710
            Persy::create(path)?;
711
            persy = Persy::open(path, config)?;
712
            prepare(&persy)?;
713
        } else {
714
            persy = Persy::open(path, config)?;
715
        }
716

717
        Ok(persy)
718
    }
719

720
    /// Begin a new transaction.
721
    ///
722
    /// The transaction isolation level is 'read_commited'.
723
    /// for commit call [`prepare`] and [`commit`]
724
    ///
725
    /// [`prepare`]:struct.Transaction.html#method.prepare
726
    /// [`commit`]:struct.TransactionFinalize.html#method.commit
727
    ///
728
    /// # Example
729
    ///
730
    /// ```rust
731
    /// # use persy::{Persy,Config,PRes};
732
    /// # fn foo() -> PRes<()> {
733
    /// # Persy::create("./open.persy")?;
734
    /// # let persy = Persy::open("./open.persy",Config::new())?;
735
    /// let mut tx = persy.begin()?;
736
    /// // ...
737
    /// tx.prepare()?.commit()?;
738
    /// # Ok(())
739
    /// # }
740
    /// ```
741 1
    pub fn begin(&self) -> PRes<Transaction> {
742 1
        self.begin_with(TransactionConfig::new())
743 1
    }
744

745
    /// Begin a new transaction specifying and id usable for crash recover.
746
    ///
747
    /// The transaction isolation level is 'read_commited'.
748
    /// for commit call [`prepare`] and [`commit`]
749
    ///
750
    /// [`prepare`]:struct.Transaction.html#method.prepare
751
    /// [`commit`]:struct.TransactionFinalize.html#method.commit
752
    ///
753
    /// # Example
754
    ///
755
    /// ```rust
756
    /// # use persy::{Persy,Config,PRes};
757
    /// # fn foo() -> PRes<()> {
758
    /// # Persy::create("./open.persy")?;
759
    /// # let persy = Persy::open("./open.persy",Config::new())?;
760
    /// let tx_id = vec![2;2];
761
    /// let mut tx = persy.begin_id(tx_id)?;
762
    /// // ...
763
    /// tx.prepare()?.commit()?;
764
    /// # Ok(())
765
    /// # }
766
    /// ```
767
    #[deprecated = "replaced by 'begin_with'"]
768
    pub fn begin_id(&self, meta_id: TransactionId) -> PRes<Transaction> {
769
        self.begin_with(TransactionConfig::new().set_transaction_id(meta_id))
770
    }
771

772
    /// Begin a new transaction specifying parameters for the transaction.
773
    ///
774
    /// The transaction isolation level is 'read_commited'.
775
    /// for commit call [`prepare`] and [`commit`]
776
    ///
777
    /// [`prepare`]:struct.Transaction.html#method.prepare
778
    /// [`commit`]:struct.TransactionFinalize.html#method.commit
779
    ///
780
    /// # Example
781
    ///
782
    /// ```rust
783
    /// # use persy::{Persy,Config, TransactionConfig,PRes};
784
    /// # fn foo() -> PRes<()> {
785
    /// # Persy::create("./open.persy")?;
786
    /// # let persy = Persy::open("./open.persy",Config::new())?;
787
    /// let tx_id = vec![2;2];
788
    /// let mut tx = persy.begin_with(TransactionConfig::new().set_transaction_id(tx_id))?;
789
    /// // ...
790
    /// tx.prepare()?.commit()?;
791
    /// # Ok(())
792
    /// # }
793
    /// ```
794 1
    pub fn begin_with(&self, config: TransactionConfig) -> PRes<Transaction> {
795 1
        Ok(Transaction {
796 1
            tx: Some(self.persy_impl.begin_with(config)?),
797 1
            persy_impl: self.persy_impl.clone(),
798 0
        })
799 1
    }
800

801
    /// Check if a segment already exist in the storage
802
    ///
803
    /// # Example
804
    ///
805
    /// ```rust
806
    /// # use persy::{Persy,Config,PRes};
807
    /// # fn foo() -> PRes<()> {
808
    /// # Persy::create("./open.persy")?;
809
    /// # let persy = Persy::open("./open.persy",Config::new())?;
810
    /// let mut tx = persy.begin()?;
811
    /// tx.create_segment("my_new_segment")?;
812
    /// let prepared = tx.prepare()?;
813
    /// prepared.commit()?;
814
    /// assert!(persy.exists_segment("my_new_segment")?);
815
    /// # Ok(())
816
    /// # }
817
    /// ```
818 1
    pub fn exists_segment(&self, segment: &str) -> PRes<bool> {
819 1
        self.persy_impl.exists_segment(segment)
820 1
    }
821

822
    /// Resolves the segment to a SegmentId
823
    ///
824
    /// # Example
825
    ///
826
    /// ```rust
827
    /// # use persy::{Persy,Config,PRes};
828
    /// # fn foo() -> PRes<()> {
829
    /// # Persy::create("./open.persy")?;
830
    /// # let persy = Persy::open("./open.persy",Config::new())?;
831
    /// let mut tx = persy.begin()?;
832
    /// tx.create_segment("my_new_segment")?;
833
    /// let prepared = tx.prepare()?;
834
    /// prepared.commit()?;
835
    /// let segment_id = persy.solve_segment_id("my_new_segment")?;
836
    /// # Ok(())
837
    /// # }
838
    /// ```
839 1
    pub fn solve_segment_id(&self, segment: impl ToSegmentId) -> PRes<SegmentId> {
840
        //TODO: find a better name and make this public again
841 1
        self.persy_impl.solve_segment_id(segment)
842 1
    }
843

844
    /// Resolves the index to a IndexId
845
    ///
846
    /// # Example
847
    ///
848
    /// ```rust
849
    /// # use persy::{Persy,Config,PRes,ValueMode};
850
    /// # fn foo() -> PRes<()> {
851
    /// # Persy::create("./open.persy")?;
852
    /// # let persy = Persy::open("./open.persy",Config::new())?;
853
    /// let mut tx = persy.begin()?;
854
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
855
    /// let prepared = tx.prepare()?;
856
    /// prepared.commit()?;
857
    /// let segment_id = persy.solve_index_id("my_new_index")?;
858
    /// # Ok(())
859
    /// # }
860
    /// ```
861 1
    pub fn solve_index_id(&self, index: impl ToIndexId) -> PRes<IndexId> {
862
        //TODO: find a better name and make this public again
863 1
        self.persy_impl.solve_index_id(index)
864 1
    }
865

866
    #[deprecated = "use Persy::read instead"]
867
    pub fn read_record(&self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
868
        self.read(segment, id)
869
    }
870

871
    /// Read the record content from persistent data.
872
    ///
873
    ///
874
    /// # Example
875
    ///
876
    /// ```rust
877
    /// # use persy::{Persy,Config,PRes};
878
    /// # fn foo() -> PRes<()> {
879
    /// # Persy::create("./open.persy")?;
880
    /// # let persy = Persy::open("./open.persy",Config::new())?;
881
    /// let mut tx = persy.begin()?;
882
    /// # tx.create_segment("seg")?;
883
    /// let data = vec![1;20];
884
    /// let id = tx.insert("seg", &data)?;
885
    /// let prepared = tx.prepare()?;
886
    /// prepared.commit()?;
887
    /// let read = persy.read("seg", &id)?.expect("record exits");
888
    /// assert_eq!(data,read);
889
    /// # Ok(())
890
    /// # }
891
    /// ```
892 1
    pub fn read(&self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
893 1
        let segment_id = self.solve_segment_id(segment)?;
894 1
        self.persy_impl.read(segment_id, &id.0)
895 1
    }
896

897
    /// Scan a segment for persistent records
898
    ///
899
    /// # Example
900
    ///
901
    /// ```rust
902
    /// # use persy::{Persy,Config,PRes};
903
    /// # fn foo() -> PRes<()> {
904
    /// # Persy::create("./open.persy")?;
905
    /// # let persy = Persy::open("./open.persy",Config::new())?;
906
    /// let mut tx = persy.begin()?;
907
    /// # tx.create_segment("seg")?;
908
    /// let data = vec![1;20];
909
    /// let id = tx.insert("seg", &data)?;
910
    /// let prepared = tx.prepare()?;
911
    /// prepared.commit()?;
912
    /// let mut count = 0;
913
    /// for (id,content) in persy.scan("seg")? {
914
    ///     println!("record size:{}",content.len());
915
    ///     count+=1;
916
    /// }
917
    /// assert_eq!(count,1);
918
    /// # Ok(())
919
    /// # }
920
    /// ```
921 1
    pub fn scan(&self, segment: impl ToSegmentId) -> PRes<SegmentIter> {
922 1
        let segment_id = self.solve_segment_id(segment)?;
923 1
        Ok(SegmentIter::new(
924 1
            self.persy_impl.scan(segment_id)?,
925 1
            self.persy_impl.clone(),
926 1
        ))
927 1
    }
928

929
    /// Check if a segment already exist in the storage
930
    ///
931
    /// # Example
932
    ///
933
    /// ```rust
934
    /// # use persy::{Persy,Config,PRes,ValueMode};
935
    /// # fn foo() -> PRes<()> {
936
    /// # Persy::create("./open.persy")?;
937
    /// # let persy = Persy::open("./open.persy",Config::new())?;
938
    /// let mut tx = persy.begin()?;
939
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::REPLACE)?;
940
    /// let prepared = tx.prepare()?;
941
    /// prepared.commit()?;
942
    /// assert!(persy.exists_index("my_new_index")?);
943
    /// # Ok(())
944
    /// # }
945
    /// ```
946 1
    pub fn exists_index(&self, segment: &str) -> PRes<bool> {
947 1
        self.persy_impl.exists_index(segment)
948 1
    }
949

950
    /// Get a value or a group of values from a key.
951
    ///
952
    /// # Example
953
    ///
954
    /// ```rust
955
    /// # use persy::{Persy,Config,PRes,ValueMode, Value};
956
    /// # fn foo() -> PRes<()> {
957
    /// # Persy::create("./data.persy")?;
958
    /// # let persy = Persy::open("./data.persy",Config::new())?;
959
    /// # let mut tx = persy.begin()?;
960
    /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
961
    /// # tx.put::<u8,u8>("my_new_index",10,10)?;
962
    /// # let prepared = tx.prepare()?;
963
    /// # prepared.commit()?;
964
    /// let val = persy.get::<u8,u8>("my_new_index",&10)?;
965
    /// if let Some(is_there) = val {
966
    ///     // A value is actually there
967
    ///     match is_there {
968
    ///         Value::SINGLE(actual_value) => {
969
    ///         },
970
    ///         Value::CLUSTER(actual_value) => {
971
    ///         },
972
    ///     }
973
    /// }
974
    /// # Ok(())
975
    /// # }
976
    /// ```
977 1
    pub fn get<K, V>(&self, index_name: &str, k: &K) -> PRes<Option<Value<V>>>
978
    where
979
        K: IndexType,
980
        V: IndexType,
981
    {
982 1
        let index_id = self.solve_index_id(index_name)?;
983 1
        self.persy_impl.get::<K, V>(index_id, k)
984 1
    }
985

986
    /// Browse a range of keys and values from and index.
987
    ///
988
    /// # Example
989
    ///
990
    /// ```rust
991
    /// # use persy::{Persy,Config,PRes,ValueMode, Value,IndexIter};
992
    /// # fn foo() -> PRes<()> {
993
    /// # Persy::create("./data.persy")?;
994
    /// # let persy = Persy::open("./data.persy",Config::new())?;
995
    /// # let mut tx = persy.begin()?;
996
    /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
997
    /// # tx.put::<u8,u8>("my_new_index",10,10)?;
998
    /// # let prepared = tx.prepare()?;
999
    /// # prepared.commit()?;
1000
    /// let iter:IndexIter<u8,u8> = persy.range("my_new_index",10..12)?;
1001
    /// for (k,val) in iter  {
1002
    ///     // A value is actually there
1003
    ///     match val {
1004
    ///         Value::SINGLE(actual_value) => {
1005
    ///         },
1006
    ///         Value::CLUSTER(actual_value) => {
1007
    ///         },
1008
    ///     }
1009
    /// }
1010
    /// # Ok(())
1011
    /// # }
1012
    /// ```
1013 1
    pub fn range<K, V, R>(&self, index_name: &str, range: R) -> PRes<IndexIter<K, V>>
1014
    where
1015
        K: IndexType,
1016
        V: IndexType,
1017
        R: RangeBounds<K>,
1018
    {
1019 1
        let index_id = self.solve_index_id(index_name)?;
1020 1
        let (_, raw) = self.persy_impl.range(index_id, range)?;
1021 1
        Ok(IndexIter::new(raw, self.persy_impl.clone()))
1022 1
    }
1023

1024
    /// List all the existing segments.
1025
    ///
1026
    /// # Example
1027
    ///
1028
    /// ```rust
1029
    /// # use persy::{Persy,Config,PRes};
1030
    /// # fn foo() -> PRes<()> {
1031
    /// # Persy::create("./open.persy")?;
1032
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1033
    /// let mut tx = persy.begin()?;
1034
    /// tx.create_segment("seg")?;
1035
    /// let prepared = tx.prepare()?;
1036
    /// prepared.commit()?;
1037
    /// let segments = persy.list_segments()?;
1038
    /// let names = segments.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
1039
    /// assert!(names.contains(&"seg".to_string()));
1040
    /// # Ok(())
1041
    /// # }
1042
    /// ```
1043 1
    pub fn list_segments(&self) -> PRes<Vec<(String, SegmentId)>> {
1044 1
        Ok(self
1045
            .persy_impl
1046 1
            .list_segments()?
1047
            .into_iter()
1048 1
            .map(|(name, id)| (name, SegmentId::new(id)))
1049
            .collect())
1050 1
    }
1051

1052
    /// List all the existing indexes.
1053
    ///
1054
    /// # Example
1055
    ///
1056
    /// ```rust
1057
    /// # use persy::{Persy,Config,PRes, ValueMode};
1058
    /// # fn foo() -> PRes<()> {
1059
    /// # Persy::create("./open.persy")?;
1060
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1061
    /// let mut tx = persy.begin()?;
1062
    /// tx.create_index::<u8,u8>("index", ValueMode::CLUSTER)?;
1063
    /// let prepared = tx.prepare()?;
1064
    /// prepared.commit()?;
1065
    /// let indexes = persy.list_indexes()?;
1066
    /// let names = indexes.into_iter().map(|(name,_info)|name).collect::<Vec<String>>();
1067
    /// assert!(names.contains(&"seg".to_string()));
1068
    /// # Ok(())
1069
    /// # }
1070
    /// ```
1071 1
    pub fn list_indexes(&self) -> PRes<Vec<(String, IndexInfo)>> {
1072 1
        Ok(self.persy_impl.list_indexes()?)
1073 1
    }
1074

1075
    ///  Create a read snapshot at the current data status.
1076
    ///
1077
    ///
1078
    /// ```rust
1079
    /// # use persy::{Persy,Config,PRes,ValueMode};
1080
    /// # fn foo() -> PRes<()> {
1081
    /// # Persy::create("./open.persy")?;
1082
    /// let persy = Persy::open("./open.persy",Config::new())?;
1083
    /// // ... More logic
1084
    /// let snapshot = persy.snapshot()?;
1085
    /// // .. Access data from the snapshot
1086
    /// # Ok(())
1087
    /// # }
1088
    /// ```
1089 1
    pub fn snapshot(&self) -> PRes<Snapshot> {
1090 1
        Ok(Snapshot::new(self.persy_impl.clone(), self.persy_impl.snapshot()?))
1091 1
    }
1092
}
1093

1094 1
fn tx_mut(tx: &mut Option<transaction::Transaction>) -> &mut transaction::Transaction {
1095 1
    tx.as_mut().unwrap()
1096 1
}
1097
impl Transaction {
1098 1
    fn tx_mut(&mut self) -> &mut transaction::Transaction {
1099 1
        tx_mut(&mut self.tx)
1100 1
    }
1101 1
    fn tx(&self) -> &transaction::Transaction {
1102 1
        self.tx.as_ref().unwrap()
1103 1
    }
1104
    /// Create a new segment with the provided name
1105
    ///
1106
    /// # Example
1107
    ///
1108
    /// ```rust
1109
    /// # use persy::{Persy,Config,PRes};
1110
    /// # fn foo() -> PRes<()> {
1111
    /// # Persy::create("./open.persy")?;
1112
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1113
    /// let mut tx = persy.begin()?;
1114
    /// tx.create_segment("my_new_segment")?;
1115
    /// tx.prepare()?.commit()?;
1116
    /// # Ok(())
1117
    /// # }
1118
    /// ```
1119 1
    pub fn create_segment(&mut self, segment: &str) -> PRes<SegmentId> {
1120 1
        assert!(!segment.starts_with(index::config::INDEX_META_PREFIX));
1121 1
        assert!(!segment.starts_with(index::config::INDEX_DATA_PREFIX));
1122 1
        self.persy_impl.create_segment(tx_mut(&mut self.tx), segment)
1123 1
    }
1124

1125
    /// Drop a existing segment
1126
    ///
1127
    /// # Example
1128
    ///
1129
    /// ```rust
1130
    /// # use persy::{Persy,Config,PRes};
1131
    /// # fn foo() -> PRes<()> {
1132
    /// # Persy::create("./open.persy")?;
1133
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1134
    /// let mut tx = persy.begin()?;
1135
    /// tx.drop_segment("existing_segment_name")?;
1136
    /// tx.prepare()?.commit()?;
1137
    /// # Ok(())
1138
    /// # }
1139
    /// ```
1140 1
    pub fn drop_segment(&mut self, segment: &str) -> PRes<()> {
1141 1
        self.persy_impl.drop_segment(tx_mut(&mut self.tx), segment)
1142 1
    }
1143

1144
    /// Check if a segment already exist in the storage considering the transaction
1145
    ///
1146
    ///
1147
    /// # Example
1148
    /// ```rust
1149
    /// # use persy::{Persy,Config,PRes};
1150
    /// # fn foo() -> PRes<()> {
1151
    /// # Persy::create("./open.persy")?;
1152
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1153
    /// let mut tx = persy.begin()?;
1154
    /// tx.create_segment("my_new_segment")?;
1155
    /// assert!(tx.exists_segment("my_new_segment")?);
1156
    /// # tx.prepare()?.commit()?;
1157
    /// # Ok(())
1158
    /// # }
1159
    /// ```
1160 1
    pub fn exists_segment(&self, segment: &str) -> PRes<bool> {
1161 1
        self.persy_impl.exists_segment_tx(self.tx(), segment)
1162 1
    }
1163

1164
    /// Resolves the segment to a SegmentId, considering the transaction
1165
    ///
1166
    /// # Example
1167
    ///
1168
    /// ```rust
1169
    /// # use persy::{Persy,Config,PRes};
1170
    /// # fn foo() -> PRes<()> {
1171
    /// # Persy::create("./open.persy")?;
1172
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1173
    /// let mut tx = persy.begin()?;
1174
    /// tx.create_segment("my_new_segment")?;
1175
    /// let segment_id = tx.solve_segment_id("my_new_segment")?;
1176
    /// # tx.prepare()?.commit()?;
1177
    /// # Ok(())
1178
    /// # }
1179
    /// ```
1180 1
    pub fn solve_segment_id(&self, segment: impl ToSegmentId) -> PRes<SegmentId> {
1181 1
        self.persy_impl.solve_segment_id_tx(self.tx(), segment)
1182 1
    }
1183

1184
    /// Resolves the index name to a IndexId, considering the transaction
1185
    ///
1186
    /// # Example
1187
    ///
1188
    /// ```rust
1189
    /// # use persy::{Persy,Config,PRes, ValueMode};
1190
    /// # fn foo() -> PRes<()> {
1191
    /// # Persy::create("./open.persy")?;
1192
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1193
    /// let mut tx = persy.begin()?;
1194
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1195
    /// let segment_id = tx.solve_index_id("my_new_index")?;
1196
    /// # tx.prepare()?.commit()?;
1197
    /// # Ok(())
1198
    /// # }
1199
    /// ```
1200 1
    pub fn solve_index_id(&self, index: impl ToIndexId) -> PRes<IndexId> {
1201 1
        let (id, _) = self.persy_impl.solve_index_id_tx(self.tx(), index)?;
1202 1
        Ok(id)
1203 1
    }
1204

1205
    #[deprecated = "use Transaction::insert instead"]
1206
    pub fn insert_record(&mut self, segment: impl ToSegmentId, rec: &[u8]) -> PRes<PersyId> {
1207
        self.insert(segment, rec)
1208
    }
1209

1210
    /// Create a new record.
1211
    ///
1212
    /// This function return an id that can be used by [`read`],
1213
    /// the record content can be read only with the [`transaction read`] till the transaction is committed.
1214
    ///
1215
    /// [`read`]:struct.Persy.html#method.read
1216
    /// [`transaction read`]:struct.Transaction.html#method.read
1217
    ///
1218
    /// # Example
1219
    ///
1220
    /// ```rust
1221
    /// # use persy::{Persy,Config,PRes};
1222
    /// # fn foo() -> PRes<()> {
1223
    /// # Persy::create("./open.persy")?;
1224
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1225
    /// let mut tx = persy.begin()?;
1226
    /// # tx.create_segment("seg")?;
1227
    /// let data = vec![1;20];
1228
    /// tx.insert("seg", &data)?;
1229
    /// tx.prepare()?.commit()?;
1230
    /// # Ok(())
1231
    /// # }
1232
    /// ```
1233 1
    pub fn insert(&mut self, segment: impl ToSegmentId, rec: &[u8]) -> PRes<PersyId> {
1234 1
        Ok(PersyId(self.persy_impl.insert_record(
1235 1
            tx_mut(&mut self.tx),
1236 1
            segment,
1237
            rec,
1238 1
        )?))
1239 1
    }
1240

1241
    #[deprecated = "use Transaction::read instead"]
1242
    pub fn read_record(&mut self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
1243
        self.read(segment, id)
1244
    }
1245

1246
    /// Read the record content considering eventual in transaction changes.
1247
    ///
1248
    /// # Example
1249
    ///
1250
    /// ```rust
1251
    /// # use persy::{Persy,Config,PRes};
1252
    /// # fn foo() -> PRes<()> {
1253
    /// # Persy::create("./open.persy")?;
1254
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1255
    /// let mut tx = persy.begin()?;
1256
    /// # tx.create_segment("seg")?;
1257
    /// let data = vec![1;20];
1258
    /// let id = tx.insert("seg", &data)?;
1259
    /// let read = tx.read("seg", &id)?.expect("record exists");
1260
    /// assert_eq!(data,read);
1261
    /// # tx.prepare()?.commit()?;
1262
    /// # Ok(())
1263
    /// # }
1264
    /// ```
1265 1
    pub fn read(&mut self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
1266 1
        let segment_id = self.solve_segment_id(segment)?;
1267 1
        self.persy_impl.read_tx(tx_mut(&mut self.tx), segment_id, &id.0)
1268 1
    }
1269

1270
    /// Scan for persistent and in transaction records
1271
    ///
1272
    /// # Example
1273
    ///
1274
    /// ```rust
1275
    /// # use persy::{Persy,Config,PRes};
1276
    /// # fn foo() -> PRes<()> {
1277
    /// # Persy::create("./open.persy")?;
1278
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1279
    /// let mut tx = persy.begin()?;
1280
    /// # tx.create_segment("seg")?;
1281
    /// let data = vec![1;20];
1282
    /// let id = tx.insert("seg", &data)?;
1283
    /// let mut count = 0;
1284
    /// for (id,content) in tx.scan("seg")? {
1285
    ///     println!("record size:{}",content.len());
1286
    ///     count+=1;
1287
    /// }
1288
    /// assert_eq!(count,1);
1289
    /// # Ok(())
1290
    /// # }
1291
    /// ```
1292 1
    pub fn scan<'a>(&'a mut self, segment: impl ToSegmentId) -> PRes<TxSegmentIter<'a>> {
1293 1
        let segment_id = self.solve_segment_id(segment)?;
1294 1
        Ok(TxSegmentIter::new(
1295 1
            self.persy_impl.scan_tx(&self.tx.as_mut().unwrap(), segment_id)?,
1296
            self,
1297
        ))
1298 1
    }
1299

1300
    #[deprecated = "use Transaction::update instead"]
1301
    pub fn update_record(&mut self, segment: impl ToSegmentId, id: &PersyId, rec: &[u8]) -> PRes<()> {
1302
        self.update(segment, id, rec)
1303
    }
1304

1305
    /// Update the record content.
1306
    ///
1307
    /// This updated content can be read only with the [`transaction read`] till the transaction is committed.
1308
    ///
1309
    /// [`read`]:struct.Transaction.html#method.read
1310
    ///
1311
    /// # Example
1312
    ///
1313
    /// ```rust
1314
    /// # use persy::{Persy,Config,PRes};
1315
    /// # fn foo() -> PRes<()> {
1316
    /// # Persy::create("./open.persy")?;
1317
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1318
    /// let mut tx = persy.begin()?;
1319
    /// # tx.create_segment("seg")?;
1320
    /// let data = vec![1;20];
1321
    /// let id = tx.insert("seg", &data)?;
1322
    /// let new_data = vec![2;20];
1323
    /// tx.update("seg", &id, &new_data)?;
1324
    /// # tx.prepare()?.commit()?;
1325
    /// # Ok(())
1326
    /// # }
1327
    /// ```
1328 1
    pub fn update(&mut self, segment: impl ToSegmentId, id: &PersyId, rec: &[u8]) -> PRes<()> {
1329 1
        let segment_id = self.solve_segment_id(segment)?;
1330 1
        self.persy_impl.update(tx_mut(&mut self.tx), segment_id, &id.0, rec)
1331 1
    }
1332

1333
    #[deprecated = "use Transaction::delete instead"]
1334
    pub fn delete_record(&mut self, segment: impl ToSegmentId, id: &PersyId) -> PRes<()> {
1335
        self.delete(segment, id)
1336
    }
1337

1338
    /// Delete a record.
1339
    ///
1340
    /// The record will result deleted only reading it with [`transaction read`] till the transaction is committed.
1341
    ///
1342
    /// [`transaction read`]:struct.Persy.html#method.read
1343
    ///
1344
    /// # Example
1345
    ///
1346
    /// ```rust
1347
    /// # use persy::{Persy,Config,PRes};
1348
    /// # fn foo() -> PRes<()> {
1349
    /// # Persy::create("./open.persy")?;
1350
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1351
    /// let mut tx = persy.begin()?;
1352
    /// # tx.create_segment("seg")?;
1353
    /// let data = vec![1;20];
1354
    /// let id = tx.insert("seg", &data)?;
1355
    /// tx.delete_record("seg", &id)?;
1356
    /// # tx.prepare()?.commit()?;
1357
    /// # Ok(())
1358
    /// # }
1359
    /// ```
1360 1
    pub fn delete(&mut self, segment: impl ToSegmentId, id: &PersyId) -> PRes<()> {
1361 1
        let segment_id = self.solve_segment_id(segment)?;
1362 1
        self.persy_impl.delete(tx_mut(&mut self.tx), segment_id, &id.0)
1363 1
    }
1364

1365
    /// Create a new index with the name and the value management mode.
1366
    ///
1367
    /// The create operation require two template arguments that are the types as keys and
1368
    /// values of the index this have to match the following operation on the indexes.
1369
    ///
1370
    /// # Example
1371
    ///
1372
    /// ```rust
1373
    /// # use persy::{Persy,Config,PRes,ValueMode};
1374
    /// # fn foo() -> PRes<()> {
1375
    /// # Persy::create("./data.persy")?;
1376
    /// # let persy = Persy::open("./data.persy",Config::new())?;
1377
    /// let mut tx = persy.begin()?;
1378
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1379
    /// # tx.prepare()?.commit()?;
1380
    /// # Ok(())
1381
    /// # }
1382
    /// ```
1383 1
    pub fn create_index<K, V>(&mut self, index_name: &str, value_mode: ValueMode) -> PRes<()>
1384
    where
1385
        K: IndexType,
1386
        V: IndexType,
1387
    {
1388 1
        self.persy_impl
1389 1
            .create_index::<K, V>(tx_mut(&mut self.tx), index_name, value_mode)
1390 1
    }
1391

1392
    /// Drop an existing index.
1393
    ///
1394
    /// # Example
1395
    ///
1396
    /// ```rust
1397
    /// # use persy::{Persy,Config,PRes,ValueMode};
1398
    /// # fn foo() -> PRes<()> {
1399
    /// # Persy::create("./data.persy")?;
1400
    /// # let persy = Persy::open("./data.persy",Config::new())?;
1401
    /// let mut tx = persy.begin()?;
1402
    /// tx.drop_index("my_new_index")?;
1403
    /// # tx.prepare()?.commit()?;
1404
    /// # Ok(())
1405
    /// # }
1406
    /// ```
1407 1
    pub fn drop_index(&mut self, index_name: &str) -> PRes<()> {
1408 1
        self.persy_impl.drop_index(tx_mut(&mut self.tx), index_name)
1409 1
    }
1410

1411
    /// Check if a segment already exist in the storage considering the transaction
1412
    ///
1413
    /// # Example
1414
    ///
1415
    /// ```rust
1416
    /// # use persy::{Persy,Config,PRes,ValueMode};
1417
    /// # fn foo() -> PRes<()> {
1418
    /// # Persy::create("./open.persy")?;
1419
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1420
    /// let mut tx = persy.begin()?;
1421
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::REPLACE)?;
1422
    /// assert!(tx.exists_index("my_new_index")?);
1423
    /// # tx.prepare()?.commit()?;
1424
    /// # Ok(())
1425
    /// # }
1426
    /// ```
1427 1
    pub fn exists_index(&self, segment: &str) -> PRes<bool> {
1428 1
        self.persy_impl.exists_index_tx(self.tx(), segment)
1429 1
    }
1430

1431
    /// Put a key value in an index following the value mode strategy.
1432
    ///
1433
    /// # Example
1434
    ///
1435
    /// ```rust
1436
    /// # use persy::{Persy,Config,PRes,ValueMode};
1437
    /// # fn foo() -> PRes<()> {
1438
    /// # Persy::create("./data.persy")?;
1439
    /// # let persy = Persy::open("./data.persy",Config::new())?;
1440
    /// let mut tx = persy.begin()?;
1441
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1442
    /// tx.put::<u8,u8>("my_new_index",10,10)?;
1443
    /// tx.prepare()?.commit()?;
1444
    /// # Ok(())
1445
    /// # }
1446
    /// ```
1447 1
    pub fn put<K, V>(&mut self, index_name: &str, k: K, v: V) -> PRes<()>
1448
    where
1449
        K: IndexType,
1450
        V: IndexType,
1451
    {
1452 1
        let index_id = self.solve_index_id(index_name)?;
1453 1
        self.persy_impl.put::<K, V>(tx_mut(&mut self.tx), index_id, k, v)
1454 1
    }
1455

1456
    /// Remove a key and optionally a specific value from an index following the value mode strategy.
1457
    ///
1458
    /// # Example
1459
    ///
1460
    /// ```rust
1461
    /// # use persy::{Persy,Config,PRes,ValueMode};
1462
    /// # fn foo() -> PRes<()> {
1463
    /// # Persy::create("./data.persy")?;
1464
    /// # let persy = Persy::open("./data.persy",Config::new())?;
1465
    /// let mut tx = persy.begin()?;
1466
    /// tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1467
    /// tx.put::<u8,u8>("my_new_index",10,10)?;
1468
    /// tx.remove::<u8,u8>("my_new_index",10,Some(10))?;
1469
    /// # tx.prepare()?.commit()?;
1470
    /// # Ok(())
1471
    /// # }
1472
    /// ```
1473 1
    pub fn remove<K, V>(&mut self, index_name: &str, k: K, v: Option<V>) -> PRes<()>
1474
    where
1475
        K: IndexType,
1476
        V: IndexType,
1477
    {
1478 1
        let index_id = self.solve_index_id(index_name)?;
1479 1
        self.persy_impl.remove::<K, V>(tx_mut(&mut self.tx), index_id, k, v)
1480 1
    }
1481

1482
    /// Get a value or a group of values from a key considering changes in transaction.
1483
    ///
1484
    /// # Example
1485
    ///
1486
    /// ```rust
1487
    /// # use persy::{Persy,Config,PRes,ValueMode, Value};
1488
    /// # fn foo() -> PRes<()> {
1489
    /// # Persy::create("./data.persy")?;
1490
    /// # let persy = Persy::open("./data.persy",Config::new())?;
1491
    /// # let mut tx = persy.begin()?;
1492
    /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1493
    /// tx.put::<u8,u8>("my_new_index",10,10)?;
1494
    /// let val = tx.get::<u8,u8>("my_new_index",&10)?;
1495
    /// if let Some(is_there) = val {
1496
    ///     // A value is actually there
1497
    ///     match is_there {
1498
    ///         Value::SINGLE(actual_value) => {
1499
    ///         },
1500
    ///         Value::CLUSTER(actual_value) => {
1501
    ///         },
1502
    ///     }
1503
    /// }
1504
    /// # tx.prepare()?.commit()?;
1505
    /// # Ok(())
1506
    /// # }
1507
    /// ```
1508 1
    pub fn get<K, V>(&mut self, index_name: &str, k: &K) -> PRes<Option<Value<V>>>
1509
    where
1510
        K: IndexType,
1511
        V: IndexType,
1512
    {
1513 1
        let index_id = self.solve_index_id(index_name)?;
1514 1
        self.persy_impl.get_tx::<K, V>(tx_mut(&mut self.tx), index_id, k)
1515 1
    }
1516

1517
    /// Browse a range of keys and values from an index including the transaction changes
1518
    ///
1519
    /// # Example
1520
    ///
1521
    /// ```rust
1522
    /// # use persy::{Persy,Config,PRes,ValueMode, Value,TxIndexIter};
1523
    /// # fn foo() -> PRes<()> {
1524
    /// # Persy::create("./data.persy")?;
1525
    /// let persy = Persy::open("./data.persy",Config::new())?;
1526
    /// let mut tx = persy.begin()?;
1527
    /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1528
    /// tx.put::<u8,u8>("my_new_index",10,10)?;
1529
    /// {
1530
    ///     let iter:TxIndexIter<u8,u8> = tx.range("my_new_index",10..12)?;
1531
    ///     for (k,val) in iter  {
1532
    ///         // A value is actually there
1533
    ///         match val {
1534
    ///             Value::SINGLE(actual_value) => {
1535
    ///             },
1536
    ///             Value::CLUSTER(actual_value) => {
1537
    ///             },
1538
    ///         }
1539
    ///     }
1540
    /// }
1541
    /// tx.prepare()?.commit()?;
1542
    /// # Ok(())
1543
    /// # }
1544
    /// ```
1545 1
    pub fn range<'a, K, V, R>(&'a mut self, index_name: &str, range: R) -> PRes<TxIndexIter<'a, K, V>>
1546
    where
1547
        K: IndexType,
1548
        V: IndexType,
1549
        R: RangeBounds<K>,
1550
    {
1551 1
        let index_id = self.solve_index_id(index_name)?;
1552 1
        let (vm, raw) = self
1553
            .persy_impl
1554 1
            .range(index_id.clone(), (range.start_bound(), range.end_bound()))?;
1555 1
        let tx_iter = self.tx_mut().index_range::<K, V, R>(index_id.clone(), range);
1556 1
        let tx_raw = TxIndexRawIter::new(index_id, tx_iter, Some(raw), vm);
1557 1
        Ok(TxIndexIter::new(tx_raw, self))
1558 1
    }
1559

1560
    /// Rollback a not yet prepared transaction.
1561
    ///
1562
    /// All the resources used for eventual insert or update are released.
1563
    ///
1564
    /// # Example
1565
    ///
1566
    /// ```rust
1567
    /// # use persy::{Persy,Config,PRes};
1568
    /// # fn foo() -> PRes<()> {
1569
    /// # Persy::create("./open.persy")?;
1570
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1571
    /// let mut tx = persy.begin()?;
1572
    /// # tx.create_segment("seg")?;
1573
    /// let data = vec![1;20];
1574
    /// tx.insert("seg", &data)?;
1575
    /// tx.rollback()?;
1576
    /// # Ok(())
1577
    /// # }
1578
    /// ```
1579 1
    pub fn rollback(mut self) -> PRes<()> {
1580 1
        if let Some(real_tx) = replace(&mut self.tx, None) {
1581 1
            self.persy_impl.rollback(real_tx)?;
1582 1
        }
1583 1
        Ok(())
1584 1
    }
1585

1586
    #[deprecated = "replaced by Transaction::prepare"]
1587
    pub fn prepare_commit(self) -> PRes<TransactionFinalize> {
1588
        self.prepare()
1589
    }
1590

1591
    /// Prepare to commit a transaction, when this method return all the validation checks
1592
    /// are done and is guaranteed that the transaction can be committed successfully
1593
    ///
1594
    /// it will lock all the records involved in the transaction
1595
    /// till a [`commit`] or [`rollback`] is called.
1596
    ///
1597
    /// [`commit`]:struct.TransactionFinalize.html#method.commit
1598
    /// [`rollback`]:struct.TransactionFinalize.html#method.rollback
1599
    ///
1600
    /// # Example
1601
    ///
1602
    /// ```rust
1603
    /// # use persy::{Persy,Config,PRes};
1604
    /// # fn foo() -> PRes<()> {
1605
    /// # Persy::create("./open.persy")?;
1606
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1607
    /// let mut tx = persy.begin()?;
1608
    /// # tx.create_segment("seg")?;
1609
    /// //Do what ever operations on the records
1610
    /// let data = vec![1;20];
1611
    /// tx.insert("seg", &data)?;
1612
    /// tx.prepare()?;
1613
    /// # Ok(())
1614
    /// # }
1615
    /// ```
1616 1
    pub fn prepare(mut self) -> PRes<TransactionFinalize> {
1617 1
        let real_tx = replace(&mut self.tx, None).unwrap();
1618 1
        Ok(TransactionFinalize {
1619 1
            persy_impl: self.persy_impl.clone(),
1620 1
            finalize: Some(self.persy_impl.prepare(real_tx)?),
1621 1
        })
1622 1
    }
1623

1624
    /// List all the existing segments, considering all the changes in transaction.
1625
    ///
1626
    /// # Example
1627
    ///
1628
    /// ```rust
1629
    /// # use persy::{Persy,Config,PRes};
1630
    /// # fn foo() -> PRes<()> {
1631
    /// # Persy::create("./open.persy")?;
1632
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1633
    /// let mut tx = persy.begin()?;
1634
    /// tx.create_segment("seg")?;
1635
    /// let segments = tx.list_segments()?;
1636
    /// let names = segments.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
1637
    /// assert!(names.contains(&"seg".to_string()));
1638
    /// tx.prepare()?.commit()?;
1639
    /// # Ok(())
1640
    /// # }
1641
    /// ```
1642 1
    pub fn list_segments(&self) -> PRes<Vec<(String, SegmentId)>> {
1643 1
        Ok(self
1644
            .persy_impl
1645 1
            .list_segments_tx(self.tx())?
1646
            .into_iter()
1647 1
            .map(|(name, id)| (name, SegmentId::new(id)))
1648
            .collect())
1649 1
    }
1650

1651
    /// List all the existing indexes, considering changes in the transaction.
1652
    ///
1653
    /// # Example
1654
    ///
1655
    /// ```rust
1656
    /// # use persy::{Persy,Config,PRes,ValueMode};
1657
    /// # fn foo() -> PRes<()> {
1658
    /// # Persy::create("./open.persy")?;
1659
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1660
    /// let mut tx = persy.begin()?;
1661
    /// tx.create_index::<u8, u8>("idx", ValueMode::REPLACE)?;
1662
    /// let indexes = tx.list_indexes()?;
1663
    /// let names = indexes.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
1664
    /// assert!(names.contains(&"idx".to_string()));
1665
    /// tx.prepare()?.commit()?;
1666
    /// # Ok(())
1667
    /// # }
1668
    /// ```
1669 1
    pub fn list_indexes(&self) -> PRes<Vec<(String, IndexInfo)>> {
1670 1
        Ok(self.persy_impl.list_indexes_tx(self.tx())?)
1671 1
    }
1672
}
1673

1674
impl Drop for Transaction {
1675 1
    fn drop(&mut self) {
1676 1
        if let Some(tx) = replace(&mut self.tx, None) {
1677 1
            self.persy_impl.rollback(tx).unwrap();
1678 1
        }
1679 1
    }
1680
}
1681

1682
/// Iterator implementation to scan a segment considering in transaction changes.
1683
pub struct SnapshotSegmentIter {
1684
    iter_impl: SegmentSnapshotRawIter,
1685
    persy_impl: Arc<PersyImpl>,
1686
}
1687

1688
impl<'a> SnapshotSegmentIter {
1689 1
    fn new(iter_impl: SegmentSnapshotRawIter, persy_impl: Arc<PersyImpl>) -> SnapshotSegmentIter {
1690 1
        SnapshotSegmentIter { iter_impl, persy_impl }
1691 1
    }
1692
}
1693

1694
impl<'a> Iterator for SnapshotSegmentIter {
1695
    type Item = (PersyId, Vec<u8>);
1696

1697 1
    fn next(&mut self) -> Option<Self::Item> {
1698 1
        self.iter_impl.next(&self.persy_impl)
1699 1
    }
1700
}
1701

1702
/// Read snapshot at a specific point in time.
1703
///
1704
/// All the changes from transactions committed at the specific point in time were the snapshot was
1705
/// create are readable from this snapshot, all subsequent transactions are ignored.
1706
///
1707
/// Copy of the data old data is kept on the disc, with indexing access from in memory structures,
1708
/// on drop of the Snapshot, if there are no older snapshot all the data old by this snapshot not
1709
/// existing anymore in the final state will be cleaned up.
1710
///
1711
#[derive(Clone)]
1712
pub struct Snapshot {
1713
    snap: Arc<SnapshotInt>,
1714
}
1715
struct SnapshotInt {
1716
    persy_impl: Arc<PersyImpl>,
1717
    snapshot_id: SnapshotId,
1718
}
1719

1720
impl Snapshot {
1721 1
    pub(crate) fn new(persy_impl: Arc<PersyImpl>, snapshot_id: SnapshotId) -> Snapshot {
1722 1
        Snapshot {
1723 1
            snap: Arc::new(SnapshotInt {
1724
                persy_impl,
1725
                snapshot_id,
1726
            }),
1727
        }
1728 1
    }
1729

1730 1
    fn solve_segment_id(&self, segment: impl ToSegmentId) -> PRes<SegmentId> {
1731 1
        self.snap
1732
            .persy_impl
1733 1
            .solve_segment_id_snapshot(self.snap.snapshot_id, segment)
1734 1
    }
1735 1
    fn solve_index_id(&self, index: impl ToIndexId) -> PRes<IndexId> {
1736 1
        self.snap
1737
            .persy_impl
1738 1
            .solve_index_id_snapshot(self.snap.snapshot_id, index)
1739 1
    }
1740

1741
    #[deprecated = "replaced by Snapshot::read"]
1742
    pub fn read_record(&self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
1743
        self.read(segment, id)
1744
    }
1745

1746
    /// Read the record content at the point of time the snapshot was taken ignoring all following
1747
    /// committed transactions
1748
    ///
1749
    /// # Example
1750
    ///
1751
    /// ```rust
1752
    /// # use persy::{Persy,Config,PRes};
1753
    /// # fn foo() -> PRes<()> {
1754
    /// # Persy::create("./open.persy")?;
1755
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1756
    /// let mut tx = persy.begin()?;
1757
    /// # tx.create_segment("seg")?;
1758
    /// let data = vec![1;20];
1759
    /// let id = tx.insert("seg", &data)?;
1760
    /// tx.prepare()?.commit()?;
1761
    /// let snapshot = persy.snapshot()?;
1762
    /// let read = snapshot.read("seg", &id)?.expect("record exists");
1763
    /// assert_eq!(data,read);
1764
    /// # Ok(())
1765
    /// # }
1766
    /// ```
1767 1
    pub fn read(&self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
1768 1
        let segment_id = self.solve_segment_id(segment)?;
1769 1
        self.snap.persy_impl.read_snap(segment_id, &id.0, self.snap.snapshot_id)
1770 1
    }
1771

1772
    /// Scan for records existing at the moment of snapshot creation, ignoring all
1773
    /// the following committed transactions.
1774
    ///
1775
    /// # Example
1776
    ///
1777
    /// ```rust
1778
    /// # use persy::{Persy,Config,PRes};
1779
    /// # fn foo() -> PRes<()> {
1780
    /// # Persy::create("./open.persy")?;
1781
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1782
    /// let mut tx = persy.begin()?;
1783
    /// # tx.create_segment("seg")?;
1784
    /// let data = vec![1;20];
1785
    /// let id = tx.insert("seg", &data)?;
1786
    /// tx.prepare()?.commit()?;
1787
    /// let snapshot = persy.snapshot()?;
1788
    /// let mut count = 0;
1789
    /// for (id,content) in snapshot.scan("seg")? {
1790
    ///     println!("record size:{}",content.len());
1791
    ///     count+=1;
1792
    /// }
1793
    /// assert_eq!(count,1);
1794
    /// # Ok(())
1795
    /// # }
1796
    /// ```
1797 1
    pub fn scan(&self, segment: impl ToSegmentId) -> PRes<SnapshotSegmentIter> {
1798 1
        let segment_id = self.solve_segment_id(segment)?;
1799 1
        Ok(SnapshotSegmentIter::new(
1800 1
            self.snap.persy_impl.scan_snapshot(segment_id, self.snap.snapshot_id)?,
1801 1
            self.snap.persy_impl.clone(),
1802 1
        ))
1803 1
    }
1804

1805
    /// Get a value or a group of values from a key at the point the snapshot was taken ignoring
1806
    /// all following committed transactions.
1807
    ///
1808
    /// # Example
1809
    ///
1810
    /// ```rust
1811
    /// # use persy::{Persy,Config,PRes,ValueMode, Value};
1812
    /// # fn foo() -> PRes<()> {
1813
    /// # Persy::create("./data.persy")?;
1814
    /// # let persy = Persy::open("./data.persy",Config::new())?;
1815
    /// # let mut tx = persy.begin()?;
1816
    /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1817
    /// tx.put::<u8,u8>("my_new_index",10,10)?;
1818
    /// tx.prepare()?.commit()?;
1819
    /// let snapshot = persy.snapshot()?;
1820
    /// let val = snapshot.get::<u8,u8>("my_new_index",&10)?;
1821
    /// if let Some(is_there) = val {
1822
    ///     // A value is actually there
1823
    ///     match is_there {
1824
    ///         Value::SINGLE(actual_value) => {
1825
    ///         },
1826
    ///         Value::CLUSTER(actual_value) => {
1827
    ///         },
1828
    ///     }
1829
    /// }
1830
    /// # Ok(())
1831
    /// # }
1832
    /// ```
1833 1
    pub fn get<K, V>(&self, index_name: &str, k: &K) -> PRes<Option<Value<V>>>
1834
    where
1835
        K: IndexType,
1836
        V: IndexType,
1837
    {
1838 1
        let index_id = self.solve_index_id(index_name)?;
1839 1
        self.snap
1840
            .persy_impl
1841 1
            .get_snapshot::<K, V>(index_id, self.snap.snapshot_id, k)
1842 1
    }
1843

1844
    /// Browse a range of keys and values from an index at the pointing that the snapshot was created ignoring all
1845
    /// the following committed transactions.
1846
    ///
1847
    /// # Example
1848
    ///
1849
    /// ```rust
1850
    /// # use persy::{Persy,Config,PRes,ValueMode, Value, IndexIter};
1851
    /// # fn foo() -> PRes<()> {
1852
    /// # Persy::create("./data.persy")?;
1853
    /// let persy = Persy::open("./data.persy",Config::new())?;
1854
    /// let mut tx = persy.begin()?;
1855
    /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::CLUSTER)?;
1856
    /// tx.put::<u8,u8>("my_new_index",10,10)?;
1857
    /// tx.prepare()?.commit()?;
1858
    /// let snapshot = persy.snapshot()?;
1859
    /// let iter:IndexIter<u8,u8> = snapshot.range("my_new_index",10..12)?;
1860
    /// for (k,val) in iter  {
1861
    ///     // A value is actually there
1862
    ///     match val {
1863
    ///         Value::SINGLE(actual_value) => {
1864
    ///         },
1865
    ///         Value::CLUSTER(actual_value) => {
1866
    ///         },
1867
    ///     }
1868
    /// }
1869
    /// # Ok(())
1870
    /// # }
1871
    /// ```
1872 1
    pub fn range<K, V, R>(&self, index_name: &str, range: R) -> PRes<IndexIter<K, V>>
1873
    where
1874
        K: IndexType,
1875
        V: IndexType,
1876
        R: RangeBounds<K>,
1877
    {
1878 1
        let index_id = self.solve_index_id(index_name)?;
1879 1
        let (_, raw) = self
1880
            .snap
1881
            .persy_impl
1882 1
            .range_snapshot(index_id, self.snap.snapshot_id, range, false)?;
1883 1
        Ok(IndexIter::new(raw, self.snap.persy_impl.clone()))
1884 1
    }
1885

1886
    /// List all the existing segments, at the pointing that the snapshot was created ignoring all
1887
    /// the following committed transactions.
1888
    ///
1889
    /// # Example
1890
    ///
1891
    /// ```rust
1892
    /// # use persy::{Persy,Config,PRes};
1893
    /// # fn foo() -> PRes<()> {
1894
    /// # Persy::create("./open.persy")?;
1895
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1896
    /// let mut tx = persy.begin()?;
1897
    /// tx.create_segment("seg")?;
1898
    /// tx.prepare()?.commit()?;
1899
    /// let snapshot = persy.snapshot()?;
1900
    /// let segments = snapshot.list_segments()?;
1901
    /// let names = segments.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
1902
    /// assert!(names.contains(&"seg".to_string()));
1903
    /// # Ok(())
1904
    /// # }
1905
    /// ```
1906 1
    pub fn list_segments(&self) -> PRes<Vec<(String, SegmentId)>> {
1907 1
        Ok(self.snap.persy_impl.list_segments_snapshot(self.snap.snapshot_id)?)
1908 1
    }
1909

1910
    /// List all the existing indexes, at the pointing that the snapshot was created ignoring all
1911
    /// the following committed transactions.
1912
    ///
1913
    /// # Example
1914
    ///
1915
    /// ```rust
1916
    /// # use persy::{Persy,Config,PRes,ValueMode};
1917
    /// # fn foo() -> PRes<()> {
1918
    /// # Persy::create("./open.persy")?;
1919
    /// # let persy = Persy::open("./open.persy",Config::new())?;
1920
    /// let mut tx = persy.begin()?;
1921
    /// tx.create_index::<u8, u8>("idx", ValueMode::REPLACE)?;
1922
    /// tx.prepare()?.commit()?;
1923
    /// let snapshot = persy.snapshot()?;
1924
    /// let indexes = snapshot.list_indexes()?;
1925
    /// let names = indexes.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
1926
    /// assert!(names.contains(&"idx".to_string()));
1927
    /// # Ok(())
1928
    /// # }
1929
    /// ```
1930 1
    pub fn list_indexes(&self) -> PRes<Vec<(String, IndexInfo)>> {
1931 1
        Ok(self.snap.persy_impl.list_indexes_snapshot(self.snap.snapshot_id)?)
1932 1
    }
1933
}
1934

1935
impl Drop for SnapshotInt {
1936 1
    fn drop(&mut self) {
1937 1
        self.persy_impl.release_snapshot(self.snapshot_id).unwrap();
1938 1
    }
1939
}
1940

1941
#[cfg(test)]
1942
mod tests {
1943
    use super::{Config, Persy, TransactionConfig};
1944
    use std::fs;
1945
    #[test]
1946 1
    pub fn test_recover_prepared_tx() {
1947 1
        Persy::create("./target/test_recover_prepared.persy").unwrap();
1948
        let id;
1949
        let val;
1950
        {
1951 1
            let persy = Persy::open("./target/test_recover_prepared.persy", Config::new()).unwrap();
1952 1
            let mut tx = persy.begin().expect("error on transactoin begin");
1953 1
            tx.create_segment("def").expect("error on segment creation");
1954 1
            let fin = tx.prepare().expect("error on commit prepare");
1955 1
            fin.commit().expect("error on commit");
1956

1957 1
            let mut tx = persy.begin().expect("error on transaction begin");
1958 1
            val = String::from("aaa").into_bytes();
1959 1
            id = tx.insert("def", &val).expect("error on insert value");
1960 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
1961 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
1962 1
        }
1963
        {
1964 1
            let persy = Persy::open("./target/test_recover_prepared.persy", Config::new()).unwrap();
1965 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val));
1966 1
        }
1967

1968 1
        fs::remove_file("./target/test_recover_prepared.persy").unwrap();
1969 1
    }
1970

1971
    #[test]
1972 1
    pub fn test_dobule_recover_prepared_tx() {
1973 1
        Persy::create("./target/test_double_recover_prepared.persy").unwrap();
1974
        let id;
1975
        let id1;
1976
        let val;
1977
        let val1;
1978
        {
1979 1
            let persy = Persy::open("./target/test_double_recover_prepared.persy", Config::new()).unwrap();
1980 1
            let mut tx = persy.begin().expect("error on transactoin begin");
1981 1
            tx.create_segment("def").expect("error on segment creation");
1982 1
            let fin = tx.prepare().expect("error on commit prepare");
1983 1
            fin.commit().expect("error on commit");
1984

1985 1
            let mut tx = persy.begin().expect("error on transaction begin");
1986 1
            val = String::from("aaa").into_bytes();
1987 1
            id = tx.insert("def", &val).expect("error on insert value");
1988 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
1989 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
1990 1
        }
1991
        {
1992 1
            let persy = Persy::open("./target/test_double_recover_prepared.persy", Config::new()).unwrap();
1993 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val.clone()));
1994 1
            let mut tx = persy.begin().expect("error on transaction begin");
1995 1
            val1 = String::from("bbbb").into_bytes();
1996 1
            id1 = tx.insert("def", &val1).expect("error on insert value");
1997 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
1998 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
1999 1
        }
2000

2001
        {
2002 1
            let persy = Persy::open("./target/test_double_recover_prepared.persy", Config::new()).unwrap();
2003 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val));
2004 1
            assert_eq!(persy.read("def", &id1).expect("error reading record",), Some(val1));
2005 1
        }
2006 1
        fs::remove_file("./target/test_double_recover_prepared.persy").unwrap();
2007 1
    }
2008

2009
    #[test]
2010 1
    pub fn test_recover_tx_id() {
2011 1
        Persy::create("./target/test_recover_tx_id.persy").unwrap();
2012
        let id;
2013
        let id_pers;
2014
        let id_pers_update;
2015
        let val;
2016
        let val_1;
2017 1
        let tx_id = vec![10; 5];
2018
        {
2019 1
            val = String::from("aaa").into_bytes();
2020 1
            let persy = Persy::open("./target/test_recover_tx_id.persy", Config::new()).unwrap();
2021 1
            let mut tx = persy.begin().expect("error on transactoin begin");
2022 1
            tx.create_segment("def").expect("error on segment creation");
2023 1
            id_pers = tx.insert("def", &val).expect("error on insert value");
2024 1
            id_pers_update = tx.insert("def", &val).expect("error on insert value");
2025 1
            let fin = tx.prepare().expect("error on commit prepare");
2026 1
            fin.commit().expect("error on commit");
2027

2028 1
            let mut tx = persy
2029 1
                .begin_with(TransactionConfig::new().set_transaction_id(tx_id.clone()))
2030 1
                .expect("error on transaction begin");
2031 1
            id = tx.insert("def", &val).expect("error on insert value");
2032 1
            tx.delete("def", &id_pers).expect("delete record works");
2033 1
            val_1 = String::from("bbb").into_bytes();
2034 1
            tx.update("def", &id_pers_update, &val_1).expect("delete record works");
2035 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
2036 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
2037 1
        }
2038
        {
2039 1
            let persy = Persy::open_with_recover("./target/test_recover_tx_id.persy", Config::new(), |t_id| {
2040 1
                assert_eq!(&tx_id, t_id);
2041
                true
2042 1
            })
2043
            .unwrap();
2044 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val));
2045 1
            assert_eq!(persy.read("def", &id_pers).expect("error reading record"), None);
2046 1
            assert_eq!(
2047 1
                persy.read("def", &id_pers_update).expect("error reading record"),
2048 1
                Some(val_1)
2049
            );
2050 1
        }
2051

2052 1
        fs::remove_file("./target/test_recover_tx_id.persy").unwrap();
2053 1
    }
2054

2055
    #[test]
2056 1
    pub fn test_recover_tx_choice() {
2057 1
        Persy::create("./target/test_recover_tx_choice.persy").unwrap();
2058
        let id;
2059
        let id_1;
2060
        let id_pers;
2061
        let id_pers_update;
2062
        let val;
2063
        let val_1;
2064 1
        let tx_id = vec![10; 5];
2065 1
        let tx_id_1 = vec![10; 10];
2066 1
        {
2067 1
            val = String::from("aaa").into_bytes();
2068 1
            let persy = Persy::open("./target/test_recover_tx_choice.persy", Config::new()).unwrap();
2069 1
            let mut tx = persy.begin().expect("error on transactoin begin");
2070 1
            tx.create_segment("def").expect("error on segment creation");
2071 1
            id_pers = tx.insert("def", &val).expect("error on insert value");
2072 1
            id_pers_update = tx.insert("def", &val).expect("error on insert value");
2073 1
            let fin = tx.prepare().expect("error on commit prepare");
2074 1
            fin.commit().expect("error on commit");
2075

2076 1
            let mut tx = persy
2077 1
                .begin_with(TransactionConfig::new().set_transaction_id(tx_id.clone()))
2078 1
                .expect("error on transaction begin");
2079 1
            id = tx.insert("def", &val).expect("error on insert value");
2080 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
2081 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
2082

2083 1
            let mut tx = persy
2084 1
                .begin_with(TransactionConfig::new().set_transaction_id(tx_id_1.clone()))
2085 1
                .expect("error on transaction begin");
2086 1
            id_1 = tx.insert("def", &val).expect("error on insert value");
2087 1
            tx.delete("def", &id_pers).expect("delete record works");
2088 1
            val_1 = String::from("bbb").into_bytes();
2089 1
            tx.update("def", &id_pers_update, &val_1).expect("delete record works");
2090 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
2091 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
2092 1
        }
2093
        {
2094 1
            let mut recover = Persy::recover("./target/test_recover_tx_choice.persy", Config::new()).unwrap();
2095

2096 1
            assert!(recover.list_transactions().expect("list successfully").len() >= 2);
2097 1
            recover.rollback(tx_id_1).expect("marked rollback correctly");
2098 1
            recover.commit(tx_id).expect("marked commit correctly");
2099 1
            let persy = recover.finalize().expect("recover correctly");
2100

2101 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val.clone()));
2102 1
            assert_eq!(persy.read("def", &id_1).expect("error reading record"), None);
2103 1
            assert_eq!(
2104 1
                persy.read("def", &id_pers).expect("error reading record"),
2105 1
                Some(val.clone())
2106
            );
2107 1
            assert_eq!(
2108 1
                persy.read("def", &id_pers_update).expect("error reading record"),
2109 1
                Some(val)
2110
            );
2111 1
        }
2112

2113 1
        fs::remove_file("./target/test_recover_tx_choice.persy").unwrap();
2114 1
    }
2115
}

Read our documentation on viewing source code .

Loading