History

Handle registration (#266)

Sebastian Thiel committed 4 years ago

Commit df4e4eb1 parent 3a5cb5f1 file · +84 −7Browse files

Showing the changes to git-odb/src (1 of 1 file). Show all

Unified · Split

git-odb/src/store/general/mod.rs+84−7
@@ -7,12 +7,12 @@ use std::sync::atomic::AtomicUsize; · 6 unmodified lines
77
88 /// This effectively acts like a handle but exists to be usable from the actual `crate::Handle` implementation which adds caches on top.
99 /// Each store is quickly cloned and contains thread-local state for shared packs.
10−#[derive(Clone)]
1110 pub struct Handle<S>
1211 where
1312 S: Deref<Target = Store> + Clone,
1413 {
15− state: S,
14+ pub(crate) store: S,
15+ pub(crate) token: Option<handle::Mode>,
1616 }
1717
1818 pub struct Store {
@@ -81,6 +81,7 @@ mod init { · 62 unmodified lines
8181 use arc_swap::ArcSwap;
8282 use git_features::threading::OwnShared;
8383 use std::iter::FromIterator;
84+ use std::ops::Deref;
8485 use std::path::PathBuf;
8586 use std::sync::atomic::AtomicUsize;
8687 use std::sync::Arc;
@@ -102,10 +103,6 @@ mod init { · 15 unmodified lines
102103 num_handles_unstable: Default::default(),
103104 })
104105 }
105−
106− pub fn to_handle(self: &OwnShared<Self>) -> super::Handle<OwnShared<super::Store>> {
107− super::Handle { state: self.clone() }
108− }
109106 }
110107 }
111108
@@ -121,7 +118,7 @@ mod store { · 9 unmodified lines
121118
122119 /// A way to indicate which pack indices we have seen already and which of them are loaded, along with an idea
123120 /// of whether stored `PackId`s are still usable.
124− #[derive(Clone, Default)]
121+ #[derive(Default)]
125122 pub struct SlotIndexMarker {
126123 /// The generation the `loaded_until_index` belongs to. Indices of different generations are completely incompatible.
127124 /// This value changes once the internal representation is compacted, something that may happen only if there is no handle
@@ -272,6 +269,9 @@ mod store { · 144 unmodified lines
272269
273270 pub mod handle {
274271 use crate::general::store;
272+ use git_features::threading::OwnShared;
273+ use std::ops::Deref;
274+ use std::sync::atomic::Ordering;
275275 use std::sync::Arc;
276276
277277 pub(crate) mod multi_index {
@@ -338,6 +338,83 @@ pub mod handle { · 60 unmodified lines
338338 }
339339 }
340340 }
341+
342+ pub(crate) enum Mode {
343+ DeletedPacksAreInaccessible,
344+ /// This mode signals that we should not unload packs even after they went missing.
345+ KeepDeletedPacksAvailable,
346+ }
347+
348+ /// Handle registration
349+ impl super::Store {
350+ pub(crate) fn register_handle(&self) -> Mode {
351+ self.num_handles_unstable.fetch_add(1, Ordering::Relaxed);
352+ Mode::DeletedPacksAreInaccessible
353+ }
354+ pub(crate) fn remove_handle(&self, mode: Mode) {
355+ match mode {
356+ Mode::KeepDeletedPacksAvailable => {
357+ let _ = self.path.lock();
358+ self.num_handles_stable.fetch_sub(1, Ordering::SeqCst)
359+ }
360+ Mode::DeletedPacksAreInaccessible => self.num_handles_unstable.fetch_sub(1, Ordering::Relaxed),
361+ };
362+ }
363+ pub(crate) fn upgrade_handle(&self, mode: Mode) -> Mode {
364+ if let Mode::DeletedPacksAreInaccessible = mode {
365+ let _ = self.path.lock();
366+ self.num_handles_stable.fetch_add(1, Ordering::SeqCst);
367+ self.num_handles_unstable.fetch_sub(1, Ordering::SeqCst);
368+ }
369+ Mode::KeepDeletedPacksAvailable
370+ }
371+ }
372+
373+ /// Handle creation
374+ impl super::Store {
375+ pub fn to_handle(self: &OwnShared<Self>) -> super::Handle<OwnShared<super::Store>> {
376+ let token = self.register_handle();
377+ super::Handle {
378+ store: self.clone(),
379+ token: Some(token),
380+ }
381+ }
382+ }
383+
384+ impl<S> super::Handle<S>
385+ where
386+ S: Deref<Target = super::Store> + Clone,
387+ {
388+ /// Call once if pack ids are stored and later used for lookup, meaning they should always remain mapped and not be unloaded
389+ /// even if they disappear from disk.
390+ /// This must be called if there is a chance that git maintenance is happening while a pack is created.
391+ pub fn prevent_pack_unload(&mut self) {
392+ self.token = self.token.take().map(|token| self.store.upgrade_handle(token));
393+ }
394+ }
395+
396+ impl<S> Drop for super::Handle<S>
397+ where
398+ S: Deref<Target = super::Store> + Clone,
399+ {
400+ fn drop(&mut self) {
401+ if let Some(token) = self.token.take() {
402+ self.store.remove_handle(token)
403+ }
404+ }
405+ }
406+
407+ impl<S> Clone for super::Handle<S>
408+ where
409+ S: Deref<Target = super::Store> + Clone,
410+ {
411+ fn clone(&self) -> Self {
412+ super::Handle {
413+ store: self.store.clone(),
414+ token: self.store.register_handle().into(),
415+ }
416+ }
417+ }
341418 }
342419
343420 pub mod load_indices {