@@ -10,31 +10,39 @@ use crate::{
1010 size,
1111} ;
1212use derive_more:: { AsMut , AsRef , Display , Error , From , Into } ;
13+ use parking_lot:: Mutex ;
1314use pipe_trait:: Pipe ;
1415use 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 ) ]
2223pub 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
2728pub use Aware as HardlinkAware ;
2829
2930impl < 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
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 ( )
0 commit comments