168 lines
5.0 KiB
Diff
168 lines
5.0 KiB
Diff
|
--- kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/17 02:34:11 1104230
|
||
|
+++ kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/17 02:38:08 1104231
|
||
|
@@ -40,6 +40,7 @@
|
||
|
#include <kstandarddirs.h>
|
||
|
#include <kdebug.h>
|
||
|
#include <klockfile.h>
|
||
|
+#include <ksavefile.h>
|
||
|
#include <ksvgrenderer.h>
|
||
|
#include <kdefakes.h>
|
||
|
|
||
|
@@ -633,6 +634,10 @@
|
||
|
qint32 leftchild, rightchild;
|
||
|
stream >> fkey >> foffset >> timesused >> lastused >> leftchild >> rightchild;
|
||
|
|
||
|
+ if (fkey.isEmpty()) {
|
||
|
+ return start;
|
||
|
+ }
|
||
|
+
|
||
|
if (key < fkey) {
|
||
|
if (leftchild) {
|
||
|
return binarySearchKey(stream, key, leftchild);
|
||
|
@@ -660,12 +665,21 @@
|
||
|
// exist yet and there are no entries. Otherwise, do a binary search
|
||
|
// starting from the root node.
|
||
|
if (!stream.atEnd()) {
|
||
|
+ // One exception is that the root node may exist but be invalid,
|
||
|
+ // which can happen when the cache data is discarded. This is
|
||
|
+ // represented by an empty fkey
|
||
|
+ QString fkey;
|
||
|
+ stream >> fkey;
|
||
|
+
|
||
|
+ if (fkey.isEmpty()) {
|
||
|
+ delete device;
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+
|
||
|
int nodeoffset = binarySearchKey(stream, key, mIndexRootOffset);
|
||
|
|
||
|
// Load the found entry and check if it's the one we're looking for.
|
||
|
device->seek(nodeoffset);
|
||
|
- QString fkey;
|
||
|
- stream >> fkey;
|
||
|
if (fkey == key) {
|
||
|
// Read offset and statistics
|
||
|
qint32 foffset;
|
||
|
@@ -814,7 +828,9 @@
|
||
|
QString fkey;
|
||
|
stream.device()->seek(parentoffset);
|
||
|
stream >> fkey;
|
||
|
- if (key == fkey) {
|
||
|
+
|
||
|
+ // The key would be empty if the cache had been discarded.
|
||
|
+ if (key == fkey || fkey.isEmpty()) {
|
||
|
// We're overwriting an existing entry
|
||
|
offset = parentoffset;
|
||
|
}
|
||
|
@@ -1195,16 +1211,14 @@
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
- d->invalidateMmapFiles();
|
||
|
- d->unmmapFiles();
|
||
|
-
|
||
|
- d->mEnabled = false;
|
||
|
-
|
||
|
KPCLockFile lock(d->mLockFileName);
|
||
|
// Hope we got the lock...
|
||
|
|
||
|
+ d->invalidateMmapFiles();
|
||
|
+ d->mEnabled = false;
|
||
|
+
|
||
|
// Create index file
|
||
|
- QFile indexfile(d->mIndexFile);
|
||
|
+ KSaveFile indexfile(d->mIndexFile);
|
||
|
if (!indexfile.open(QIODevice::WriteOnly)) {
|
||
|
kError() << "Couldn't create index file" << d->mIndexFile;
|
||
|
return false;
|
||
|
@@ -1212,7 +1226,7 @@
|
||
|
|
||
|
d->mCacheId = ::time(0);
|
||
|
d->mTimestamp = ::time(0);
|
||
|
-
|
||
|
+
|
||
|
// We can't know the full size until custom headers written.
|
||
|
// mmapFiles() will take care of correcting the size.
|
||
|
KPixmapCacheIndexHeader indexHeader = { {0}, KPIXMAPCACHE_VERSION, 0, d->mCacheId, d->mTimestamp };
|
||
|
@@ -1221,7 +1235,7 @@
|
||
|
indexfile.write(reinterpret_cast<char*>(&indexHeader), sizeof indexHeader);
|
||
|
|
||
|
// Create data file
|
||
|
- QFile datafile(d->mDataFile);
|
||
|
+ KSaveFile datafile(d->mDataFile);
|
||
|
if (!datafile.open(QIODevice::WriteOnly)) {
|
||
|
kError() << "Couldn't create data file" << d->mDataFile;
|
||
|
return false;
|
||
|
@@ -1243,40 +1257,54 @@
|
||
|
// Close the files and mmap them (if mmapping is used)
|
||
|
indexfile.close();
|
||
|
datafile.close();
|
||
|
+ indexfile.finalize();
|
||
|
+ datafile.finalize();
|
||
|
+
|
||
|
d->mEnabled = true;
|
||
|
d->mmapFiles();
|
||
|
+
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void KPixmapCache::deleteCache(const QString& name)
|
||
|
{
|
||
|
- foreach (KPixmapCache::Private *d, Private::mCaches) {
|
||
|
- if (d->mName == name && d->mInited) {
|
||
|
- d->q->discard();
|
||
|
- }
|
||
|
- }
|
||
|
+ QString indexFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + name + ".index");
|
||
|
+ QString dataFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + name + ".data");
|
||
|
+
|
||
|
+ QFile::remove(indexFile);
|
||
|
+ QFile::remove(dataFile);
|
||
|
}
|
||
|
|
||
|
void KPixmapCache::discard()
|
||
|
{
|
||
|
- d->invalidateMmapFiles();
|
||
|
- d->unmmapFiles();
|
||
|
- d->mInited = false;
|
||
|
+ // To "discard" the cache we simply have to make sure that every that
|
||
|
+ // was in there before is no longer present when we search for them.
|
||
|
+ // Easiest way to do *that* is to simply delete the index.
|
||
|
+
|
||
|
+ KPCLockFile lock(d->mLockFileName);
|
||
|
+ if(!lock.isValid()) {
|
||
|
+ kError(264) << "Unable to lock pixmap cache when trying to discard it";
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ QIODevice *device = d->indexDevice();
|
||
|
+ if (!device) {
|
||
|
+ kError(264) << "Unable to access index when trying to discard cache";
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ device->seek(d->mIndexRootOffset);
|
||
|
+ QDataStream stream(device);
|
||
|
+
|
||
|
+ // Stream an empty QString as the hash key to signify that the cache
|
||
|
+ // has been discarded.
|
||
|
+ stream << QString();
|
||
|
|
||
|
if (d->mUseQPixmapCache) {
|
||
|
// TODO: This is broken, it removes every cached QPixmap in the whole
|
||
|
// process, not just this KPixmapCache.
|
||
|
QPixmapCache::clear();
|
||
|
}
|
||
|
-
|
||
|
- QString indexFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + d->mName + ".index");
|
||
|
- QString dataFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + d->mName + ".data");
|
||
|
-
|
||
|
- QFile::remove(indexFile);
|
||
|
- QFile::remove(dataFile);
|
||
|
-
|
||
|
- // No need to remove the lockfile
|
||
|
- d->init();
|
||
|
}
|
||
|
|
||
|
void KPixmapCache::removeEntries(int newsize)
|