comparison data/fileio/FileSource.cpp @ 469:a8a7b8f698c8

* Revert revisions 1244 and 1245 on FileSource -- backing out its built-in persistent cache support, as CachedFile now does the same thing and will do so more properly
author Chris Cannam
date Tue, 28 Oct 2008 11:07:08 +0000
parents 70b333085952
children dddd4ab77068
comparison
equal deleted inserted replaced
468:70b333085952 469:a8a7b8f698c8
22 #include <QHttp> 22 #include <QHttp>
23 #include <QFtp> 23 #include <QFtp>
24 #include <QFileInfo> 24 #include <QFileInfo>
25 #include <QDir> 25 #include <QDir>
26 #include <QCoreApplication> 26 #include <QCoreApplication>
27 #include <QCryptographicHash>
28 #include <QHttpResponseHeader> 27 #include <QHttpResponseHeader>
29 28
30 #include <iostream> 29 #include <iostream>
31 #include <cstdlib> 30 #include <cstdlib>
32 31
33 #define DEBUG_FILE_SOURCE 1 32 //#define DEBUG_FILE_SOURCE 1
34 33
35 int 34 int
36 FileSource::m_count = 0; 35 FileSource::m_count = 0;
37 36
38 QMutex 37 QMutex
45 FileSource::m_remoteLocalMap; 44 FileSource::m_remoteLocalMap;
46 45
47 QMutex 46 QMutex
48 FileSource::m_mapMutex; 47 FileSource::m_mapMutex;
49 48
50 FileSource::FileSource(QString fileOrUrl, ProgressReporter *reporter, 49 FileSource::FileSource(QString fileOrUrl, ProgressReporter *reporter) :
51 LocalCacheMode cacheMode) :
52 m_url(fileOrUrl), 50 m_url(fileOrUrl),
53 m_cacheMode(cacheMode),
54 m_ftp(0), 51 m_ftp(0),
55 m_http(0), 52 m_http(0),
56 m_localFile(0), 53 m_localFile(0),
57 m_ok(false), 54 m_ok(false),
58 m_lastStatus(0), 55 m_lastStatus(0),
67 std::cerr << "FileSource::FileSource: Persistent cache mode used for \"" << fileOrUrl.toStdString() << "\"" << std::endl; 64 std::cerr << "FileSource::FileSource: Persistent cache mode used for \"" << fileOrUrl.toStdString() << "\"" << std::endl;
68 exit(1); 65 exit(1);
69 } 66 }
70 67
71 #ifdef DEBUG_FILE_SOURCE 68 #ifdef DEBUG_FILE_SOURCE
72 std::cerr << "FileSource::FileSource(" << fileOrUrl.toStdString() << ", " << cacheMode << ")" << std::endl; 69 std::cerr << "FileSource::FileSource(" << fileOrUrl.toStdString() << ")" << std::endl;
73 #endif 70 #endif
74 71
75 if (!canHandleScheme(m_url)) { 72 if (!canHandleScheme(m_url)) {
76 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl; 73 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
77 m_errorString = tr("Unsupported scheme in URL"); 74 m_errorString = tr("Unsupported scheme in URL");
117 emit statusAvailable(); 114 emit statusAvailable();
118 emit ready(); 115 emit ready();
119 } 116 }
120 } 117 }
121 118
122 FileSource::FileSource(QUrl url, ProgressReporter *reporter, 119 FileSource::FileSource(QUrl url, ProgressReporter *reporter) :
123 LocalCacheMode cacheMode) :
124 m_url(url), 120 m_url(url),
125 m_cacheMode(cacheMode),
126 m_ftp(0), 121 m_ftp(0),
127 m_http(0), 122 m_http(0),
128 m_localFile(0), 123 m_localFile(0),
129 m_ok(false), 124 m_ok(false),
130 m_lastStatus(0), 125 m_lastStatus(0),
154 } 149 }
155 150
156 FileSource::FileSource(const FileSource &rf) : 151 FileSource::FileSource(const FileSource &rf) :
157 QObject(), 152 QObject(),
158 m_url(rf.m_url), 153 m_url(rf.m_url),
159 m_cacheMode(rf.m_cacheMode),
160 m_ftp(0), 154 m_ftp(0),
161 m_http(0), 155 m_http(0),
162 m_localFile(0), 156 m_localFile(0),
163 m_ok(rf.m_ok), 157 m_ok(rf.m_ok),
164 m_lastStatus(rf.m_lastStatus), 158 m_lastStatus(rf.m_lastStatus),
176 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl; 170 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
177 m_errorString = tr("Unsupported scheme in URL"); 171 m_errorString = tr("Unsupported scheme in URL");
178 return; 172 return;
179 } 173 }
180 174
181 if (m_cacheMode == PersistentCache) { 175 if (!isRemote()) {
182
183 m_localFilename = rf.m_localFilename; 176 m_localFilename = rf.m_localFilename;
184
185 } else if (!isRemote()) {
186
187 m_localFilename = rf.m_localFilename;
188
189 } else { 177 } else {
190 QMutexLocker locker(&m_mapMutex); 178 QMutexLocker locker(&m_mapMutex);
191 #ifdef DEBUG_FILE_SOURCE 179 #ifdef DEBUG_FILE_SOURCE
192 std::cerr << "FileSource::FileSource(copy ctor): ref count is " 180 std::cerr << "FileSource::FileSource(copy ctor): ref count is "
193 << m_refCountMap[m_url] << std::endl; 181 << m_refCountMap[m_url] << std::endl;
214 std::cerr << "FileSource(" << m_url.toString().toStdString() << ")::~FileSource" << std::endl; 202 std::cerr << "FileSource(" << m_url.toString().toStdString() << ")::~FileSource" << std::endl;
215 #endif 203 #endif
216 204
217 cleanup(); 205 cleanup();
218 206
219 if (isRemote() && (m_cacheMode == TemporaryCache) && !m_leaveLocalFile) { 207 if (isRemote() && !m_leaveLocalFile) deleteCacheFile();
220 deleteCacheFile();
221 }
222 } 208 }
223 209
224 void 210 void
225 FileSource::init() 211 FileSource::init()
226 { 212 {
262 return; 248 return;
263 } 249 }
264 250
265 if (createCacheFile()) { 251 if (createCacheFile()) {
266 #ifdef DEBUG_FILE_SOURCE 252 #ifdef DEBUG_FILE_SOURCE
267 std::cerr << "FileSource::init: Already have this one at " 253 std::cerr << "FileSource::init: Already have this one" << std::endl;
268 << m_localFilename.toStdString() << std::endl;
269 #endif 254 #endif
270 m_ok = true; 255 m_ok = true;
271 if (!QFileInfo(m_localFilename).exists()) { 256 if (!QFileInfo(m_localFilename).exists()) {
272 m_lastStatus = 404; 257 m_lastStatus = 404;
273 } else { 258 } else {
283 268
284 QString scheme = m_url.scheme().toLower(); 269 QString scheme = m_url.scheme().toLower();
285 270
286 #ifdef DEBUG_FILE_SOURCE 271 #ifdef DEBUG_FILE_SOURCE
287 std::cerr << "FileSource::init: Don't have local copy of \"" 272 std::cerr << "FileSource::init: Don't have local copy of \""
288 << m_url.toString().toStdString() << "\", retrieving to " 273 << m_url.toString().toStdString() << "\", retrieving" << std::endl;
289 << m_localFilename.toStdString() << std::endl;
290 #endif 274 #endif
291 275
292 if (scheme == "http") { 276 if (scheme == "http") {
293 initHttp(); 277 initHttp();
294 std::cerr << "FileSource: initHttp succeeded" << std::endl; 278 std::cerr << "FileSource: initHttp succeeded" << std::endl;
431 } 415 }
432 416
433 void 417 void
434 FileSource::cleanup() 418 FileSource::cleanup()
435 { 419 {
436 if (m_done) {
437 delete m_localFile; // does not actually delete the file
438 m_localFile = 0;
439 }
440 m_done = true; 420 m_done = true;
441 if (m_http) { 421 if (m_http) {
442 QHttp *h = m_http; 422 QHttp *h = m_http;
443 m_http = 0; 423 m_http = 0;
444 h->abort(); 424 h->abort();
448 QFtp *f = m_ftp; 428 QFtp *f = m_ftp;
449 m_ftp = 0; 429 m_ftp = 0;
450 f->abort(); 430 f->abort();
451 f->deleteLater(); 431 f->deleteLater();
452 } 432 }
453 if (m_localFile) { 433 delete m_localFile; // does not actually delete the file
454 delete m_localFile; // does not actually delete the file 434 m_localFile = 0;
455 m_localFile = 0;
456 }
457 } 435 }
458 436
459 bool 437 bool
460 FileSource::isRemote(QString fileOrUrl) 438 FileSource::isRemote(QString fileOrUrl)
461 { 439 {
676 } 654 }
677 } 655 }
678 656
679 if (error) { 657 if (error) {
680 #ifdef DEBUG_FILE_SOURCE 658 #ifdef DEBUG_FILE_SOURCE
681 std::cerr << "FileSource::done: error is " << error << " (\"" 659 std::cerr << "FileSource::done: error is " << error << ", deleting cache file" << std::endl;
682 << m_errorString.toStdString() << "\"), deleting cache file" << std::endl;
683 #endif 660 #endif
684 deleteCacheFile(); 661 deleteCacheFile();
685 } 662 }
686 663
687 m_ok = !error; 664 m_ok = !error;
726 } 703 }
727 } 704 }
728 705
729 m_fileCreationMutex.lock(); 706 m_fileCreationMutex.lock();
730 707
731 // We always delete the file here, even in PersistentCache mode,
732 // because this function is also used if retrieval failed (in
733 // which case we want to delete the cache so that subsequent users
734 // won't trust it). It's up to the calling code to determine
735 // whether we actually want to delete the cache or not, e.g. on
736 // destruction.
737
738 if (!QFile(m_localFilename).remove()) { 708 if (!QFile(m_localFilename).remove()) {
709 #ifdef DEBUG_FILE_SOURCE
739 std::cerr << "FileSource::deleteCacheFile: ERROR: Failed to delete file \"" << m_localFilename.toStdString() << "\"" << std::endl; 710 std::cerr << "FileSource::deleteCacheFile: ERROR: Failed to delete file \"" << m_localFilename.toStdString() << "\"" << std::endl;
711 #endif
740 } else { 712 } else {
741 #ifdef DEBUG_FILE_SOURCE 713 #ifdef DEBUG_FILE_SOURCE
742 std::cerr << "FileSource::deleteCacheFile: Deleted cache file \"" << m_localFilename.toStdString() << "\"" << std::endl; 714 std::cerr << "FileSource::deleteCacheFile: Deleted cache file \"" << m_localFilename.toStdString() << "\"" << std::endl;
743 #endif 715 #endif
744 m_localFilename = ""; 716 m_localFilename = "";
745 } 717 }
746 718
747 m_fileCreationMutex.unlock(); 719 m_fileCreationMutex.unlock();
748 720
749 m_done = true; 721 m_done = true;
750 }
751
752 QString
753 FileSource::getPersistentCacheDirectory()
754 {
755 QDir dir = TempDirectory::getInstance()->getContainingPath();
756
757 QString cacheDirName("cache");
758
759 QFileInfo fi(dir.filePath(cacheDirName));
760
761 if ((fi.exists() && !fi.isDir()) ||
762 (!fi.exists() && !dir.mkdir(cacheDirName))) {
763
764 throw DirectoryCreationFailed(fi.filePath());
765 }
766
767 return fi.filePath();
768 }
769
770 QString
771 FileSource::getPersistentCacheFilePath(QUrl url)
772 {
773 QDir dir(getPersistentCacheDirectory());
774
775 QString filename =
776 QString::fromLocal8Bit
777 (QCryptographicHash::hash(url.toString().toLocal8Bit(),
778 QCryptographicHash::Sha1).toHex());
779
780 return dir.filePath(filename);
781 } 722 }
782 723
783 bool 724 bool
784 FileSource::createCacheFile() 725 FileSource::createCacheFile()
785 { 726 {
786 if (m_cacheMode == PersistentCache) {
787 m_localFilename = getPersistentCacheFilePath(m_url);
788 if (QFileInfo(m_localFilename).exists()) return true;
789 else return false;
790 }
791
792 { 727 {
793 QMutexLocker locker(&m_mapMutex); 728 QMutexLocker locker(&m_mapMutex);
794 729
795 #ifdef DEBUG_FILE_SOURCE 730 #ifdef DEBUG_FILE_SOURCE
796 std::cerr << "FileSource::createCacheFile: refcount is " << m_refCountMap[m_url] << std::endl; 731 std::cerr << "FileSource::createCacheFile: refcount is " << m_refCountMap[m_url] << std::endl;