Mercurial > hg > svcore
comparison data/fileio/CachedFile.cpp @ 465:63b8ba45d953
* stub out persistent cacheing class, as I've decided I don't like the
way things were going with trying to incorporate all this logic into
the already too big FileSource class
author | Chris Cannam |
---|---|
date | Mon, 27 Oct 2008 11:53:35 +0000 |
parents | |
children | f35bfa88f0b5 |
comparison
equal
deleted
inserted
replaced
464:9525c9d7e54d | 465:63b8ba45d953 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2008 QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "CachedFile.h" | |
17 | |
18 #include "base/TempDirectory.h" | |
19 #include "base/ProgressReporter.h" | |
20 #include "base/Exceptions.h" | |
21 | |
22 #include <QFileInfo> | |
23 #include <QSettings> | |
24 #include <QVariant> | |
25 #include <QMap> | |
26 #include <QDir> | |
27 #include <QCryptographicHash> | |
28 | |
29 QString | |
30 CachedFile::getLocalFilenameFor(QUrl url) | |
31 { | |
32 QDir dir(getCacheDirectory()); | |
33 | |
34 QString filename = | |
35 QString::fromLocal8Bit | |
36 (QCryptographicHash::hash(url.toString().toLocal8Bit(), | |
37 QCryptographicHash::Sha1).toHex()); | |
38 | |
39 return dir.filePath(filename); | |
40 } | |
41 | |
42 QString | |
43 CachedFile::getCacheDirectory() | |
44 { | |
45 QDir dir = TempDirectory::getInstance()->getContainingPath(); | |
46 | |
47 QString cacheDirName("cache"); | |
48 | |
49 QFileInfo fi(dir.filePath(cacheDirName)); | |
50 | |
51 if ((fi.exists() && !fi.isDir()) || | |
52 (!fi.exists() && !dir.mkdir(cacheDirName))) { | |
53 | |
54 throw DirectoryCreationFailed(fi.filePath()); | |
55 } | |
56 | |
57 return fi.filePath(); | |
58 } | |
59 | |
60 CachedFile::CachedFile(QUrl url, ProgressReporter *reporter) : | |
61 m_url(url), | |
62 m_localFilename(getLocalFilenameFor(url)), | |
63 m_ok(false) | |
64 { | |
65 refresh(); | |
66 } | |
67 | |
68 bool | |
69 CachedFile::isOK() const | |
70 { | |
71 return m_ok; | |
72 } | |
73 | |
74 QString | |
75 CachedFile::getLocalFilename() const | |
76 { | |
77 return m_localFilename; | |
78 } | |
79 | |
80 void | |
81 CachedFile::refresh() | |
82 { | |
83 //!!! n.b. obvious race condition here if different CachedFile | |
84 // objects for same url used in more than one thread -- need to | |
85 // lock appropriately. also consider race condition between | |
86 // separate instances of the program | |
87 | |
88 if (!QFileInfo(m_localFilename).exists()) { | |
89 updateLastRetrieval(false); // empirically! | |
90 } | |
91 | |
92 QDateTime lastRetrieval = getLastRetrieval(); | |
93 | |
94 if (lastRetrieval.isValid()) { | |
95 // this will not be the case if the file is missing, after | |
96 // updateLastRetrieval(false) was called above | |
97 m_ok = true; | |
98 if (lastRetrieval.addDays(2) < QDateTime::currentDateTime()) { //!!! | |
99 // doesn't matter if retrieval fails -- we just don't | |
100 // update the last retrieval time | |
101 | |
102 //!!! but we do want an additional last-attempted | |
103 // timestamp so as to ensure we aren't retrying the | |
104 // retrieval every single time if it isn't working | |
105 | |
106 if (retrieve()) { | |
107 updateLastRetrieval(true); | |
108 } | |
109 } | |
110 } else { | |
111 // there is no acceptable file | |
112 if (retrieve()) { | |
113 m_ok = true; | |
114 updateLastRetrieval(true); | |
115 } else { | |
116 // again, we don't need to do anything here -- the last | |
117 // retrieval timestamp is already invalid | |
118 } | |
119 } | |
120 } | |
121 | |
122 bool | |
123 CachedFile::retrieve() | |
124 { | |
125 //!!! need to work by retrieving the file to another name, and | |
126 //!!! then "atomically" moving it to its proper place (I'm not | |
127 //!!! sure we can do an atomic move to replace an existing file | |
128 //!!! using Qt classes, but a plain delete then copy is probably | |
129 //!!! good enough) | |
130 | |
131 | |
132 | |
133 | |
134 } | |
135 | |
136 QDateTime | |
137 CachedFile::getLastRetrieval() | |
138 { | |
139 QSettings settings; | |
140 settings.beginGroup("FileCache"); | |
141 | |
142 QString key("last-retrieval-times"); | |
143 | |
144 QMap<QString, QVariant> timeMap = settings.value(key).toMap(); | |
145 QDateTime lastTime = timeMap[m_localFilename].toDateTime(); | |
146 | |
147 settings.endGroup(); | |
148 return lastTime; | |
149 } | |
150 | |
151 void | |
152 CachedFile::updateLastRetrieval(bool successful) | |
153 { | |
154 //!!! note !successful does not mean "we failed to update the | |
155 //!!! file" (and so it remains the same as before); it means "the | |
156 //!!! file is not there at all" | |
157 | |
158 QSettings settings; | |
159 settings.beginGroup("FileCache"); | |
160 | |
161 QString key("last-retrieval-times"); | |
162 | |
163 QMap<QString, QVariant> timeMap = settings.value(key).toMap(); | |
164 | |
165 QDateTime dt; | |
166 if (successful) dt = QDateTime::currentDateTime(); | |
167 | |
168 timeMap[m_localFilename] = dt; | |
169 settings.setValue(key, timeMap); | |
170 | |
171 settings.endGroup(); | |
172 } | |
173 | |
174 |