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