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::tree::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
        ))
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.persy_impl.list_segments()?)
1045 1
    }
1046

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

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

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

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

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

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

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

1200
    #[deprecated = "use Transaction::insert instead"]
1201
    pub fn insert_record(&mut self, segment: impl ToSegmentId, rec: &[u8]) -> PRes<PersyId> {
1202
        self.insert(segment, rec)
1203
    }
1204

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

1236
    #[deprecated = "use Transaction::read instead"]
1237
    pub fn read_record(&mut self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
1238
        self.read(segment, id)
1239
    }
1240

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

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

1295
    #[deprecated = "use Transaction::update instead"]
1296
    pub fn update_record(&mut self, segment: impl ToSegmentId, id: &PersyId, rec: &[u8]) -> PRes<()> {
1297
        self.update(segment, id, rec)
1298
    }
1299

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

1328
    #[deprecated = "use Transaction::delete instead"]
1329
    pub fn delete_record(&mut self, segment: impl ToSegmentId, id: &PersyId) -> PRes<()> {
1330
        self.delete(segment, id)
1331
    }
1332

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

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

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

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

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

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

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

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

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

1581
    #[deprecated = "replaced by Transaction::prepare"]
1582
    pub fn prepare_commit(self) -> PRes<TransactionFinalize> {
1583
        self.prepare()
1584
    }
1585

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

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

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

1664
impl Drop for Transaction {
1665 1
    fn drop(&mut self) {
1666 1
        if let Some(tx) = replace(&mut self.tx, None) {
1667 1
            self.persy_impl.rollback(tx).unwrap();
1668 1
        }
1669 1
    }
1670
}
1671

1672
/// Iterator implementation to scan a segment considering in transaction changes.
1673
pub struct SnapshotSegmentIter {
1674
    iter_impl: SegmentSnapshotRawIter,
1675
    persy_impl: Arc<PersyImpl>,
1676
}
1677

1678
impl<'a> SnapshotSegmentIter {
1679 1
    fn new(iter_impl: SegmentSnapshotRawIter, persy_impl: Arc<PersyImpl>) -> SnapshotSegmentIter {
1680 1
        SnapshotSegmentIter { iter_impl, persy_impl }
1681 1
    }
1682
}
1683

1684
impl<'a> Iterator for SnapshotSegmentIter {
1685
    type Item = (PersyId, Vec<u8>);
1686

1687 1
    fn next(&mut self) -> Option<Self::Item> {
1688 1
        self.iter_impl.next(&self.persy_impl)
1689 1
    }
1690
}
1691

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

1710
impl Snapshot {
1711 1
    pub(crate) fn new(persy_impl: Arc<PersyImpl>, snapshot_id: SnapshotId) -> Snapshot {
1712 1
        Snapshot {
1713 1
            snap: Arc::new(SnapshotInt {
1714
                persy_impl,
1715
                snapshot_id,
1716
            }),
1717
        }
1718 1
    }
1719

1720 1
    fn solve_segment_id(&self, segment: impl ToSegmentId) -> PRes<SegmentId> {
1721 1
        self.snap
1722
            .persy_impl
1723 1
            .solve_segment_id_snapshot(self.snap.snapshot_id, segment)
1724 1
    }
1725 1
    fn solve_index_id(&self, index: impl ToIndexId) -> PRes<IndexId> {
1726 1
        self.snap
1727
            .persy_impl
1728 1
            .solve_index_id_snapshot(self.snap.snapshot_id, index)
1729 1
    }
1730

1731
    #[deprecated = "replaced by Snapshot::read"]
1732
    pub fn read_record(&self, segment: impl ToSegmentId, id: &PersyId) -> PRes<Option<Vec<u8>>> {
1733
        self.read(segment, id)
1734
    }
1735

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

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

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

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

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

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

1925
impl Drop for SnapshotInt {
1926 1
    fn drop(&mut self) {
1927 1
        self.persy_impl.release_snapshot(self.snapshot_id).unwrap();
1928 1
    }
1929
}
1930

1931
#[cfg(test)]
1932
mod tests {
1933
    use super::{Config, Persy, TransactionConfig};
1934
    use std::fs;
1935
    #[test]
1936 1
    pub fn test_recover_prepared_tx() {
1937 1
        Persy::create("./target/test_recover_prepared.persy").unwrap();
1938
        let id;
1939
        let val;
1940
        {
1941 1
            let persy = Persy::open("./target/test_recover_prepared.persy", Config::new()).unwrap();
1942 1
            let mut tx = persy.begin().expect("error on transactoin begin");
1943 1
            tx.create_segment("def").expect("error on segment creation");
1944 1
            let fin = tx.prepare().expect("error on commit prepare");
1945 1
            fin.commit().expect("error on commit");
1946

1947 1
            let mut tx = persy.begin().expect("error on transaction begin");
1948 1
            val = String::from("aaa").into_bytes();
1949 1
            id = tx.insert("def", &val).expect("error on insert value");
1950 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
1951 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
1952 1
        }
1953
        {
1954 1
            let persy = Persy::open("./target/test_recover_prepared.persy", Config::new()).unwrap();
1955 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val));
1956 1
        }
1957

1958 1
        fs::remove_file("./target/test_recover_prepared.persy").unwrap();
1959 1
    }
1960

1961
    #[test]
1962 1
    pub fn test_dobule_recover_prepared_tx() {
1963 1
        Persy::create("./target/test_double_recover_prepared.persy").unwrap();
1964
        let id;
1965
        let id1;
1966
        let val;
1967
        let val1;
1968
        {
1969 1
            let persy = Persy::open("./target/test_double_recover_prepared.persy", Config::new()).unwrap();
1970 1
            let mut tx = persy.begin().expect("error on transactoin begin");
1971 1
            tx.create_segment("def").expect("error on segment creation");
1972 1
            let fin = tx.prepare().expect("error on commit prepare");
1973 1
            fin.commit().expect("error on commit");
1974

1975 1
            let mut tx = persy.begin().expect("error on transaction begin");
1976 1
            val = String::from("aaa").into_bytes();
1977 1
            id = tx.insert("def", &val).expect("error on insert value");
1978 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
1979 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
1980 1
        }
1981
        {
1982 1
            let persy = Persy::open("./target/test_double_recover_prepared.persy", Config::new()).unwrap();
1983 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val.clone()));
1984 1
            let mut tx = persy.begin().expect("error on transaction begin");
1985 1
            val1 = String::from("bbbb").into_bytes();
1986 1
            id1 = tx.insert("def", &val1).expect("error on insert value");
1987 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
1988 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
1989 1
        }
1990

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));
1994 1
            assert_eq!(persy.read("def", &id1).expect("error reading record",), Some(val1));
1995 1
        }
1996 1
        fs::remove_file("./target/test_double_recover_prepared.persy").unwrap();
1997 1
    }
1998

1999
    #[test]
2000 1
    pub fn test_recover_tx_id() {
2001 1
        Persy::create("./target/test_recover_tx_id.persy").unwrap();
2002
        let id;
2003
        let id_pers;
2004
        let id_pers_update;
2005
        let val;
2006
        let val_1;
2007 1
        let tx_id = vec![10; 5];
2008
        {
2009 1
            val = String::from("aaa").into_bytes();
2010 1
            let persy = Persy::open("./target/test_recover_tx_id.persy", Config::new()).unwrap();
2011 1
            let mut tx = persy.begin().expect("error on transactoin begin");
2012 1
            tx.create_segment("def").expect("error on segment creation");
2013 1
            id_pers = tx.insert("def", &val).expect("error on insert value");
2014 1
            id_pers_update = tx.insert("def", &val).expect("error on insert value");
2015 1
            let fin = tx.prepare().expect("error on commit prepare");
2016 1
            fin.commit().expect("error on commit");
2017

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

2042 1
        fs::remove_file("./target/test_recover_tx_id.persy").unwrap();
2043 1
    }
2044

2045
    #[test]
2046 1
    pub fn test_recover_tx_choice() {
2047 1
        Persy::create("./target/test_recover_tx_choice.persy").unwrap();
2048
        let id;
2049
        let id_1;
2050
        let id_pers;
2051
        let id_pers_update;
2052
        let val;
2053
        let val_1;
2054 1
        let tx_id = vec![10; 5];
2055 1
        let tx_id_1 = vec![10; 10];
2056 1
        {
2057 1
            val = String::from("aaa").into_bytes();
2058 1
            let persy = Persy::open("./target/test_recover_tx_choice.persy", Config::new()).unwrap();
2059 1
            let mut tx = persy.begin().expect("error on transactoin begin");
2060 1
            tx.create_segment("def").expect("error on segment creation");
2061 1
            id_pers = tx.insert("def", &val).expect("error on insert value");
2062 1
            id_pers_update = tx.insert("def", &val).expect("error on insert value");
2063 1
            let fin = tx.prepare().expect("error on commit prepare");
2064 1
            fin.commit().expect("error on commit");
2065

2066 1
            let mut tx = persy
2067 1
                .begin_with(TransactionConfig::new().set_transaction_id(tx_id.clone()))
2068 1
                .expect("error on transaction begin");
2069 1
            id = tx.insert("def", &val).expect("error on insert value");
2070 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
2071 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
2072

2073 1
            let mut tx = persy
2074 1
                .begin_with(TransactionConfig::new().set_transaction_id(tx_id_1.clone()))
2075 1
                .expect("error on transaction begin");
2076 1
            id_1 = tx.insert("def", &val).expect("error on insert value");
2077 1
            tx.delete("def", &id_pers).expect("delete record works");
2078 1
            val_1 = String::from("bbb").into_bytes();
2079 1
            tx.update("def", &id_pers_update, &val_1).expect("delete record works");
2080 1
            let mut prepared = tx.prepare().expect("error on commit prepare");
2081 1
            let _replaced = std::mem::replace(&mut prepared.finalize, None);
2082 1
        }
2083
        {
2084 1
            let mut recover = Persy::recover("./target/test_recover_tx_choice.persy", Config::new()).unwrap();
2085

2086 1
            assert!(recover.list_transactions().expect("list successfully").len() >= 2);
2087 1
            recover.rollback(tx_id_1).expect("marked rollback correctly");
2088 1
            recover.commit(tx_id).expect("marked commit correctly");
2089 1
            let persy = recover.finalize().expect("recover correctly");
2090

2091 1
            assert_eq!(persy.read("def", &id).expect("error reading record"), Some(val.clone()));
2092 1
            assert_eq!(persy.read("def", &id_1).expect("error reading record"), None);
2093 1
            assert_eq!(
2094 1
                persy.read("def", &id_pers).expect("error reading record"),
2095 1
                Some(val.clone())
2096
            );
2097 1
            assert_eq!(
2098 1
                persy.read("def", &id_pers_update).expect("error reading record"),
2099 1
                Some(val)
2100
            );
2101 1
        }
2102

2103 1
        fs::remove_file("./target/test_recover_tx_choice.persy").unwrap();
2104 1
    }
2105
}

Read our documentation on viewing source code .

Loading