kdelibs/kdelibs-4.4.2-kpixmapcache....

169 lines
5.1 KiB
Diff

--- branches/KDE/4.4/kdelibs/kdeui/util/kpixmapcache.cpp 2010/01/24 02:37:20 1079318
+++ branches/KDE/4.4/kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/25 02:24:54 1107210
@@ -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,23 @@
// 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 +830,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 +1213,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 +1228,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 +1237,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 +1259,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)