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 <?php 1 <?php
2 /** 2 /**
3 * $Id$ 3 * $Id$
4 - * 4 + *
5 * KnowledgeTree Community Edition 5 * KnowledgeTree Community Edition
6 * Document Management Made Simple 6 * Document Management Made Simple
7 * Copyright (C) 2008 KnowledgeTree Inc. 7 * Copyright (C) 2008 KnowledgeTree Inc.
8 * Portions copyright The Jam Warehouse Software (Pty) Limited 8 * Portions copyright The Jam Warehouse Software (Pty) Limited
9 - * 9 + *
10 * This program is free software; you can redistribute it and/or modify it under 10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License version 3 as published by the 11 * the terms of the GNU General Public License version 3 as published by the
12 * Free Software Foundation. 12 * Free Software Foundation.
13 - * 13 + *
14 * This program is distributed in the hope that it will be useful, but WITHOUT 14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details. 17 * details.
18 - * 18 + *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 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 * California 94120-7775, or email info@knowledgetree.com. 23 * California 94120-7775, or email info@knowledgetree.com.
24 - * 24 + *
25 * The interactive user interfaces in modified source and object code versions 25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under 26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU General Public License version 3. 27 * Section 5 of the GNU General Public License version 3.
28 - * 28 + *
29 * In accordance with Section 7(b) of the GNU General Public License version 3, 29 * In accordance with Section 7(b) of the GNU General Public License version 3,
30 * these Appropriate Legal Notices must retain the display of the "Powered by 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 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices 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 * copyright notice. 34 * copyright notice.
35 * Contributor( s): ______________________________________ 35 * Contributor( s): ______________________________________
36 */ 36 */
37 37
38 require_once(dirname(__FILE__) . '/../config/dmsDefaults.php'); 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 ?>