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
7 7
8/// This effectively acts like a handle but exists to be usable from the actual `crate::Handle` implementation which adds caches on top.8/// This effectively acts like a handle but exists to be usable from the actual `crate::Handle` implementation which adds caches on top.
9/// Each store is quickly cloned and contains thread-local state for shared packs.9/// Each store is quickly cloned and contains thread-local state for shared packs.
10#[derive(Clone)]
11pub struct Handle<S>10pub struct Handle<S>
12where11where
13 S: Deref<Target = Store> + Clone,12 S: Deref<Target = Store> + Clone,
14{13{
15 state: S,14 pub(crate) store: S,
15 pub(crate) token: Option<handle::Mode>,
16}16}
17 17
18pub struct Store {18pub struct Store {
@@ -81,6 +81,7 @@ mod init { · 62 unmodified lines
81 use arc_swap::ArcSwap;81 use arc_swap::ArcSwap;
82 use git_features::threading::OwnShared;82 use git_features::threading::OwnShared;
83 use std::iter::FromIterator;83 use std::iter::FromIterator;
84 use std::ops::Deref;
84 use std::path::PathBuf;85 use std::path::PathBuf;
85 use std::sync::atomic::AtomicUsize;86 use std::sync::atomic::AtomicUsize;
86 use std::sync::Arc;87 use std::sync::Arc;
@@ -102,10 +103,6 @@ mod init { · 15 unmodified lines
102 num_handles_unstable: Default::default(),103 num_handles_unstable: Default::default(),
103 })104 })
104 }105 }
105
106 pub fn to_handle(self: &OwnShared<Self>) -> super::Handle<OwnShared<super::Store>> {
107 super::Handle { state: self.clone() }
108 }
109 }106 }
110}107}
111 108
@@ -121,7 +118,7 @@ mod store { · 9 unmodified lines
121 118
122 /// A way to indicate which pack indices we have seen already and which of them are loaded, along with an idea119 /// A way to indicate which pack indices we have seen already and which of them are loaded, along with an idea
123 /// of whether stored `PackId`s are still usable.120 /// of whether stored `PackId`s are still usable.
124 #[derive(Clone, Default)]121 #[derive(Default)]
125 pub struct SlotIndexMarker {122 pub struct SlotIndexMarker {
126 /// The generation the `loaded_until_index` belongs to. Indices of different generations are completely incompatible.123 /// The generation the `loaded_until_index` belongs to. Indices of different generations are completely incompatible.
127 /// This value changes once the internal representation is compacted, something that may happen only if there is no handle124 /// 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
272 269
273pub mod handle {270pub mod handle {
274 use crate::general::store;271 use crate::general::store;
272 use git_features::threading::OwnShared;
273 use std::ops::Deref;
274 use std::sync::atomic::Ordering;
275 use std::sync::Arc;275 use std::sync::Arc;
276 276
277 pub(crate) mod multi_index {277 pub(crate) mod multi_index {
@@ -338,6 +338,83 @@ pub mod handle { · 60 unmodified lines
338 }338 }
339 }339 }
340 }340 }
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 }
341}418}
342 419
343pub mod load_indices {420pub mod load_indices {