Skip to content

Commit 71c4695

Browse files
committed
feat(api): use Mutex<HashMap> instead of DashMap
1 parent 2b4fd62 commit 71c4695

8 files changed

Lines changed: 61 additions & 71 deletions

File tree

Cargo.lock

Lines changed: 12 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ cli = ["clap/derive", "clap_complete", "clap-utilities", "json"]
4949
cli-completions = ["cli"]
5050

5151
[dependencies]
52-
dashmap = "^6.1.0"
52+
parking_lot = "^0.12.4"
5353
pipe-trait = "^0.4.0"
5454
smart-default = "^0.7.1"
5555
derive_more = { version = "^2.0.1", features = ["full"] }

src/hardlink/aware.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,39 @@ use crate::{
1010
size,
1111
};
1212
use derive_more::{AsMut, AsRef, Display, Error, From, Into};
13+
use parking_lot::Mutex;
1314
use pipe_trait::Pipe;
1415
use smart_default::SmartDefault;
15-
use std::{convert::Infallible, fmt::Debug, os::unix::fs::MetadataExt, path::Path};
16+
use std::{convert::Infallible, fmt::Debug, mem, os::unix::fs::MetadataExt, path::Path};
1617

1718
/// Be aware of hardlinks. Treat them as links that share space.
1819
/// Detect files with more than 1 links and record them.
1920
/// Deduplicate them (remove duplicated size) from total size to
2021
/// accurately reflect the real size of their containers.
21-
#[derive(Debug, SmartDefault, Clone, AsRef, AsMut, From, Into)]
22+
#[derive(Debug, SmartDefault, AsRef, AsMut, From, Into)]
2223
pub struct Aware<Size> {
2324
/// Map an inode number to its size and detected paths.
24-
record: HardlinkList<Size>,
25+
record: Mutex<HardlinkList<Size>>,
2526
}
2627

2728
pub use Aware as HardlinkAware;
2829

2930
impl<Size> Aware<Size> {
3031
/// Create new hardlinks handler.
3132
pub fn new() -> Self {
32-
HardlinkList::default().pipe(Aware::from)
33+
Aware::from_record(HardlinkList::default())
3334
}
3435

3536
/// Create a detector/recorder of hardlinks.
3637
pub fn from_record(record: HardlinkList<Size>) -> Self {
37-
Aware::from(record)
38+
record.pipe(Mutex::new).pipe(Aware::from)
39+
}
40+
}
41+
42+
// Manual Clone implementation because parking_lot::Mutex doesn't have it.
43+
impl<Size: Clone> Clone for Aware<Size> {
44+
fn clone(&self) -> Self {
45+
self.record.lock().clone().pipe(Aware::from_record)
3846
}
3947
}
4048

@@ -83,6 +91,7 @@ where
8391

8492
let ino = InodeNumber::get(stats);
8593
self.record
94+
.lock()
8695
.add(ino, size, links, path)
8796
.map_err(ReportHardlinksError::AddToRecord)
8897
}
@@ -99,10 +108,14 @@ where
99108
self,
100109
data_tree: &mut DataTree<OsStringDisplay, Size>,
101110
) -> Result<Self::Report, Self::Error> {
102-
let record: Self::Report = self.into();
111+
let mutex: Mutex<Self::Report> = self.into();
112+
let mut guard = mutex.lock();
113+
let record: Self::Report = mem::take(&mut guard);
114+
drop(guard);
115+
drop(mutex);
103116
let hardlink_info: Box<[(Size, LinkPathList)]> = record
104117
.iter()
105-
.map(|values| (*values.size(), values.paths().clone()))
118+
.map(|values| (*values.size, values.paths.clone()))
106119
.collect();
107120
let hardlink_info: Box<[(Size, Vec<&Path>)]> = hardlink_info
108121
.iter()

src/hardlink/hardlink_list.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ pub use Reflection as HardlinkListReflection;
1010
pub use Summary as SharedLinkSummary;
1111

1212
use crate::{hardlink::LinkPathList, inode::InodeNumber, size};
13-
use dashmap::DashMap;
1413
use derive_more::{Display, Error};
1514
use pipe_trait::Pipe;
1615
use smart_default::SmartDefault;
17-
use std::{fmt::Debug, path::Path};
16+
use std::{collections::HashMap, fmt::Debug, path::Path};
1817

1918
/// Map value in [`HardlinkList`].
2019
#[derive(Debug, Clone)]
@@ -35,7 +34,7 @@ struct Value<Size> {
3534
#[derive(Debug, SmartDefault, Clone)]
3635
pub struct HardlinkList<Size>(
3736
/// Map an inode number to its size, number of links, and detected paths.
38-
DashMap<InodeNumber, Value<Size>>, // TODO: benchmark against Mutex<HashMap<InodeNumber, Value<Size>>>
37+
HashMap<InodeNumber, Value<Size>>,
3938
);
4039

4140
impl<Size> HardlinkList<Size> {
@@ -88,7 +87,7 @@ where
8887
/// Add an entry to the record.
8988
#[cfg_attr(not(unix), expect(unused))]
9089
pub(crate) fn add(
91-
&self,
90+
&mut self,
9291
ino: InodeNumber,
9392
size: Size,
9493
links: u64,

src/hardlink/hardlink_list/iter.rs

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use super::{HardlinkList, Value};
22
use crate::{hardlink::LinkPathList, inode::InodeNumber};
3-
use dashmap::{iter::Iter as DashIter, mapref::multiple::RefMulti};
43
use pipe_trait::Pipe;
4+
use std::collections::hash_map;
55

66
/// Iterator over entries in [`HardlinkList`].
77
#[derive(derive_more::Debug)]
88
#[debug(bound())]
99
#[debug("Iter(..)")]
10-
pub struct Iter<'a, Size>(DashIter<'a, InodeNumber, Value<Size>>);
10+
pub struct Iter<'a, Size>(hash_map::Iter<'a, InodeNumber, Value<Size>>);
1111

1212
impl<Size> HardlinkList<Size> {
1313
/// Iterate over the recorded entries.
@@ -20,33 +20,26 @@ impl<Size> HardlinkList<Size> {
2020
#[derive(derive_more::Debug)]
2121
#[debug(bound())]
2222
#[debug("Item(..)")]
23-
pub struct Item<'a, Size>(RefMulti<'a, InodeNumber, Value<Size>>);
24-
25-
impl<'a, Size> Iterator for Iter<'a, Size> {
26-
type Item = Item<'a, Size>;
27-
fn next(&mut self) -> Option<Self::Item> {
28-
self.0.next().map(Item)
29-
}
30-
}
31-
32-
impl<'a, Size> Item<'a, Size> {
23+
pub struct Item<'a, Size> {
3324
/// The inode number of the file.
34-
pub fn ino(&self) -> InodeNumber {
35-
*self.0.key()
36-
}
37-
25+
pub ino: InodeNumber,
3826
/// Size of the file.
39-
pub fn size(&self) -> &Size {
40-
&self.0.value().size
41-
}
42-
27+
pub size: &'a Size,
4328
/// Total number of links of the file, both listed (in [`Self::paths`]) and unlisted.
44-
pub fn links(&self) -> u64 {
45-
self.0.value().links
46-
}
47-
29+
pub links: u64,
4830
/// Paths to the detected links of the file.
49-
pub fn paths(&self) -> &LinkPathList {
50-
&self.0.value().paths
31+
pub paths: &'a LinkPathList,
32+
}
33+
34+
impl<'a, Size> Iterator for Iter<'a, Size> {
35+
type Item = Item<'a, Size>;
36+
fn next(&mut self) -> Option<Self::Item> {
37+
let (ino, Value { size, links, paths }) = self.0.next()?;
38+
Some(Item {
39+
ino: *ino,
40+
size,
41+
links: *links,
42+
paths,
43+
})
5144
}
5245
}

src/hardlink/hardlink_list/reflection.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::{HardlinkList, Value};
22
use crate::{hardlink::LinkPathListReflection, inode::InodeNumber};
3-
use dashmap::DashMap;
43
use derive_more::{Display, Error, Into, IntoIterator};
54
use pipe_trait::Pipe;
5+
use std::collections::HashMap;
66

77
#[cfg(feature = "json")]
88
use serde::{Deserialize, Serialize};
@@ -106,7 +106,7 @@ pub enum ConversionError {
106106
impl<Size> TryFrom<Reflection<Size>> for HardlinkList<Size> {
107107
type Error = ConversionError;
108108
fn try_from(Reflection(entries): Reflection<Size>) -> Result<Self, Self::Error> {
109-
let map = DashMap::with_capacity(entries.len());
109+
let mut map = HashMap::with_capacity(entries.len());
110110

111111
for entry in entries {
112112
let (ino, value) = entry.dissolve();

src/hardlink/hardlink_list/summary.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,9 @@ impl<'a, Size: Copy> SummarizeHardlinks<Size> for &IterItem<'a, Size> {
213213
type Summary = SingleInodeSummary<Size>;
214214
fn summarize_hardlinks(self) -> Self::Summary {
215215
SingleInodeSummary {
216-
links: self.links(),
217-
paths: self.paths().len(),
218-
size: *self.size(),
216+
links: self.links,
217+
paths: self.paths.len(),
218+
size: *self.size,
219219
}
220220
}
221221
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ pub mod status_board;
4343
pub mod tree_builder;
4444
pub mod visualizer;
4545

46+
pub use parking_lot;
4647
pub use zero_copy_pads;

0 commit comments

Comments
 (0)