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