11//! `prune` subcommand
22
3- use derive_setters:: Setters ;
43/// App-local prelude includes `app_reader()`/`app_writer()`/`app_config()`
54/// accessors along with logging macros. Customize as you see fit.
6- use log:: { info, warn} ;
7-
85use std:: {
96 cmp:: Ordering ,
107 collections:: { BTreeMap , BTreeSet } ,
118 str:: FromStr ,
129 sync:: { Arc , Mutex } ,
1310} ;
1411
15- use bitmask_enum:: bitmask;
1612use bytesize:: ByteSize ;
1713use chrono:: { DateTime , Duration , Local } ;
1814use derive_more:: Add ;
15+ use derive_setters:: Setters ;
16+ use enumset:: { EnumSet , EnumSetType } ;
1917use itertools:: Itertools ;
18+ use log:: { info, warn} ;
2019use rayon:: prelude:: { IntoParallelIterator , ParallelIterator } ;
20+ use serde:: { Deserialize , Serialize } ;
2121
2222use crate :: {
2323 backend:: {
@@ -269,8 +269,8 @@ impl FromStr for LimitOption {
269269 }
270270}
271271
272- #[ bitmask ( u8 ) ]
273- #[ bitmask_config ( vec_debug ) ]
272+ #[ derive ( EnumSetType , Debug , PartialOrd , Ord , Serialize , Deserialize ) ]
273+ #[ enumset ( serialize_repr = "list" ) ]
274274pub enum PackStatus {
275275 NotCompressed ,
276276 TooYoung ,
@@ -282,7 +282,7 @@ pub enum PackStatus {
282282 Marked ,
283283}
284284
285- #[ derive( Debug , Clone , Copy ) ]
285+ #[ derive( Debug , Clone , Copy , Serialize ) ]
286286pub struct DebugDetailedStats {
287287 pub packs : u64 ,
288288 pub unused_blobs : u64 ,
@@ -291,15 +291,26 @@ pub struct DebugDetailedStats {
291291 pub used_size : u64 ,
292292}
293293
294- #[ derive( Debug , Default ) ]
295- pub struct DebugStats ( pub BTreeMap < ( PackToDo , BlobType , PackStatus ) , DebugDetailedStats > ) ;
294+ #[ derive( Debug , Clone , Copy , Serialize , PartialEq , Eq , PartialOrd , Ord ) ]
295+ pub struct DebugStatsKey {
296+ pub todo : PackToDo ,
297+ pub blob_type : BlobType ,
298+ pub status : EnumSet < PackStatus > ,
299+ }
300+
301+ #[ derive( Debug , Default , Serialize ) ]
302+ pub struct DebugStats ( pub BTreeMap < DebugStatsKey , DebugDetailedStats > ) ;
296303
297304impl DebugStats {
298- fn add ( & mut self , pi : & PackInfo , todo : PackToDo , status : PackStatus ) {
305+ fn add ( & mut self , pi : & PackInfo , todo : PackToDo , status : EnumSet < PackStatus > ) {
299306 let blob_type = pi. blob_type ;
300307 let details = self
301308 . 0
302- . entry ( ( todo, blob_type, status) )
309+ . entry ( DebugStatsKey {
310+ todo,
311+ blob_type,
312+ status,
313+ } )
303314 . or_insert ( DebugDetailedStats {
304315 packs : 0 ,
305316 unused_blobs : 0 ,
@@ -400,7 +411,7 @@ pub struct PruneStats {
400411 pub index_files : u64 ,
401412 /// Number of index files which will be rebuilt during the prune
402413 pub index_files_rebuild : u64 ,
403- /// Number of index files which will be rebuilt during the prune
414+ /// Detailed debug statistics
404415 pub debug : DebugStats ,
405416}
406417
@@ -441,7 +452,7 @@ impl PruneIndex {
441452}
442453
443454/// Task to be executed by a `PrunePlan` on Packs
444- #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
455+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Serialize ) ]
445456pub enum PackToDo {
446457 // TODO: Add documentation
447458 Undecided ,
@@ -559,7 +570,7 @@ impl PrunePack {
559570 & mut self ,
560571 todo : PackToDo ,
561572 pi : & PackInfo ,
562- status : PackStatus ,
573+ status : EnumSet < PackStatus > ,
563574 stats : & mut PruneStats ,
564575 ) {
565576 let tpe = self . blob_type ;
@@ -626,7 +637,7 @@ pub struct PrunePlan {
626637 /// The ids of the existing packs
627638 existing_packs : BTreeMap < Id , u32 > ,
628639 /// The packs which should be repacked
629- repack_candidates : Vec < ( PackInfo , PackStatus , RepackReason , usize , usize ) > ,
640+ repack_candidates : Vec < ( PackInfo , EnumSet < PackStatus > , RepackReason , usize , usize ) > ,
630641 /// The index files
631642 index_files : Vec < PruneIndex > ,
632643 /// `prune` statistics
@@ -784,31 +795,31 @@ impl PrunePlan {
784795 self . stats . blobs [ pi. blob_type ] . unused += u64:: from ( pi. unused_blobs ) ;
785796 self . stats . size [ pi. blob_type ] . used += u64:: from ( pi. used_size ) ;
786797 self . stats . size [ pi. blob_type ] . unused += u64:: from ( pi. unused_size ) ;
787- let mut status = PackStatus :: none ( ) ;
798+ let mut status = EnumSet :: empty ( ) ;
788799
789800 // Various checks to determine if packs need to be kept
790801 let too_young = pack. time > Some ( self . time - keep_pack) ;
791802 if too_young && !pack. delete_mark {
792- status |= PackStatus :: TooYoung ;
803+ _ = status . insert ( PackStatus :: TooYoung ) ;
793804 }
794805 let keep_uncacheable = repack_cacheable_only && !pack. blob_type . is_cacheable ( ) ;
795806
796807 let to_compress = repack_uncompressed && !pack. is_compressed ( ) ;
797808 if to_compress {
798- status |= PackStatus :: NotCompressed ;
809+ _ = status . insert ( PackStatus :: NotCompressed ) ;
799810 }
800811 let size_mismatch = !pack_sizer[ pack. blob_type ] . size_ok ( pack. size ) ;
801812 if pack_sizer[ pack. blob_type ] . is_too_small ( pack. size ) {
802- status |= PackStatus :: TooSmall ;
813+ _ = status . insert ( PackStatus :: TooSmall ) ;
803814 }
804815 if pack_sizer[ pack. blob_type ] . is_too_large ( pack. size ) {
805- status |= PackStatus :: TooLarge ;
816+ _ = status . insert ( PackStatus :: TooLarge ) ;
806817 }
807818 match ( pack. delete_mark , pi. used_blobs , pi. unused_blobs ) {
808819 ( false , 0 , _) => {
809820 // unused pack
810821 self . stats . packs . unused += 1 ;
811- status |= PackStatus :: HasUnusedBlobs ;
822+ _ = status . insert ( PackStatus :: HasUnusedBlobs ) ;
812823 if too_young {
813824 // keep packs which are too young
814825 pack. set_todo ( PackToDo :: Keep , & pi, status, & mut self . stats ) ;
@@ -819,7 +830,7 @@ impl PrunePlan {
819830 ( false , 1 .., 0 ) => {
820831 // used pack
821832 self . stats . packs . used += 1 ;
822- status |= PackStatus :: HasUsedBlobs ;
833+ _ = status . insert ( PackStatus :: HasUsedBlobs ) ;
823834 if too_young || keep_uncacheable {
824835 pack. set_todo ( PackToDo :: Keep , & pi, status, & mut self . stats ) ;
825836 } else if to_compress || repack_all {
@@ -846,7 +857,8 @@ impl PrunePlan {
846857 ( false , 1 .., 1 ..) => {
847858 // partly used pack
848859 self . stats . packs . partly_used += 1 ;
849- status |= PackStatus :: HasUsedBlobs | PackStatus :: HasUnusedBlobs ;
860+ status
861+ . insert_all ( PackStatus :: HasUsedBlobs | PackStatus :: HasUnusedBlobs ) ;
850862
851863 if too_young || keep_uncacheable {
852864 // keep packs which are too young and non-cacheable packs if requested
@@ -863,18 +875,18 @@ impl PrunePlan {
863875 }
864876 }
865877 ( true , 0 , _) => {
866- status |= PackStatus :: Marked ;
878+ _ = status . insert ( PackStatus :: Marked ) ;
867879 match pack. time {
868880 // unneeded and marked pack => check if we can remove it.
869881 Some ( local_date_time)
870882 if self . time - local_date_time >= keep_delete =>
871883 {
872- status |= PackStatus :: TooYoung ;
884+ _ = status . insert ( PackStatus :: TooYoung ) ;
873885 pack. set_todo ( PackToDo :: Delete , & pi, status, & mut self . stats ) ;
874886 }
875887 None => {
876888 warn ! ( "pack to delete {}: no time set, this should not happen! Keeping this pack." , pack. id) ;
877- status |= PackStatus :: TimeNotSet ;
889+ _ = status . insert ( PackStatus :: TimeNotSet ) ;
878890 pack. set_todo (
879891 PackToDo :: KeepMarkedAndCorrect ,
880892 & pi,
@@ -891,7 +903,7 @@ impl PrunePlan {
891903 }
892904 }
893905 ( true , 1 .., _) => {
894- status |= PackStatus :: Marked | PackStatus :: HasUsedBlobs ;
906+ status. insert_all ( PackStatus :: Marked | PackStatus :: HasUsedBlobs ) ;
895907 // needed blobs; mark this pack for recovery
896908 pack. set_todo ( PackToDo :: Recover , & pi, status, & mut self . stats ) ;
897909 }
0 commit comments