summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2018-04-30 18:23:20 +0200
committerMatthias Beyer <mail@beyermatthias.de>2018-04-30 18:39:59 +0200
commit860e47a256d38fd959ea83acd2dd2023dee0ee83 (patch)
treea28e8651271816cc733b6bfac18cef96e3d25a4f /lib
parent76966bcd6c6e9c330cc97ad230e84f3dbddcba56 (diff)
Add functionality to flush the internal cache
Before we had the problem that when iterating over _a lot_ (like 5k) entries and also fetching them, at some point the OS would return with "Too many files open". That is because the store internally caches a lot. With this change, the Store gets an API to query how big the cache is, how much the cache can currently hold and (and that's the main thing in this patch) to flush the cache to disk. A function to simply ask the store whether its cache should be flushed (which would us require to ask the OS how many files we can open... which would be possible with `libc::getrlimit`) does not yet exist, though, but could be added easily if desired.
Diffstat (limited to 'lib')
-rw-r--r--lib/core/libimagstore/src/store.rs43
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/core/libimagstore/src/store.rs b/lib/core/libimagstore/src/store.rs
index 5a7868a9..9d604abe 100644
--- a/lib/core/libimagstore/src/store.rs
+++ b/lib/core/libimagstore/src/store.rs
@@ -477,6 +477,49 @@ impl Store {
Ok(())
}
+ /// Flush the store internal cache
+ ///
+ /// This is helpful if a lot of entries are beeing read/written, because the store holds the
+ /// file handles internally. At some point, the OS simply errors with "Too many files open".
+ /// With this function, not-borrowed entries can be flushed back to disk and thus file handles
+ /// are dropped.
+ ///
+ /// After the flushables are dropped, the internal cache is shrinked to fit the number of
+ /// elements still in the cache.
+ ///
+ pub fn flush_cache(&self) -> Result<()> {
+ // We borrow this early so that between the aggregation of the flushables and the actual
+ // flush, there is no borrowing from the store.
+ let mut hsmap = self.entries.write().map_err(|_| SE::from_kind(SEK::LockPoisoned))?;
+ let mut to_flush = vec![];
+
+ for (storeid, se) in hsmap.deref() {
+ if !se.is_borrowed() {
+ to_flush.push(storeid.clone());
+ }
+ }
+
+ for id in to_flush {
+ let _ = hsmap.remove(&id);
+ }
+
+ hsmap.shrink_to_fit();
+
+ Ok(())
+ }
+
+ /// The number of elements in the internal cache
+ pub fn cache_size(&self) -> Result<usize> {
+ let hsmap = self.entries.read().map_err(|_| SE::from_kind(SEK::LockPoisoned))?;
+ Ok(hsmap.iter().count())
+ }
+
+ /// The size of the internal cache
+ pub fn cache_capacity(&self) -> Result<usize> {
+ let hsmap = self.entries.read().map_err(|_| SE::from_kind(SEK::LockPoisoned))?;
+ Ok(hsmap.capacity())
+ }
+
/// Get a copy of a given entry, this cannot be used to mutate the one on disk
///
/// # Return value