Skip to content

Commit

Permalink
add ArcHashmap to store values that are auto removed when no ref to them
Browse files Browse the repository at this point in the history
add homepage url
add locks on dir entry operations
allow publicly only change operations on inode meta with specified fields to update, it will merge time info to take the most recent ones
add back change password when fs is created
  • Loading branch information
radumarias committed May 1, 2024
1 parent 3252448 commit d5658e8
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 127 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.2.0"
edition = "2021"
license = "Apache-2.0"
authors = ["Radu Marias <[email protected]>"]
homepage = "https://github.com/radumarias/rencfs"
repository = "https://github.com/radumarias/rencfs"
readme = "README.md"
keywords = ["filesystem", "fuse", "encryption", "system", "security"]
Expand Down
14 changes: 14 additions & 0 deletions examples/arc_hashmap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use rencfs::arc_hashmap::ArcHashMap;

fn main() {
let mut m = ArcHashMap::new();
{
let v = m.insert(1, 2);
println!("size {}", m.len());
m.insert(2, 3);
println!("size {}", m.len());
let v = m.get_or_insert_with(3, || 4);
println!("size {}", m.len());
}
println!("size {}", m.len());
}
45 changes: 22 additions & 23 deletions src/arc_hashmap.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::collections::HashMap;
use std::hash::Hash;
use std::ops::Deref;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};

pub struct ArcHashMap<K, V>
where
K: Eq + Hash + Copy,
K: Eq + Hash,
{
map: HashMap<K, (Arc<V>, Arc<AtomicUsize>)>,
map: Mutex<HashMap<K, (Arc<V>, Arc<AtomicUsize>)>>,
}

pub struct Guard<V>
Expand All @@ -32,51 +32,50 @@ impl<V> Deref for Guard<V> {
}
}

impl<K: Eq + Hash + Copy, V> ArcHashMap<K, V> {
impl<K: Eq + Hash, V> ArcHashMap<K, V> {
pub fn new() -> Self {
ArcHashMap {
map: HashMap::new(),
map: Mutex::new(HashMap::new()),
}
}

pub fn insert(&mut self, key: K, value: V) -> Guard<V> {
pub fn insert(&self, key: K, value: V) -> Guard<V> {
self.purge();
self.get_or_insert_with(key, || value)
}

pub fn get<'a>(&mut self, key: &K) -> Option<Guard<V>> {
let v = self.map.get_mut(key);
pub fn get<'a>(&self, key: &K) -> Option<Guard<V>> {
self.purge();
self.get_internal(self.map.lock().unwrap().get(key))
}

pub fn get_internal<'a>(&self, v: Option<&(Arc<V>, Arc<AtomicUsize>)>) -> Option<Guard<V>> {
if let Some((v, rc)) = v {
rc.fetch_add(1, Ordering::SeqCst);
return Some(Guard { val: v.clone(), rc: rc.clone() });
}
self.purge();
None
}

pub fn get_or_insert_with<F>(&mut self, key: K, f: F) -> Guard<V>
pub fn get_or_insert_with<F>(&self, key: K, f: F) -> Guard<V>
where
F: FnOnce() -> V,
{
self.purge();
let key2 = key.clone();
self.map.entry(key).or_insert_with(|| {
(Arc::new(f()), Arc::new(AtomicUsize::new(1)))
let mut map = self.map.lock().unwrap();
let v = map.entry(key).or_insert_with(|| {
(Arc::new(f()), Arc::new(AtomicUsize::new(0)))
});
self.get(&key2).unwrap()
self.get_internal(Some(v)).unwrap()
}

fn purge(&mut self) {
let keys = self.map.keys().cloned().collect::<Vec<_>>();
for k in keys {
if self.map.get(&k).unwrap().1.load(Ordering::SeqCst) == 0 {
self.map.remove(&k);
}
}
fn purge(&self) {
let mut map = self.map.lock().unwrap();
map.retain(|_, v| v.1.load(Ordering::SeqCst) > 0);
}

pub fn len(&mut self) -> usize {
pub fn len(&self) -> usize {
self.purge();
self.map.len()
self.map.lock().unwrap().len()
}
}
Loading

0 comments on commit d5658e8

Please sign in to comment.