Commit 6c26629f2311c60ebda581542d7bf8f6a21d4c17

Authored by kevin_fourie
1 parent 5b892972

Merged in from DEV trunk...

KTS-3133
"Error in storage verification process"
Updated.

Committed By: Conrad Vermeulen
Reviewed By: Megan Watson


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/STABLE/trunk@8890 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing 1 changed file with 140 additions and 98 deletions
bin/storageverification.php
1 1 <?php
2 2 /**
3 3 * $Id$
4   - *
  4 + *
5 5 * KnowledgeTree Community Edition
6 6 * Document Management Made Simple
7 7 * Copyright (C) 2008 KnowledgeTree Inc.
8 8 * Portions copyright The Jam Warehouse Software (Pty) Limited
9   - *
  9 + *
10 10 * This program is free software; you can redistribute it and/or modify it under
11 11 * the terms of the GNU General Public License version 3 as published by the
12 12 * Free Software Foundation.
13   - *
  13 + *
14 14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 17 * details.
18   - *
  18 + *
19 19 * You should have received a copy of the GNU General Public License
20 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21   - *
22   - * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
  21 + *
  22 + * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
23 23 * California 94120-7775, or email info@knowledgetree.com.
24   - *
  24 + *
25 25 * The interactive user interfaces in modified source and object code versions
26 26 * of this program must display Appropriate Legal Notices, as required under
27 27 * Section 5 of the GNU General Public License version 3.
28   - *
  28 + *
29 29 * In accordance with Section 7(b) of the GNU General Public License version 3,
30 30 * these Appropriate Legal Notices must retain the display of the "Powered by
31   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  31 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
32 32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
33   - * must display the words "Powered by KnowledgeTree" and retain the original
  33 + * must display the words "Powered by KnowledgeTree" and retain the original
34 34 * copyright notice.
35 35 * Contributor( s): ______________________________________
36 36 */
37 37  
38 38 require_once(dirname(__FILE__) . '/../config/dmsDefaults.php');
39   -require_once(KT_LIB_DIR . '/dispatcher.inc.php');
40   -$sectionName = 'Administration';
41   -require_once(KT_LIB_DIR . '/templating/kt3template.inc.php');
42   -
43   -require_once(KT_LIB_DIR . '/browse/browseutil.inc.php');
44   -
45   -class VerifyDispatcher extends KTDispatcher {
46   - function VerifyDispatcher() {
47   - $this->aIgnore = array(
48   - '.', '..',
49   - 'CVS',
50   - '.empty',
51   - '.htaccess',
52   - '.cvsignore',
53   - '.svn',
54   - );
55   -
56   - $oConfig =& KTConfig::getSingleton();
57   - $this->fsPath = $oConfig->get('urls/documentRoot');
58   -
59   - return parent::KTDispatcher();
  39 +require_once(KT_LIB_DIR . '/storage/storagemanager.inc.php');
  40 +
  41 +// TODO: this does not verify files that are in the storage system, but not on the database. It is better that the storage system
  42 +// be in sync with the database. However, we should have a better way to query the storage driver to give us a list of files.
  43 +
  44 +class StorageVerification
  45 +{
  46 + private $count;
  47 + private $lineCount;
  48 + private $doc;
  49 + const DOCS_PER_DOT = 100;
  50 + const DOTS_PER_LINE = 80;
  51 + private $nl;
  52 + private $tab;
  53 +
  54 + private
  55 + function error($msg)
  56 + {
  57 + $doc = $this->doc;
  58 + $documentId = $doc->getId();
  59 + $path = $doc->getFullPath();
  60 + $filename = $doc->getFileName();
  61 + $storagePath = $doc->getStoragePath();
  62 +
  63 + print "{$this->nl}{$this->nl}";
  64 + print "Problem with Document ID: {$documentId}{$this->nl}";
  65 + print "{$this->tab}Path: {$path}{$this->nl}";
  66 + print "{$this->tab}Filename: {$filename}{$this->nl}";
  67 + print "{$this->tab}StoragePath: {$storagePath}{$this->nl}";
  68 + print "{$this->tab}Problem: {$msg}{$this->nl}{$this->nl}";
  69 + flush();
  70 + $this->count = 0;
  71 + $this->lineCount = 0;
  72 + $this->clearCache();
60 73 }
61 74  
62   - function do_main() {
63   - global $aFoldersToRemove;
64   - global $aFilesToRemove;
65   - global $aRepoDocumentProblems;
66   - global $aRepoFolderProblems;
67   - global $aRepoVersionProblems;
  75 + private
  76 + function progress()
  77 + {
  78 + if ($this->count++ % StorageVerification::DOCS_PER_DOT == 0)
  79 + {
  80 + $this->lineCount++;
  81 + print '.';
  82 + flush();
  83 + }
68 84  
  85 + if ($this->lineCount == StorageVerification::DOTS_PER_LINE )
  86 + {
  87 + print "{$this->nl}";
  88 + flush();
  89 + $this->lineCount = 0;
  90 + }
  91 + $this->clearCache();
  92 + }
69 93  
70   - $this->checkDirectory('');
  94 + private
  95 + function clearCache()
  96 + {
  97 + $metadataid = $this->doc->getMetadataVersionId();
  98 + $contentid = $this->doc->getContentVersionId();
  99 + $iId = $this->doc->getId();
  100 + $cache = KTCache::getSingleton();
  101 + $cache->remove('KTDocumentMetadataVersion/id', $metadataid);
  102 + $cache->remove('KTDocumentContentVersion/id', $contentid);
  103 + $cache->remove('KTDocumentCore/id', $iId);
  104 + $cache->remove('Document/id', $iId);
  105 + unset($GLOBALS['_OBJECTCACHE']['KTDocumentMetadataVersion'][$metadataid]);
  106 + unset($GLOBALS['_OBJECTCACHE']['KTDocumentContentVersion'][$contentid]);
  107 + unset($GLOBALS['_OBJECTCACHE']['KTDocumentCore'][$iId]);
  108 +
  109 + unset($this->doc);
  110 + }
71 111  
72   - $aDocuments =& Document::getList();
73   - foreach ($aDocuments as $oDocument) {
74   - $this->checkRepoDocument($oDocument);
  112 + public
  113 + function run()
  114 + {
  115 + global $argc;
  116 +
  117 + if (isset($argc))
  118 + {
  119 + $this->nl = "\n";
  120 + $this->tab = "\t";
  121 + print "Storage Verification{$this->nl}";
  122 + print "===================={$this->nl}";
75 123 }
  124 + else
  125 + {
  126 + $this->nl = '<br>';
  127 + $this->tab = '&nbsp;&nbsp;&nbsp;&nbsp;';
  128 + print "<b>Storage Verification</b>{$this->nl}";
76 129  
77   - if (!($this->aFilesToRemove or $this->aRepoDocumentProblems)) {
78   - return;
79 130 }
80 131  
81   - $oTemplate =&
82   - $this->oValidator->validateTemplate('ktcore/document/cleanup_script');
83   - $oTemplate->setData(array(
84   - 'aFilesToRemove' => $this->aFilesToRemove,
85   - 'aRepoDocumentProblems' => $this->aRepoDocumentProblems,
86   - ));
87   - print $oTemplate->render();
88   - exit(0);
89   - }
90 132  
91   - function checkDirectory($path) {
92   - $fullpath = sprintf('%s/%s', $this->fsPath, $path);
93 133  
94   - if (!is_dir($fullpath)) {
95   - print "Not a directory: $fullpath\n";
96   - }
  134 + $sql = "SELECT
  135 + dmv.id as metadata_version_id, dcv.document_id, dcv.md5hash, dcv.size
  136 + FROM
  137 + document_content_version dcv
  138 + INNER JOIN document_metadata_version dmv ON dcv.id=dmv.content_version_id";
  139 + $rows = DBUtil::getResultArray($sql);
  140 + $this->count = 0;
  141 + $this->lineCount = 0;
97 142  
98   - $dh = @opendir($fullpath);
99   - if ($dh === false) {
100   - print "Could not open directory: $fullpath\n";
101   - }
102   - while (($filename = readdir($dh)) !== false) {
103   - if (in_array($filename, $this->aIgnore)) { continue; }
104   - $subrelpath = sprintf('%s/%s', $path, $filename);
105   - if (substr($subrelpath, 0, 1) == '/') {
106   - $subrelpath = substr($subrelpath, 1);
107   - }
108   - $subfullpath = sprintf('%s/%s', $this->fsPath, $subrelpath);
109   - if (is_dir($subfullpath)) {
110   - $this->checkDirectory($subrelpath);
  143 + $storage =& KTStorageManagerUtil::getSingleton();
  144 + foreach($rows as $row)
  145 + {
  146 + $doc = Document::get($row['document_id'], $row['metadata_version_id']);
  147 +
  148 + if (PEAR::isError($doc))
  149 + {
  150 + $msg = $doc->getMessage();
  151 + $this->error($doc, "Error with document: {$msg}");
  152 + continue;
111 153 }
112   - if (is_file($subfullpath)) {
113   - $this->checkFile($subrelpath);
  154 + $this->doc = $doc;
  155 +
  156 + $tmpPath = $storage->temporaryFile($doc);
  157 + if (!file_exists($tmpPath))
  158 + {
  159 + $this->error("Temporary file could not be resolved: {$tmpPath}");
  160 + continue;
114 161 }
115   - }
116   - }
117 162  
118   - function checkFile($path, $first = true) {
119   - $oDocument = KTEntityUtil::getByDict('KTDocumentContentVersion', array(
120   - 'storage_path' => $path,
121   - ));
122   - if (is_a($oDocument, 'ktentitynoobjects')) {
123   - $this->aFilesToRemove[] = $path;
124   - return;
125   - }
126   - }
  163 + $expectedSize = $row['size'];
  164 + $currentSize = filesize($tmpPath);
  165 + if ($expectedSize != $currentSize)
  166 + {
  167 + $this->error("Filesize does not match. Expected: {$expectedSize} Current: {$currentSize}");
  168 + continue;
  169 + }
127 170  
128   - function checkRepoDocument($oDocument) {
129   - global $aRepoDocumentProblems;
130   - $aDCVs = KTDocumentContentVersion::getByDocument($oDocument);
131   - foreach ($aDCVs as $oDCV) {
132   - $sDocumentPath = $oDCV->getStoragePath();
133   - $sFullPath = sprintf('%s/%s', $this->fsPath, $sDocumentPath);
134   - if (!is_file($sFullPath)) {
135   - $this->aRepoDocumentProblems[] = array(
136   - 'document' => $oDocument,
137   - 'content' => $oDCV,
138   - 'path' => $sDocumentPath,
139   - 'doclink' => KTBrowseUtil::getUrlForDocument($oDocument),
140   - );
  171 + $expectedHash = $row['md5hash'];
  172 + $currentHash = md5_file($tmpPath);
  173 + if ($expectedHash != $currentHash)
  174 + {
  175 + $this->error("Hash does not match. Expected: {$expectedHash} Current: {$currentHash}");
  176 + continue;
141 177 }
  178 + $this->progress();
142 179 }
  180 +
  181 + print "{$this->nl}Done.{$this->nl}{$this->nl}";
143 182 }
  183 +
144 184 }
145   -$oDispatcher = new VerifyDispatcher;
146   -$oDispatcher->do_main();
  185 +
  186 +
  187 +$verification = new StorageVerification();
  188 +$verification->run();
147 189  
148 190 ?>
... ...