1 /*
2  *   File name: TreeWalker.cpp
3  *   Summary:	QDirStat helper class to walk a FileInfo tree
4  *   License:	GPL V2 - See file LICENSE for details.
5  *
6  *   Author:	Stefan Hundhammer <Stefan.Hundhammer@gmx.de>
7  */
8 
9 
10 #include "TreeWalker.h"
11 #include "FileSizeStats.h"
12 #include "FileMTimeStats.h"
13 #include "SysUtil.h"
14 #include "Logger.h"
15 #include "Exception.h"
16 
17 #define MAX_RESULTS  200
18 
19 
20 using namespace QDirStat;
21 
22 
upperPercentileThreshold(PercentileStats & stats)23 qreal TreeWalker::upperPercentileThreshold( PercentileStats & stats )
24 {
25     int percentile = 0;
26 
27     if      ( stats.dataSize() <= 100 )                 percentile = 80;
28     else if ( stats.dataSize() * 0.10 <= MAX_RESULTS )  percentile = 90;
29     else if ( stats.dataSize() * 0.05 <= MAX_RESULTS )  percentile = 95;
30     else if ( stats.dataSize() * 0.01 <= MAX_RESULTS )  percentile = 99;
31 
32     qreal threshold = 0.0;
33 
34     if ( percentile > 0 )
35     {
36         logDebug() << "Threshold: " << percentile << ". percentile" << endl;
37         threshold = stats.percentile( percentile );
38     }
39     else
40     {
41         logDebug() << "Threshold: " << MAX_RESULTS << " items" << endl;
42         int index = stats.dataSize() - MAX_RESULTS;
43         threshold = stats.data().at( index );
44     }
45 
46     return threshold;
47 }
48 
49 
lowerPercentileThreshold(PercentileStats & stats)50 qreal TreeWalker::lowerPercentileThreshold( PercentileStats & stats )
51 {
52     int percentile = 0;
53 
54     if      ( stats.dataSize() <= 100 )                 percentile = 20;
55     else if ( stats.dataSize() * 0.10 <= MAX_RESULTS )  percentile = 10;
56     else if ( stats.dataSize() * 0.05 <= MAX_RESULTS )  percentile =  5;
57     else if ( stats.dataSize() * 0.01 <= MAX_RESULTS )  percentile =  1;
58 
59     qreal threshold = 0.0;
60 
61     if ( percentile > 0 )
62     {
63         logDebug() << "Threshold: " << percentile << ". percentile" << endl;
64         threshold = stats.percentile( percentile );
65     }
66     else
67     {
68         logDebug() << "Threshold: " << MAX_RESULTS << " items" << endl;
69         int index = MAX_RESULTS;
70         threshold = stats.data().at( index );
71     }
72 
73     return threshold;
74 }
75 
76 
77 
78 
prepare(FileInfo * subtree)79 void LargestFilesTreeWalker::prepare( FileInfo * subtree )
80 {
81 
82     FileSizeStats stats( subtree );
83     _threshold = (FileSize) upperPercentileThreshold( stats );
84 }
85 
86 
prepare(FileInfo * subtree)87 void NewFilesTreeWalker::prepare( FileInfo * subtree )
88 {
89     FileMTimeStats stats( subtree );
90     _threshold = (time_t) upperPercentileThreshold( stats );
91 }
92 
93 
prepare(FileInfo * subtree)94 void OldFilesTreeWalker::prepare( FileInfo * subtree )
95 {
96     FileMTimeStats stats( subtree );
97     _threshold = (time_t) lowerPercentileThreshold( stats );
98 }
99 
100 
check(FileInfo * item)101 bool BrokenSymLinksTreeWalker::check( FileInfo * item )
102 {
103     return item &&
104         item->isSymLink() &&
105         SysUtil::isBrokenSymLink( item->url() );
106 }
107