]> git.proxmox.com Git - rustc.git/blob - vendor/gix-odb/src/cache.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / gix-odb / src / cache.rs
1 use std::{
2 cell::RefCell,
3 ops::{Deref, DerefMut},
4 rc::Rc,
5 sync::Arc,
6 };
7
8 use crate::Cache;
9
10 /// A type to store pack caches in boxes.
11 pub type PackCache = dyn gix_pack::cache::DecodeEntry + Send + 'static;
12 /// A constructor for boxed pack caches.
13 pub type NewPackCacheFn = dyn Fn() -> Box<PackCache> + Send + Sync + 'static;
14
15 /// A type to store object caches in boxes.
16 pub type ObjectCache = dyn gix_pack::cache::Object + Send + 'static;
17 /// A constructor for boxed object caches.
18 pub type NewObjectCacheFn = dyn Fn() -> Box<ObjectCache> + Send + Sync + 'static;
19
20 impl Cache<crate::store::Handle<Rc<crate::Store>>> {
21 /// Convert this cache's handle into one that keeps its store in an arc. This creates an entirely new store,
22 /// so should be done early to avoid unnecessary work (and mappings).
23 pub fn into_arc(self) -> std::io::Result<Cache<crate::store::Handle<Arc<crate::Store>>>> {
24 let inner = self.inner.into_arc()?;
25 Ok(Cache {
26 inner,
27 new_pack_cache: self.new_pack_cache,
28 new_object_cache: self.new_object_cache,
29 pack_cache: self.pack_cache,
30 object_cache: self.object_cache,
31 })
32 }
33 }
34 impl Cache<crate::store::Handle<Arc<crate::Store>>> {
35 /// No op, as we are containing an arc handle already.
36 pub fn into_arc(self) -> std::io::Result<Cache<crate::store::Handle<Arc<crate::Store>>>> {
37 Ok(self)
38 }
39 }
40
41 impl<S> Cache<S> {
42 /// Dissolve this instance, discard all caches, and return the inner implementation.
43 pub fn into_inner(self) -> S {
44 self.inner
45 }
46 /// Use this methods directly after creating a new instance to add a constructor for pack caches.
47 ///
48 /// These are used to speed up decoding objects which are located in packs, reducing long delta chains by storing
49 /// their intermediate results.
50 pub fn with_pack_cache(mut self, create: impl Fn() -> Box<PackCache> + Send + Sync + 'static) -> Self {
51 self.pack_cache = Some(RefCell::new(create()));
52 self.new_pack_cache = Some(Arc::new(create));
53 self
54 }
55 /// Use this methods directly after creating a new instance to add a constructor for object caches.
56 ///
57 /// Only use this kind of cache if the same objects are repeatedly accessed for great speedups, usually during diffing of
58 /// trees.
59 pub fn with_object_cache(mut self, create: impl Fn() -> Box<ObjectCache> + Send + Sync + 'static) -> Self {
60 self.object_cache = Some(RefCell::new(create()));
61 self.new_object_cache = Some(Arc::new(create));
62 self
63 }
64 /// Set the pack cache constructor on this instance.
65 pub fn set_pack_cache(&mut self, create: impl Fn() -> Box<PackCache> + Send + Sync + 'static) {
66 self.pack_cache = Some(RefCell::new(create()));
67 self.new_pack_cache = Some(Arc::new(create));
68 }
69 /// Set the object cache constructor on this instance.
70 pub fn set_object_cache(&mut self, create: impl Fn() -> Box<ObjectCache> + Send + Sync + 'static) {
71 self.object_cache = Some(RefCell::new(create()));
72 self.new_object_cache = Some(Arc::new(create));
73 }
74 /// Return true if an object cache is present.
75 pub fn has_object_cache(&self) -> bool {
76 self.object_cache.is_some()
77 }
78 /// Return true if a pack cache is present.
79 pub fn has_pack_cache(&self) -> bool {
80 self.pack_cache.is_some()
81 }
82 /// Remove the current pack cache as well as its constructor from this instance.
83 pub fn unset_pack_cache(&mut self) {
84 self.pack_cache = None;
85 self.new_pack_cache = None;
86 }
87 /// Remove the current object cache as well as its constructor from this instance.
88 pub fn unset_object_cache(&mut self) {
89 self.object_cache = None;
90 self.new_object_cache = None;
91 }
92 }
93
94 impl<S> From<S> for Cache<S>
95 where
96 S: gix_pack::Find,
97 {
98 fn from(store: S) -> Self {
99 Self {
100 inner: store,
101 pack_cache: None,
102 new_pack_cache: None,
103 object_cache: None,
104 new_object_cache: None,
105 }
106 }
107 }
108
109 impl<S: Clone> Clone for Cache<S> {
110 fn clone(&self) -> Self {
111 Cache {
112 inner: self.inner.clone(),
113 new_pack_cache: self.new_pack_cache.clone(),
114 new_object_cache: self.new_object_cache.clone(),
115 pack_cache: self.new_pack_cache.as_ref().map(|create| RefCell::new(create())),
116 object_cache: self.new_object_cache.as_ref().map(|create| RefCell::new(create())),
117 }
118 }
119 }
120
121 impl<S> Deref for Cache<S> {
122 type Target = S;
123
124 fn deref(&self) -> &Self::Target {
125 &self.inner
126 }
127 }
128
129 impl<S> DerefMut for Cache<S> {
130 fn deref_mut(&mut self) -> &mut Self::Target {
131 &mut self.inner
132 }
133 }
134
135 mod impls {
136 use std::{cell::RefCell, io::Read, ops::DerefMut};
137
138 use gix_hash::{oid, ObjectId};
139 use gix_object::{Data, Kind};
140 use gix_pack::cache::Object;
141
142 use crate::{find::Header, pack::data::entry::Location, Cache};
143
144 impl<S> crate::Write for Cache<S>
145 where
146 S: crate::Write,
147 {
148 fn write_stream(&self, kind: Kind, size: u64, from: &mut dyn Read) -> Result<ObjectId, crate::write::Error> {
149 self.inner.write_stream(kind, size, from)
150 }
151 }
152
153 impl<S> crate::Find for Cache<S>
154 where
155 S: gix_pack::Find,
156 {
157 fn contains(&self, id: &oid) -> bool {
158 self.inner.contains(id)
159 }
160
161 fn try_find<'a>(&self, id: &oid, buffer: &'a mut Vec<u8>) -> Result<Option<Data<'a>>, crate::find::Error> {
162 gix_pack::Find::try_find(self, id, buffer).map(|t| t.map(|t| t.0))
163 }
164 }
165
166 impl<S> crate::Header for Cache<S>
167 where
168 S: crate::Header,
169 {
170 fn try_header(&self, id: &oid) -> Result<Option<Header>, crate::find::Error> {
171 self.inner.try_header(id)
172 }
173 }
174
175 impl<S> gix_pack::Find for Cache<S>
176 where
177 S: gix_pack::Find,
178 {
179 fn contains(&self, id: &oid) -> bool {
180 self.inner.contains(id)
181 }
182
183 fn try_find<'a>(
184 &self,
185 id: &oid,
186 buffer: &'a mut Vec<u8>,
187 ) -> Result<Option<(Data<'a>, Option<Location>)>, crate::find::Error> {
188 match self.pack_cache.as_ref().map(RefCell::borrow_mut) {
189 Some(mut pack_cache) => self.try_find_cached(id, buffer, pack_cache.deref_mut()),
190 None => self.try_find_cached(id, buffer, &mut gix_pack::cache::Never),
191 }
192 }
193
194 fn try_find_cached<'a>(
195 &self,
196 id: &oid,
197 buffer: &'a mut Vec<u8>,
198 pack_cache: &mut dyn gix_pack::cache::DecodeEntry,
199 ) -> Result<Option<(Data<'a>, Option<gix_pack::data::entry::Location>)>, crate::find::Error> {
200 if let Some(mut obj_cache) = self.object_cache.as_ref().map(RefCell::borrow_mut) {
201 if let Some(kind) = obj_cache.get(&id.as_ref().to_owned(), buffer) {
202 return Ok(Some((Data::new(kind, buffer), None)));
203 }
204 }
205 let possibly_obj = self.inner.try_find_cached(id.as_ref(), buffer, pack_cache)?;
206 if let (Some(mut obj_cache), Some((obj, _location))) =
207 (self.object_cache.as_ref().map(RefCell::borrow_mut), &possibly_obj)
208 {
209 obj_cache.put(id.as_ref().to_owned(), obj.kind, obj.data);
210 }
211 Ok(possibly_obj)
212 }
213
214 fn location_by_oid(&self, id: &oid, buf: &mut Vec<u8>) -> Option<gix_pack::data::entry::Location> {
215 self.inner.location_by_oid(id, buf)
216 }
217
218 fn pack_offsets_and_oid(&self, pack_id: u32) -> Option<Vec<(u64, gix_hash::ObjectId)>> {
219 self.inner.pack_offsets_and_oid(pack_id)
220 }
221
222 fn entry_by_location(&self, location: &Location) -> Option<gix_pack::find::Entry> {
223 self.inner.entry_by_location(location)
224 }
225 }
226 }