Mercurial > hg > svcore
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; |