coven_database/
file_database_prepared_pin.rs1use super::{CacheReservation, FileDatabase};
7use crate::{file_removals::OwnedFile, DbError, FileRef};
8use coven_foundation::files::FileName;
9use coven_foundation::locks::read_unpoisoned;
10use std::sync::Arc;
11
12pub struct PreparedPin {
16 reserved: Arc<crate::reserved_names::ReservedNames>,
18 copies: Vec<(FileRef, FileName)>,
20 kept: Vec<FileRef>,
22}
23
24impl FileDatabase {
25 pub fn prepared_pin(
29 &self,
30 copies: Vec<CacheReservation>,
31 kept: Vec<FileRef>,
32 ) -> Result<PreparedPin, DbError> {
33 let reserved = {
34 let slot = read_unpoisoned(&self.database.inner);
35 slot.as_ref().ok_or(DbError::StoreClosed)?.staging.clone()
36 };
37 let copies = copies
38 .into_iter()
39 .map(|mut reservation| {
40 let _writing = reservation.writing.take();
43 (reservation.file.clone(), reservation.name.clone())
44 })
45 .collect();
46 Ok(PreparedPin { reserved, copies, kept })
47 }
48
49 #[cfg(any(test, feature = "test-utils"))]
52 pub async fn commit_pin(&self, prepared: PreparedPin) -> Result<(), DbError> {
53 self.database.write(move |sql| sql.pin(prepared)).await
54 }
55
56 pub async fn kept(&self, file: &FileRef) -> Result<bool, DbError> {
58 let file = file.clone();
59 self.read(move |db| super::cache::kept(db, &file)).await
60 }
61}
62
63impl PreparedPin {
64 pub(crate) fn names(&self) -> impl Iterator<Item = OwnedFile> + '_ {
66 self.copies.iter().map(|(_, name)| OwnedFile::Cached(name.clone()))
67 }
68
69 pub(crate) fn take(mut self) -> (Vec<(FileRef, FileName)>, Vec<FileRef>) {
72 (std::mem::take(&mut self.copies), std::mem::take(&mut self.kept))
73 }
74}
75
76impl std::fmt::Debug for PreparedPin {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 f.debug_struct("PreparedPin")
79 .field("copies", &self.copies.len())
80 .field("kept", &self.kept.len())
81 .finish_non_exhaustive()
82 }
83}
84
85impl Drop for PreparedPin {
86 fn drop(&mut self) {
87 self.reserved.release(self.names());
88 }
89}