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 journal;
40
mod locks;
41
mod persy;
42
mod record_scanner;
43
mod segment;
44
mod snapshot;
45
mod transaction;
46

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

716
        Ok(persy)
717
    }
718

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Read our documentation on viewing source code .

Loading