Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.VaultAnalyzerCLI.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 
7 namespace Dcp\Vault;
8 
9 require_once 'WHAT/Lib.Common.php';
10 
12 {
13 }
14 
16 {
17 
18  public static function main(\Action & $action)
19  {
20  $opts = array();
21  $usage = new \ApiUsage($action);
22  $usage->setDefinitionText('Analyze or clean orphan files');
23  $usage->setStrictMode(true);
24  $opts['analyze'] = ($usage->addEmptyParameter('analyze', 'Analyze orphan files (non-destructive)') !== false);
25  $opts['clean'] = ($usage->addEmptyParameter('clean', 'Clean orphan files') !== false);
26  $opts['missing-files'] = ($usage->addEmptyParameter('missing-files', "Use in conjunction with '--analyze' to analyze missing physical files instead of orphan files") !== false);
27  $opts['skip-trash'] = ($usage->addEmptyParameter('skip-trash', "Really delete file and do not move them under '<vault_root>/.trash/' sub-directory") !== false);
28  $usage->verify();
29  if (!$opts['analyze'] && !$opts['clean']) {
30  $usage->exitError("Use '--analyze' or '--clean'.");
31  return;
32  }
33  if ($opts['analyze'] xor !$opts['clean']) {
34  $usage->exitError("Use either '--analyze' or '--clean', but not both.");
35  return;
36  }
37 
38  try {
39  if ($opts['analyze']) {
40  if ($opts['missing-files']) {
41  self::main_analyze_missing_files();
42  } else {
43  self::main_analyze_orphans();
44  }
45  } elseif ($opts['clean']) {
46  self::main_clean_orphans($opts['skip-trash']);
47  }
48  }
49  catch(VaultAnalyzerCLIException $e) {
50  printf("\nError: %s\n\n", $e->getMessage());
51  exit(1);
52  }
53  return;
54  }
55 
56  public static function main_analyze_orphans()
57  {
59  self::checkDocVaultIndex($vaultAnalyzer);
60 
61  printf("* Analyzing... ");
62  $report = $vaultAnalyzer->summary();
63 
64  printf("Done.\n");
65  printf("\n");
66  printf("Analyze\n");
67  printf("-------\n");
68  printf("\n");
69  printf("All:\n");
70  printf("\tcount = %d\n", $report['all']['count']);
71  printf("\tsize = %d%s\n", $report['all']['size'], (empty($report['all']['size_pretty']) ? '' : ' (' . $report['all']['size_pretty'] . ')'));
72  printf("\n");
73  printf("Used:\n");
74  printf("\tcount = %d\n", $report['used']['count']);
75  printf("\tsize = %d%s (%3.02f%%)\n", $report['used']['size'], ((empty($report['used']['size_pretty'])) ? '' : ' (' . $report['used']['size_pretty'] . ')') , (($report['all']['size'] != 0) ? ((100 * $report['used']['size']) / $report['all']['size']) : '0'));
76  printf("\n");
77  printf("Orphan:\n");
78  printf("\tcount = %d\n", $report['orphan']['count']);
79  printf("\tsize = %d%s (%3.02f%%)\n", $report['orphan']['size'], ((empty($report['orphan']['size_pretty'])) ? '' : ' (' . $report['orphan']['size_pretty'] . ')') , (($report['all']['size'] != 0) ? ((100 * $report['orphan']['size']) / $report['all']['size']) : '0'));
80  printf("\n");
81 
82  return;
83  }
84 
85  public static function main_clean_orphans($skipTrash = false)
86  {
88  self::checkDocVaultIndex($vaultAnalyzer);
89 
90  printf("* Cleanup docvaultindex: ");
91  $report = $vaultAnalyzer->cleanDocVaultIndex();
92  printf("removed %d entries.\n", $report['count']);
93 
94  $report = $vaultAnalyzer->analyzeOrphans();
95  printf("* Deleting %d orphan files...\n", $report['count']);
96  $pom = new \Dcp\ConsoleProgressOMeter();
97  $pom->setMax($report['count'])->setInterval(1000)->start();
98  $p = 0;
99  foreach ($report['iterator'] as $t) {
100  $p++;
101  $vault_root = $t['vault_root'];
102  $trash_root = $vault_root . '/.trash';
103  $filename = $t['filename'];
104  $vault_filename = $vault_root . '/' . $filename;
105  $trash_filename = $trash_root . '/' . $filename;
106  /*
107  * Delete file
108  */
109  if (file_exists($vault_filename)) {
110  if ($skipTrash === true) {
111  if (unlink($vault_filename) === false) {
112  printf("Error: could not delete '%s'.\n", $vault_filename);
113  continue;
114  }
115  } else {
116  if (!is_dir($trash_root)) {
117  if (mkdir($trash_root) === false) {
118  throw new VaultAnalyzerCLIException("Could not create trash dir '%s'.", $trash_root);
119  }
120  }
121  $dir = dirname($trash_filename);
122  if (!is_dir($dir)) {
123  if (mkdir($dir, 0777, true) === false) {
124  printf("Error: could not create trash subdir '%s'.\n", $dir);
125  continue;
126  }
127  }
128  if (rename($vault_filename, $trash_filename) === false) {
129  printf("Error: could not move '%s' to '%s'.\n", $vault_filename, $trash_filename);
130  continue;
131  }
132  }
133  }
134  /*
135  * Delete vaultdiskstorage entry
136  */
137  $vaultAnalyzer->deleteIdFile($t['id_file']);
138  $pom->progress($p);
139  }
140  $pom->finish();
141 
142  printf("* Reset sizes...\n");
143  $fs=new \VaultDiskFsStorage(getDbAccess());
144  $fs->recomputeDirectorySize();
145 
146  printf("\nDone.\n");
147  printf("\n");
148 
149  return;
150  }
151 
152  public static function main_analyze_missing_files()
153  {
154  $vaultAnalyzer = new vaultAnalyzer();
155  self::checkDocVaultIndex($vaultAnalyzer);
156 
157  printf("* Counting entries: ");
158  $report = $vaultAnalyzer->analyzePhysicalFiles();
159  printf("found %d entries.\n", $report['count']);
160  printf("\n");
161  printf("* Checking missing physical files for %d entries...\n", $report['count']);
162  printf("\n");
163  $missing = array();
164  $missing_nodoc = array();
165  $missing_doc = array();
166  foreach ($report['iterator'] as $t) {
167  $vid = $t['id_file'];
168  $docid = $t['docid'];
169  $vault_root = $t['vault_root'];
170  $filename = $t['filename'];
171  $vault_filename = $vault_root . '/' . $filename;
172  if (file_exists($vault_filename)) {
173  continue;
174  }
175  if (!isset($missing[$vault_filename])) {
176  $missing[$vault_filename] = 0;
177  } else {
178  $missing[$vault_filename]++;
179  }
180  if ($docid === null) {
181  printf("Missing physical file '%s' (vid = %d) without docvaultindex entries\n", $vault_filename, $vid);
182  if (!isset($missing_nodoc[$vault_filename])) {
183  $missing_nodoc[$vault_filename] = 0;
184  } else {
185  $missing_nodoc[$filename]++;
186  }
187  } else {
188  printf("Missing physical file '%s' (vid = %d) with valid docvaultindex entries (docid = %d)\n", $vault_filename, $vid, $docid);
189  if (!isset($missing_doc[$vault_filename])) {
190  $missing_doc[$vault_filename] = 0;
191  } else {
192  $missing_doc[$vault_filename]++;
193  }
194  }
195  }
196  printf("\n");
197  printf("Analyze\n");
198  printf("-------\n");
199  printf("\n");
200  printf("Found %d missing physical file:\n", count($missing));
201  printf("\twith valid docvaultindex entries = %d\n", count($missing_doc));
202  printf("\twithout docvaultindex entries = %d\n", count($missing_nodoc));
203  printf("\n");
204 
205  return;
206  }
207 
208  protected static function checkDocVaultIndex(VaultAnalyzer & $vaultAnalyzer)
209  {
210  $report = array();
211  if ($vaultAnalyzer->checkDocVaultIndex($report) === false) {
212  throw new VaultAnalyzerCLIException(sprintf("Found inconsistencies in 'docvaultindex': you might need to regenerate docvaultindex with \"./wsh.php --api=refreshVaultIndex\""));
213  }
214  }
215 }
global $action
Exception class use exceptionCode to identifiy correctly exception.
Definition: exceptions.php:19
static main_clean_orphans($skipTrash=false)
$filename
static main(\Action &$action)
$vaultAnalyzer
$docid
Definition: cleanFamily.php:13
getDbAccess()
Definition: Lib.Common.php:368
switch($command) exit
Definition: checkVault.php:46
$dir
Definition: resizeimg.php:144
static checkDocVaultIndex(VaultAnalyzer &$vaultAnalyzer)
$usage
← centre documentaire © anakeen