persy/transaction.rs
1use crate::{
2 address::segment_iter::TxSegmentIter,
3 error::{
4 CreateIndexError, CreateSegmentError, DeleteError, DropIndexError, DropSegmentError, GenericError,
5 IndexChangeError, IndexError, IndexOpsError, IndexPutError, InsertError, PrepareError, SegmentError,
6 UpdateError, PE,
7 },
8 id::{IndexId, PersyId, SegmentId, ToIndexId, ToSegmentId},
9 index::{
10 config::{is_index_name_data, is_index_name_meta, IndexType, ValueMode},
11 iter::TxIndexIter,
12 tree::nodes::Value,
13 value_iter::ValueIter,
14 },
15 persy::{IndexInfo, PersyImpl, TxFinalize},
16 transaction::tx_impl::TransactionImpl,
17 ReadError, Snapshot,
18};
19use std::{ops::RangeBounds, sync::Arc};
20
21pub(crate) mod index_locks;
22pub(crate) mod iter;
23pub(crate) mod locks;
24#[cfg(test)]
25mod tests;
26pub mod tx_impl;
27
28/// Transaction container, it include all the changes done in a transaction.
29pub struct Transaction {
30 pub(crate) persy_impl: Arc<PersyImpl>,
31 pub(crate) tx: Option<TransactionImpl>,
32}
33
34fn tx_mut(tx: &mut Option<TransactionImpl>) -> &mut TransactionImpl {
35 tx.as_mut().unwrap()
36}
37impl Transaction {
38 fn tx_mut(&mut self) -> &mut TransactionImpl {
39 tx_mut(&mut self.tx)
40 }
41 fn tx(&self) -> &TransactionImpl {
42 self.tx.as_ref().unwrap()
43 }
44 /// Create a new segment with the provided name
45 ///
46 /// # Example
47 ///
48 /// ```rust
49 /// # use persy::{OpenOptions};
50 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
51 /// # let persy = OpenOptions::new().memory()?;
52 /// let mut tx = persy.begin()?;
53 /// tx.create_segment("my_new_segment")?;
54 /// tx.prepare()?.commit()?;
55 /// # Ok(())
56 /// # }
57 /// ```
58 pub fn create_segment(&mut self, segment: &str) -> Result<SegmentId, PE<CreateSegmentError>> {
59 assert!(!is_index_name_meta(segment));
60 assert!(!is_index_name_data(segment));
61 Ok(self.persy_impl.create_segment(tx_mut(&mut self.tx), segment)?)
62 }
63
64 /// Drop a existing segment
65 ///
66 /// # Example
67 ///
68 /// ```rust
69 /// # use persy::{OpenOptions};
70 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
71 /// # let persy = OpenOptions::new().memory()?;
72 /// # let mut tx = persy.begin()?;
73 /// # tx.create_segment("existing_segment_name")?;
74 /// # tx.prepare()?.commit()?;
75 /// let mut tx = persy.begin()?;
76 /// tx.drop_segment("existing_segment_name")?;
77 /// tx.prepare()?.commit()?;
78 /// # Ok(())
79 /// # }
80 /// ```
81 pub fn drop_segment(&mut self, segment: &str) -> Result<(), PE<DropSegmentError>> {
82 Ok(self.persy_impl.drop_segment(tx_mut(&mut self.tx), segment)?)
83 }
84
85 /// Check if a segment already exist in the storage considering the transaction
86 ///
87 ///
88 /// # Example
89 /// ```rust
90 /// # use persy::{OpenOptions};
91 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
92 /// # let persy = OpenOptions::new().memory()?;
93 /// let mut tx = persy.begin()?;
94 /// tx.create_segment("my_new_segment")?;
95 /// assert!(tx.exists_segment("my_new_segment")?);
96 /// # tx.prepare()?.commit()?;
97 /// # Ok(())
98 /// # }
99 /// ```
100 pub fn exists_segment(&self, segment: &str) -> Result<bool, PE<GenericError>> {
101 Ok(self.persy_impl.exists_segment_tx(self.tx(), segment))
102 }
103
104 /// Resolves the segment to a SegmentId, considering the transaction
105 ///
106 /// # Example
107 ///
108 /// ```rust
109 /// # use persy::{OpenOptions};
110 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
111 /// # let persy = OpenOptions::new().memory()?;
112 /// let mut tx = persy.begin()?;
113 /// tx.create_segment("my_new_segment")?;
114 /// let segment_id = tx.solve_segment_id("my_new_segment")?;
115 /// # tx.prepare()?.commit()?;
116 /// # Ok(())
117 /// # }
118 /// ```
119 pub fn solve_segment_id(&self, segment: impl ToSegmentId) -> Result<SegmentId, PE<SegmentError>> {
120 Ok(self.persy_impl.solve_segment_id_tx(self.tx(), segment)?)
121 }
122
123 /// Resolves the index name to a IndexId, considering the transaction,
124 /// this has no public use as today, but may be used in future.
125 ///
126 /// # Example
127 ///
128 /// ```rust
129 /// # use persy::{OpenOptions, ValueMode};
130 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
131 /// # let persy = OpenOptions::new().memory()?;
132 /// # let mut tx = persy.begin()?;
133 /// let mut tx = persy.begin()?;
134 /// tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
135 /// let index_id = tx.solve_index_id("my_new_index")?;
136 /// # tx.prepare()?.commit()?;
137 /// # Ok(())
138 /// # }
139 /// ```
140 pub fn solve_index_id(&self, index: impl ToIndexId) -> Result<IndexId, PE<IndexError>> {
141 let (id, _) = self.persy_impl.solve_index_id_tx(self.tx(), index)?;
142 Ok(id)
143 }
144
145 /// Create a new record.
146 ///
147 /// This function return an id that can be used by [`read`],
148 /// the record content can be read only with the [`transaction read`] till the transaction is committed.
149 ///
150 /// [`read`]:struct.Persy.html#method.read
151 /// [`transaction read`]:struct.Transaction.html#method.read
152 ///
153 /// # Example
154 ///
155 /// ```rust
156 /// # use persy::{OpenOptions};
157 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
158 /// # let persy = OpenOptions::new().memory()?;
159 /// let mut tx = persy.begin()?;
160 /// # tx.create_segment("seg")?;
161 /// let data = vec![1;20];
162 /// tx.insert("seg", &data)?;
163 /// tx.prepare()?.commit()?;
164 /// # Ok(())
165 /// # }
166 /// ```
167 pub fn insert(&mut self, segment: impl ToSegmentId, rec: &[u8]) -> Result<PersyId, PE<InsertError>> {
168 Ok(PersyId(self.persy_impl.insert_record(
169 tx_mut(&mut self.tx),
170 segment,
171 rec,
172 )?))
173 }
174
175 /// Read the record content considering eventual in transaction changes.
176 ///
177 /// # Example
178 ///
179 /// ```rust
180 /// # use persy::{OpenOptions};
181 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
182 /// # let persy = OpenOptions::new().memory()?;
183 /// let mut tx = persy.begin()?;
184 /// # tx.create_segment("seg")?;
185 /// let data = vec![1;20];
186 /// let id = tx.insert("seg", &data)?;
187 /// let read = tx.read("seg", &id)?.expect("record exists");
188 /// assert_eq!(data,read);
189 /// # tx.prepare()?.commit()?;
190 /// # Ok(())
191 /// # }
192 /// ```
193 pub fn read(&mut self, segment: impl ToSegmentId, id: &PersyId) -> Result<Option<Vec<u8>>, PE<ReadError>> {
194 let segment_id = self.solve_segment_id(segment).map_err(|PE::PE(e)| ReadError::from(e))?;
195 Ok(self.persy_impl.read_tx(tx_mut(&mut self.tx), segment_id, &id.0)?)
196 }
197
198 /// Scan for persistent and in transaction records
199 ///
200 /// # Example
201 ///
202 /// ```rust
203 /// # use persy::{OpenOptions};
204 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
205 /// # let persy = OpenOptions::new().memory()?;
206 /// let mut tx = persy.begin()?;
207 /// # tx.create_segment("seg")?;
208 /// let data = vec![1;20];
209 /// let id = tx.insert("seg", &data)?;
210 /// let mut count = 0;
211 /// for (id,content) in tx.scan("seg")? {
212 /// println!("record size:{}",content.len());
213 /// count+=1;
214 /// }
215 /// assert_eq!(count,1);
216 /// # Ok(())
217 /// # }
218 /// ```
219 pub fn scan(&mut self, segment: impl ToSegmentId) -> Result<TxSegmentIter, PE<SegmentError>> {
220 let segment_id = self.solve_segment_id(segment)?;
221 Ok(TxSegmentIter::new(
222 self.persy_impl.scan_tx(self.tx.as_mut().unwrap(), segment_id)?,
223 self,
224 ))
225 }
226
227 /// Update the record content.
228 ///
229 /// This updated content can be read only with the [`transaction read`] till the transaction is committed.
230 ///
231 /// [`read`]:struct.Transaction.html#method.read
232 ///
233 /// # Example
234 ///
235 /// ```rust
236 /// # use persy::{OpenOptions};
237 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
238 /// # let persy = OpenOptions::new().memory()?;
239 /// let mut tx = persy.begin()?;
240 /// # tx.create_segment("seg")?;
241 /// let data = vec![1;20];
242 /// let id = tx.insert("seg", &data)?;
243 /// let new_data = vec![2;20];
244 /// tx.update("seg", &id, &new_data)?;
245 /// # tx.prepare()?.commit()?;
246 /// # Ok(())
247 /// # }
248 /// ```
249 pub fn update(&mut self, segment: impl ToSegmentId, id: &PersyId, rec: &[u8]) -> Result<(), PE<UpdateError>> {
250 let segment_id = self
251 .solve_segment_id(segment)
252 .map_err(|e| PE::PE(UpdateError::from(e.error())))?;
253 Ok(self.persy_impl.update(tx_mut(&mut self.tx), segment_id, &id.0, rec)?)
254 }
255
256 /// Delete a record.
257 ///
258 /// The record will result deleted only reading it with [`transaction read`] till the transaction is committed.
259 ///
260 /// [`transaction read`]:struct.Persy.html#method.read
261 ///
262 /// # Example
263 ///
264 /// ```rust
265 /// # use persy::{OpenOptions};
266 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
267 /// # let persy = OpenOptions::new().memory()?;
268 /// let mut tx = persy.begin()?;
269 /// # tx.create_segment("seg")?;
270 /// let data = vec![1;20];
271 /// let id = tx.insert("seg", &data)?;
272 /// tx.delete("seg", &id)?;
273 /// # tx.prepare()?.commit()?;
274 /// # Ok(())
275 /// # }
276 /// ```
277 pub fn delete(&mut self, segment: impl ToSegmentId, id: &PersyId) -> Result<(), PE<DeleteError>> {
278 let segment_id = self
279 .solve_segment_id(segment)
280 .map_err(|e| PE::PE(DeleteError::from(e.error())))?;
281 Ok(self.persy_impl.delete(tx_mut(&mut self.tx), segment_id, &id.0)?)
282 }
283
284 /// Create a new index with the name and the value management mode.
285 ///
286 /// The create operation require two template arguments that are the types as keys and
287 /// values of the index this have to match the following operation on the indexes.
288 ///
289 /// # Example
290 ///
291 /// ```rust
292 /// # use persy::{OpenOptions, ValueMode};
293 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
294 /// # let persy = OpenOptions::new().memory()?;
295 /// let mut tx = persy.begin()?;
296 /// tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
297 /// # tx.prepare()?.commit()?;
298 /// # Ok(())
299 /// # }
300 /// ```
301 pub fn create_index<K, V>(&mut self, index_name: &str, value_mode: ValueMode) -> Result<(), PE<CreateIndexError>>
302 where
303 K: IndexType,
304 V: IndexType,
305 {
306 Ok(self
307 .persy_impl
308 .create_index::<K, V>(tx_mut(&mut self.tx), index_name, value_mode)?)
309 }
310
311 /// Drop an existing index.
312 ///
313 /// # Example
314 ///
315 /// ```rust
316 /// # use persy::{OpenOptions, ValueMode};
317 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
318 /// # let persy = OpenOptions::new().memory()?;
319 /// # let mut tx = persy.begin()?;
320 /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
321 /// # tx.prepare()?.commit()?;
322 /// let mut tx = persy.begin()?;
323 /// tx.drop_index("my_new_index")?;
324 /// # tx.prepare()?.commit()?;
325 /// # Ok(())
326 /// # }
327 /// ```
328 pub fn drop_index(&mut self, index_name: &str) -> Result<(), PE<DropIndexError>> {
329 Ok(self.persy_impl.drop_index(tx_mut(&mut self.tx), index_name)?)
330 }
331
332 /// Check if a segment already exist in the storage considering the transaction
333 ///
334 /// # Example
335 ///
336 /// ```rust
337 /// # use persy::{OpenOptions, ValueMode};
338 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
339 /// # let persy = OpenOptions::new().memory()?;
340 /// let mut tx = persy.begin()?;
341 /// tx.create_index::<u8,u8>("my_new_index", ValueMode::Replace)?;
342 /// assert!(tx.exists_index("my_new_index")?);
343 /// # tx.prepare()?.commit()?;
344 /// # Ok(())
345 /// # }
346 /// ```
347 pub fn exists_index(&self, index_name: &str) -> Result<bool, PE<GenericError>> {
348 Ok(self.persy_impl.exists_index_tx(self.tx(), index_name))
349 }
350
351 /// Put a key value in an index following the value mode strategy.
352 ///
353 /// # Example
354 ///
355 /// ```rust
356 /// # use persy::{OpenOptions, ValueMode};
357 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
358 /// # let persy = OpenOptions::new().memory()?;
359 /// let mut tx = persy.begin()?;
360 /// tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
361 /// tx.put::<u8,u8>("my_new_index",10,10)?;
362 /// tx.prepare()?.commit()?;
363 /// # Ok(())
364 /// # }
365 /// ```
366 pub fn put<K, V>(&mut self, index_name: &str, k: K, v: V) -> Result<(), PE<IndexPutError>>
367 where
368 K: IndexType,
369 V: IndexType,
370 {
371 let index_id = self
372 .solve_index_id(index_name)
373 .map_err(|e| PE::PE(IndexPutError::from(e.error())))?;
374 Ok(self
375 .persy_impl
376 .put::<K::Wrapper, V::Wrapper>(tx_mut(&mut self.tx), index_id, k.wrap(), v.wrap())?)
377 }
378
379 /// Remove a key and optionally a specific value from an index following the value mode strategy.
380 ///
381 /// # Example
382 ///
383 /// ```rust
384 /// # use persy::{OpenOptions, ValueMode};
385 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
386 /// # let persy = OpenOptions::new().memory()?;
387 /// let mut tx = persy.begin()?;
388 /// tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
389 /// tx.put::<u8,u8>("my_new_index",10,10)?;
390 /// tx.remove::<u8,u8>("my_new_index",10,Some(10))?;
391 /// # tx.prepare()?.commit()?;
392 /// # Ok(())
393 /// # }
394 /// ```
395 pub fn remove<K, V>(&mut self, index_name: &str, k: K, v: Option<V>) -> Result<(), PE<IndexOpsError>>
396 where
397 K: IndexType,
398 V: IndexType,
399 {
400 let index_id = self
401 .solve_index_id(index_name)
402 .map_err(|e| PE::PE(IndexOpsError::from(e.error())))?;
403 Ok(self.persy_impl.remove::<K::Wrapper, V::Wrapper>(
404 tx_mut(&mut self.tx),
405 index_id,
406 k.wrap(),
407 v.map(|rv| rv.wrap()),
408 )?)
409 }
410
411 /// Get a value or a group of values from a key considering changes in transaction.
412 ///
413 /// # Example
414 ///
415 /// ```rust
416 /// # use persy::{OpenOptions, ValueMode};
417 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
418 /// # let persy = OpenOptions::new().memory()?;
419 /// # let mut tx = persy.begin()?;
420 /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
421 /// tx.put::<u8,u8>("my_new_index",10,10)?;
422 /// let values = tx.get::<u8,u8>("my_new_index",&10)?;
423 /// for value in values {
424 /// //...
425 /// }
426 /// # tx.prepare()?.commit()?;
427 /// # Ok(())
428 /// # }
429 /// ```
430 pub fn get<K, V>(&mut self, index_name: &str, k: &K) -> Result<ValueIter<V>, PE<IndexChangeError>>
431 where
432 K: IndexType,
433 V: IndexType,
434 {
435 let index_id = self
436 .solve_index_id(index_name)
437 .map_err(|e| IndexChangeError::from(e.error()))?;
438 let entry: Option<Value<V::Wrapper>> =
439 self.persy_impl
440 .get_tx::<K::Wrapper, V::Wrapper>(tx_mut(&mut self.tx), index_id, &k.clone().wrap())?;
441 Ok(ValueIter::from(entry))
442 }
443
444 /// Get one value or none from a key considering changes in transaction.
445 ///
446 /// # Example
447 ///
448 /// ```rust
449 /// # use persy::{OpenOptions, ValueMode};
450 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
451 /// # let persy = OpenOptions::new().memory()?;
452 /// # let mut tx = persy.begin()?;
453 /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
454 /// tx.put::<u8,u8>("my_new_index",10,10)?;
455 /// if let Some(value) = tx.one::<u8,u8>("my_new_index",&10)?{
456 /// //...
457 /// }
458 /// # tx.prepare()?.commit()?;
459 /// # Ok(())
460 /// # }
461 /// ```
462 pub fn one<K, V>(&mut self, index_name: &str, k: &K) -> Result<Option<V>, PE<IndexChangeError>>
463 where
464 K: IndexType,
465 V: IndexType,
466 {
467 Ok(self.get(index_name, k)?.next())
468 }
469
470 /// Browse a range of keys and values from an index including the transaction changes
471 ///
472 /// # Example
473 ///
474 /// ```rust
475 /// # use persy::{OpenOptions, ValueMode, TxIndexIter};
476 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
477 /// # let persy = OpenOptions::new().memory()?;
478 /// let mut tx = persy.begin()?;
479 /// # tx.create_index::<u8,u8>("my_new_index", ValueMode::Cluster)?;
480 /// tx.put::<u8,u8>("my_new_index",10,10)?;
481 /// {
482 /// let iter:TxIndexIter<u8,u8> = tx.range("my_new_index",10..12)?;
483 /// for (k,values) in iter {
484 /// for value in values {
485 /// //...
486 /// }
487 /// }
488 /// }
489 /// tx.prepare()?.commit()?;
490 /// # Ok(())
491 /// # }
492 /// ```
493 pub fn range<'a, K, V, R>(
494 &'a mut self,
495 index_name: &str,
496 range: R,
497 ) -> Result<TxIndexIter<'a, K, V>, PE<IndexOpsError>>
498 where
499 K: IndexType,
500 V: IndexType,
501 R: RangeBounds<K>,
502 {
503 let index_id = self
504 .solve_index_id(index_name)
505 .map_err(|e| IndexOpsError::from(e.error()))?;
506 let imp = self.persy_impl.clone();
507
508 let range = PersyImpl::map_index_range_bounds(range);
509 let tx_raw = imp.range_tx(self.tx_mut(), index_id, range)?;
510 Ok(TxIndexIter::new(tx_raw, self))
511 }
512
513 /// Rollback a not yet prepared transaction.
514 ///
515 /// All the resources used for eventual insert or update are released.
516 ///
517 /// # Example
518 ///
519 /// ```rust
520 /// # use persy::{OpenOptions};
521 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
522 /// # let persy = OpenOptions::new().memory()?;
523 /// let mut tx = persy.begin()?;
524 /// # tx.create_segment("seg")?;
525 /// let data = vec![1;20];
526 /// tx.insert("seg", &data)?;
527 /// tx.rollback()?;
528 /// # Ok(())
529 /// # }
530 /// ```
531 pub fn rollback(mut self) -> Result<(), PE<GenericError>> {
532 if let Some(real_tx) = self.tx.take() {
533 self.persy_impl.rollback(real_tx)?;
534 }
535 Ok(())
536 }
537
538 /// Prepare to commit a transaction, when this method return all the validation checks
539 /// are done and is guaranteed that the transaction can be committed successfully
540 ///
541 /// it will lock all the records involved in the transaction
542 /// till a [`commit`] or [`rollback`] is called.
543 ///
544 /// [`commit`]:struct.TransactionFinalize.html#method.commit
545 /// [`rollback`]:struct.TransactionFinalize.html#method.rollback
546 ///
547 /// # Example
548 ///
549 /// ```rust
550 /// # use persy::{OpenOptions};
551 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
552 /// # let persy = OpenOptions::new().memory()?;
553 /// let mut tx = persy.begin()?;
554 /// # tx.create_segment("seg")?;
555 /// //Do what ever operations on the records
556 /// let data = vec![1;20];
557 /// tx.insert("seg", &data)?;
558 /// tx.prepare()?;
559 /// # Ok(())
560 /// # }
561 /// ```
562 pub fn prepare(mut self) -> Result<TransactionFinalize, PE<PrepareError>> {
563 let real_tx = self.tx.take().unwrap();
564 Ok(TransactionFinalize {
565 persy_impl: self.persy_impl.clone(),
566 finalize: Some(self.persy_impl.prepare(real_tx)?),
567 })
568 }
569
570 /// List all the existing segments, considering all the changes in transaction.
571 ///
572 /// # Example
573 ///
574 /// ```rust
575 /// # use persy::{OpenOptions};
576 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
577 /// # let persy = OpenOptions::new().memory()?;
578 /// let mut tx = persy.begin()?;
579 /// tx.create_segment("seg")?;
580 /// let segments = tx.list_segments()?;
581 /// let names = segments.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
582 /// assert!(names.contains(&"seg".to_string()));
583 /// tx.prepare()?.commit()?;
584 /// # Ok(())
585 /// # }
586 /// ```
587 pub fn list_segments(&self) -> Result<Vec<(String, SegmentId)>, GenericError> {
588 Ok(self.persy_impl.list_segments_tx(self.tx()))
589 }
590
591 /// List all the existing indexes, considering changes in the transaction.
592 ///
593 /// # Example
594 ///
595 /// ```rust
596 /// # use persy::{OpenOptions, ValueMode};
597 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
598 /// # let persy = OpenOptions::new().memory()?;
599 /// let mut tx = persy.begin()?;
600 /// tx.create_index::<u8, u8>("idx", ValueMode::Replace)?;
601 /// let indexes = tx.list_indexes()?;
602 /// let names = indexes.into_iter().map(|(name,_id)|name).collect::<Vec<String>>();
603 /// assert!(names.contains(&"idx".to_string()));
604 /// tx.prepare()?.commit()?;
605 /// # Ok(())
606 /// # }
607 /// ```
608 pub fn list_indexes(&self) -> Result<Vec<(String, IndexInfo)>, PE<GenericError>> {
609 Ok(self.persy_impl.list_indexes_tx(self.tx()))
610 }
611
612 /// Prepare and Commit a transaction
613 ///
614 /// # Example
615 ///
616 /// ```rust
617 /// # use persy::{OpenOptions};
618 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
619 /// # let persy = OpenOptions::new().memory()?;
620 /// let mut tx = persy.begin()?;
621 /// # tx.create_segment("seg")?;
622 /// //Do what ever operations on the records
623 /// let data = vec![1;20];
624 /// tx.insert("seg", &data)?;
625 /// tx.commit()?;
626 /// # Ok(())
627 /// # }
628 /// ```
629 pub fn commit(mut self) -> Result<(), PE<PrepareError>> {
630 let real_tx = self.tx.take().unwrap();
631 let mut finalize = self.persy_impl.prepare(real_tx)?;
632 self.persy_impl.commit(&mut finalize)?;
633 Ok(())
634 }
635}
636
637impl Drop for Transaction {
638 fn drop(&mut self) {
639 if let Some(tx) = self.tx.take() {
640 self.persy_impl
641 .rollback(tx)
642 .expect("no failure on rollback transaction on drop");
643 }
644 }
645}
646
647/// prepared transaction state
648#[must_use]
649pub struct TransactionFinalize {
650 persy_impl: Arc<PersyImpl>,
651 finalize: Option<TxFinalize>,
652}
653
654impl TransactionFinalize {
655 /// Rollback a prepared commit.
656 ///
657 /// All the modification are rolled back and all the used resources are put released
658 ///
659 /// # Example
660 ///
661 /// ```rust
662 /// # use persy::{OpenOptions};
663 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
664 /// # let persy = OpenOptions::new().memory()?;
665 /// # let mut tx = persy.begin()?;
666 /// # tx.create_segment("seg")?;
667 /// # tx.prepare()?.commit()?;
668 /// let mut tx = persy.begin()?;
669 /// //Do what ever operations on the records
670 /// let data = vec![1;20];
671 /// tx.insert("seg", &data)?;
672 /// let prepared = tx.prepare()?;
673 /// prepared.rollback()?;
674 /// # Ok(())
675 /// # }
676 /// ```
677 pub fn rollback(mut self) -> Result<(), PE<GenericError>> {
678 if let Some(mut finalize) = self.finalize.take() {
679 self.persy_impl.rollback_prepared(&mut finalize)?;
680 }
681 Ok(())
682 }
683
684 /// Finalize the commit result of a prepared commit.
685 ///
686 /// All the operation done on the transaction are finalized all the lock released, all the
687 /// old resources are released for reuse.
688 ///
689 /// # Example
690 ///
691 /// ```rust
692 /// # use persy::{OpenOptions};
693 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
694 /// # let persy = OpenOptions::new().memory()?;
695 /// # let mut tx = persy.begin()?;
696 /// # tx.create_segment("seg")?;
697 /// # tx.prepare()?.commit()?;
698 /// let mut tx = persy.begin()?;
699 /// let prepared = tx.prepare()?;
700 /// prepared.commit()?;
701 /// # Ok(())
702 /// # }
703 /// ```
704 pub fn commit(mut self) -> Result<(), PE<GenericError>> {
705 if let Some(mut finalize) = self.finalize.take() {
706 self.persy_impl.commit(&mut finalize)?;
707 }
708 Ok(())
709 }
710
711 /// Prepare and Commit a transaction
712 ///
713 /// # Example
714 ///
715 /// ```rust
716 /// # use persy::{OpenOptions};
717 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
718 /// # let persy = OpenOptions::new().memory()?;
719 /// let mut tx = persy.begin()?;
720 /// # tx.create_segment("seg")?;
721 /// //Do what ever operations on the records
722 /// let data = vec![1;20];
723 /// tx.insert("seg", &data)?;
724 /// let prepared = tx.prepare()?;
725 /// let snapshot = prepared.commit_to_snapshot()?;
726 /// # Ok(())
727 /// # }
728 /// ```
729 pub fn commit_to_snapshot(mut self) -> Result<Snapshot, PE<PrepareError>> {
730 let mut finalize = self.finalize.take().expect("at this state is there all the times");
731
732 let pre_segs = self.persy_impl.address().snapshot_list();
733 let snap = self.persy_impl.commit(&mut finalize)?;
734 let snap = self.persy_impl.fill_snapshot_tx(&snap, pre_segs, &finalize.transaction);
735 Ok(Snapshot::new(self.persy_impl.clone(), snap))
736 }
737
738 #[cfg(test)]
739 pub(crate) fn leak(mut self) {
740 if let Some(mut finalize) = self.finalize.take() {
741 finalize.leak();
742 }
743 }
744}
745
746impl Drop for TransactionFinalize {
747 fn drop(&mut self) {
748 if let Some(mut finalize) = self.finalize.take() {
749 self.persy_impl
750 .rollback_prepared(&mut finalize)
751 .expect("no failure on rollback transaction on drop");
752 }
753 }
754}