1 /* 2 * filecache.h - File storage with age and size control 3 * Copyright (C) 2010 Rion 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 */ 20 21 #ifndef FILECACHE_H 22 #define FILECACHE_H 23 24 #include <QObject> 25 #include <QDateTime> 26 #include <QFile> 27 #include <QHash> 28 #include <QVariantMap> 29 30 class QTimer; 31 class OptionsTree; 32 class FileCache; 33 34 class FileCacheItem : public QObject 35 { 36 Q_OBJECT 37 public: 38 enum Flags { 39 OnDisk = 0x1, 40 Registered = 0x2, 41 SessionUndeletable = 0x4 // The item is undeletable by expiration or cache size limits during this session 42 //Unloadable = 0x8 // another good idea 43 }; 44 45 FileCacheItem(FileCache *parent, const QString &itemId, const QVariantMap &metadata, 46 const QDateTime &dt, unsigned int maxAge, unsigned int size, 47 const QByteArray &data = QByteArray()); 48 49 void flushToDisk(); // put data to disk, but not to registry. don't call this directly. FileCache will care about it. 50 bool remove() const; // remove file from disk but not from registry. don't call this directly. 51 void unload(); // drop file to disk, deallocate memory 52 inline bool inMemory() const; isOnDisk()53 inline bool isOnDisk() const { return _flags & OnDisk; } // data is on disk and not in rgistry isRegistered()54 inline bool isRegistered() const { return _flags & Registered; } // data is on disk and not in rgistry 55 bool isExpired(bool finishSession = false) const; parentCache()56 inline FileCache *parentCache() const { return (FileCache *)parent(); } id()57 inline QString id() const { return _id; } metadata()58 inline QVariantMap metadata() const { return _metadata; } setMetadata(const QVariantMap & md)59 inline void setMetadata(const QVariantMap &md) { _metadata = md; _flags &= ~Registered; } // we have to update registry eventually created()60 inline QDateTime created() const { return _ctime; } reborn()61 inline void reborn() { _ctime = QDateTime::currentDateTime(); } maxAge()62 inline unsigned int maxAge() const { return _maxAge; } size()63 inline unsigned int size() const { return _size; } 64 QByteArray data(); fileName()65 inline QString fileName() const { return _fileName; } hash()66 inline QString hash() const { return _hash; } // it's a hash from 'id'. so you can have string for id. the hash will be used for filename 67 68 inline void setSessionUndeletable(bool state = true) { if (state) _flags |= SessionUndeletable; else _flags &= ~SessionUndeletable; } 69 void setUndeletable(bool state = true); // survives restarts 70 inline bool isDeletable() const; 71 72 private: 73 friend class FileCache; 74 75 QString _id; 76 QVariantMap _metadata; 77 QDateTime _ctime; 78 unsigned int _maxAge; 79 unsigned int _size; 80 QByteArray _data; 81 82 quint16 _flags; 83 QString _fileName; 84 QString _hash; 85 }; 86 87 class FileCache : public QObject 88 { 89 Q_OBJECT 90 public: 91 static const unsigned int Session = 0; //remove data when application exits 92 static const unsigned int Forever = -1; //never remove 93 94 static const unsigned int DefaultMemoryCacheSize = 1*1024*1024; //1 Mb 95 static const unsigned int DefaultFileCacheSize = 50*1024*1024; //50 Mb 96 97 enum SyncPolicy { 98 InstantFLush, // always flush all data to disk (keeps copy in memory if fit) 99 FlushOverflow // flush to disk only when memory cache limit is exceeded 100 }; 101 102 FileCache(const QString &cacheDir, QObject *parent = 0); 103 ~FileCache(); 104 105 void gc(); 106 cacheDir()107 inline QString cacheDir() const { return _cacheDir; } 108 setMemoryCacheSize(unsigned int size)109 inline void setMemoryCacheSize(unsigned int size) 110 { _memoryCacheSize = size; } memoryCacheSize()111 inline unsigned int memoryCacheSize() const { return _memoryCacheSize; } 112 setFileCacheSize(unsigned int size)113 inline void setFileCacheSize(unsigned int size) { _fileCacheSize = size; } fileCacheSize()114 inline unsigned int fileCacheSize() const { return _fileCacheSize; } 115 setDefaultMaxAge(unsigned int maxAge)116 inline void setDefaultMaxAge(unsigned int maxAge) 117 { _defaultMaxAge = maxAge; } defaultMaxAge()118 inline unsigned int defaultMaxAge() const { return _defaultMaxAge; } 119 setSyncPolicy(SyncPolicy sp)120 inline void setSyncPolicy(SyncPolicy sp) { _syncPolicy = sp; } syncPolicy()121 inline SyncPolicy syncPolicy() const { return _syncPolicy; } 122 123 /** 124 * @brief Add data to cache 125 * @param id unique id (e.g. sha1 of data) 126 * @param type e.g. content-type 127 * @param data / if no data(size=0) memory size restiction won't affect this item, also no files will be created 128 * @param maxAge Session/Forever or just seconds to live 129 * @return a new cache item. Not yet synchronized to disk 130 */ 131 FileCacheItem *append(const QString &id, const QByteArray &data, 132 const QVariantMap &metadata = QVariantMap(), unsigned int maxAge = Forever); 133 void remove(const QString &id, bool needSync = true); 134 135 /** 136 * @brief get cache item metadata from cache (does not involve actual data loading) 137 * @param id uniqie id 138 * @param reborn - if more than half of the item age passed then set create-date to current 139 * @return 140 */ 141 FileCacheItem *get(const QString &id, bool reborn = false); 142 QByteArray getData(const QString &id, bool reborn = false); 143 void sync(bool finishSession); 144 145 protected: 146 /** 147 * @brief removeItem item from disk, shedules registry update as well if required. 148 * When called explicitly, removes even "Undeletable" items. 149 * @param item - item to delete 150 * @param needSync - shedule regitry update. 151 */ 152 virtual void removeItem(FileCacheItem *item, bool needSync); 153 154 public slots: 155 void sync(); 156 157 private: 158 void toRegistry(FileCacheItem *); 159 160 protected: 161 QHash<QString, FileCacheItem*> _items; 162 163 private: 164 QString _cacheDir; 165 unsigned int _memoryCacheSize; 166 unsigned int _fileCacheSize; 167 unsigned int _defaultMaxAge; 168 SyncPolicy _syncPolicy; 169 QTimer *_syncTimer; 170 OptionsTree *_registry; 171 QHash<QString, FileCacheItem*> _pendingRegisterItems; 172 173 bool _registryChanged; 174 }; 175 176 #endif //FILECACHE_H 177