[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: KDE/kdelibs/kded
From: David Faure <faure () kde ! org>
Date: 2010-11-26 0:04:20
Message-ID: 20101126000420.1E411AC8A2 () svn ! kde ! org
[Download RAW message or body]
SVN commit 1200847 by dfaure:
Fix two bugs that were compensating each other in the unittest here:
1) kbuildsycoca would not emit databaseChanged("...") for resources where desktop \
files had been deleted 2) a name clash ("screensaver.desktop" in both servicetypes \
and services) made kbuildsycoca4 always emit databaseChanged("services")
And of course the unittest was for "deleting a desktop file in the services resource" \
so it was passing by pure chance (and not on Volker's machine which didn't have both \
desktop files).
Fixed 2) by using resource+path as the key in that dict rather than just path.
and fixed 1) by looking at g_ctimeDict at the end, to see which resources are still \
there (which needed the fix for 2 in the first place)
The fix for 1) uncovers a new bug though: databaseChanged("apps") is always emitted, \
so we never go into the fast path of "no need to save to disk"; I'll look at this \
tomorrow.
M +37 -22 kbuildsycoca.cpp
M +3 -0 kbuildsycoca.h
M +75 -39 kctimefactory.cpp
M +29 -9 kctimefactory.h
--- trunk/KDE/kdelibs/kded/kbuildsycoca.cpp #1200846:1200847
@@ -71,13 +71,12 @@
static KBuildServiceFactory *g_serviceFactory = 0;
static KBuildServiceGroupFactory *g_buildServiceGroupFactory = 0;
static KSycocaFactory *g_currentFactory = 0;
-static KCTimeInfo *g_ctimeInfo = 0;
-static QHash<QString, quint32> *g_ctimeDict = 0;
+static KCTimeInfo *g_ctimeInfo = 0; // factory
+static KCTimeDict *g_ctimeDict = 0; // old timestamps
static QByteArray g_resource = 0;
static KBSEntryDict *g_currentEntryDict = 0;
static KBSEntryDict *g_serviceGroupEntryDict = 0;
-static KSycocaEntryListList *g_allEntries = 0;
-static QStringList *g_changeList = 0;
+static KSycocaEntryListList *g_allEntries = 0; // entries from existing ksycoca
static QStringList *g_allResourceDirs = 0;
static bool g_changed = false;
static KSycocaEntry::List g_tempStorage;
@@ -113,7 +112,7 @@
KSycocaEntry::Ptr KBuildSycoca::createEntry(const QString &file, bool addToFactory)
{
- quint32 timeStamp = g_ctimeInfo->ctime(file);
+ quint32 timeStamp = g_ctimeInfo->dict()->ctime(file, g_resource);
if (!timeStamp)
{
timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, file,
@@ -123,7 +122,7 @@
if (g_allEntries)
{
assert(g_ctimeDict);
- quint32 oldTimestamp = g_ctimeDict->value( file, 0 );
+ quint32 oldTimestamp = g_ctimeDict->ctime(file, g_resource);
if (timeStamp && (timeStamp == oldTimestamp))
{
@@ -137,20 +136,23 @@
// remove from g_ctimeDict; if g_ctimeDict is not empty
// after all files have been processed, it means
// some files were removed since last time
- g_ctimeDict->remove( file );
+ if (file.contains("fake"))
+ kDebug(7021) << g_resource << "reusing (and removing) old entry \
[\"fake\"] for:" << file; + g_ctimeDict->remove(file, g_resource);
}
else if (oldTimestamp)
{
g_changed = true;
- kDebug(7021) << "modified:" << file;
+ g_ctimeDict->remove(file, g_resource);
+ kDebug(7021) << "modified:" << file << "in" << g_resource.constData();
}
else
{
g_changed = true;
- kDebug(7021) << "new:" << file;
+ kDebug(7021) << "new:" << file << "in" << g_resource.constData();
}
}
- g_ctimeInfo->addCTime(file, timeStamp );
+ g_ctimeInfo->dict()->addCTime(file, g_resource, timeStamp);
if (!entry)
{
// Create a new entry
@@ -173,7 +175,7 @@
return KService::Ptr::staticCast(entry);
}
-// returns false if the database is up to date
+// returns false if the database is up to date, true if it needs to be saved
bool KBuildSycoca::build()
{
typedef QLinkedList<KBSEntryDict *> KBSEntryDictList;
@@ -280,12 +282,24 @@
if (g_changed || !g_allEntries)
{
uptodate = false;
- g_changeList->append(g_resource);
+ //kDebug() << "CHANGED:" << g_resource;
+ m_changedResources.append(g_resource);
}
}
bool result = !uptodate || (g_ctimeDict && !g_ctimeDict->isEmpty());
+ if (g_ctimeDict && !g_ctimeDict->isEmpty()) {
+ //kDebug() << "Still in time dict:";
+ //g_ctimeDict->dump();
+ // ## It seems entries filtered out by vfolder are still in there,
+ // so we end up always saving ksycoca, i.e. this method never returns false
+ // Get the list of resources from which some files were deleted
+ const QStringList resources = g_ctimeDict->resourceList();
+ kDebug() << "Still in the time dict (i.e. deleted files)" << resources;
+ m_changedResources += resources;
+ }
+
if (result || bMenuTest)
{
g_resource = "apps";
@@ -309,7 +323,8 @@
if (g_changed || !g_allEntries)
{
uptodate = false;
- g_changeList->append(g_resource);
+ //kDebug() << "CHANGED:" << g_resource;
+ m_changedResources.append(g_resource);
}
if (bMenuTest) {
result = false;
@@ -331,7 +346,7 @@
QString directoryFile = subMenu->directoryFile;
if (directoryFile.isEmpty())
directoryFile = subName+".directory";
- quint32 timeStamp = g_ctimeInfo->ctime(directoryFile);
+ quint32 timeStamp = g_ctimeInfo->dict()->ctime(directoryFile, g_resource);
if (!timeStamp) {
timeStamp = KGlobal::dirs()->calcResourceHash( g_resource, directoryFile,
KStandardDirs::Recursive );
@@ -340,7 +355,7 @@
KServiceGroup::Ptr entry;
if (g_allEntries)
{
- quint32 oldTimestamp = g_ctimeDict->value( directoryFile, 0 );
+ const quint32 oldTimestamp = g_ctimeDict->ctime(directoryFile, g_resource);
if (timeStamp && (timeStamp == oldTimestamp))
{
@@ -353,7 +368,7 @@
}
}
}
- g_ctimeInfo->addCTime(directoryFile, timeStamp);
+ g_ctimeInfo->dict()->addCTime(directoryFile, g_resource, timeStamp);
entry = g_buildServiceGroupFactory->addNew(subName, subMenu->directoryFile, \
entry, subMenu->isDeleted); entry->setLayoutInfo(subMenu->layoutList);
@@ -701,8 +716,6 @@
}
}
- g_changeList = new QStringList;
-
bool checkstamps = incremental && args->isSet("checkstamps") && checkfiles;
quint32 filestamp = 0;
QStringList oldresourcedirs;
@@ -744,6 +757,7 @@
}
newTimestamp = (quint32) time(0);
+ QStringList changedResources;
if( checkfiles && ( !checkstamps || !KBuildSycoca::checkTimestamps( filestamp, \
oldresourcedirs ))) {
@@ -758,7 +772,7 @@
KSycoca::self();
KSycocaFactoryList *factories = new KSycocaFactoryList;
g_allEntries = new KSycocaEntryListList;
- g_ctimeDict = new QHash<QString, quint32>;
+ g_ctimeDict = new KCTimeDict;
// Must be in same order as in KBuildSycoca::recreate()!
factories->append( new KServiceTypeFactory );
@@ -776,7 +790,7 @@
}
delete factories; factories = 0;
KCTimeInfo *ctimeInfo = new KCTimeInfo;
- ctimeInfo->fillCTimeDict(*g_ctimeDict);
+ *g_ctimeDict = ctimeInfo->loadDict();
}
cSycocaPath = 0;
@@ -786,6 +800,7 @@
if (!sycoca->recreate()) {
return -1;
}
+ changedResources = sycoca->changedResources();
if (bGlobalDatabase)
{
@@ -802,10 +817,10 @@
{
// Notify ALL applications that have a ksycoca object, using a signal
QDBusMessage signal = QDBusMessage::createSignal("/", "org.kde.KSycoca", \
"notifyDatabaseChanged" );
- signal << *g_changeList;
+ signal << changedResources;
if (QDBusConnection::sessionBus().isConnected()) {
- kDebug() << "Emitting notifyDatabaseChanged" << *g_changeList;
+ kDebug() << "Emitting notifyDatabaseChanged" << changedResources;
QDBusConnection::sessionBus().send(signal);
qApp->processEvents(); // make sure the dbus signal is sent before we quit.
}
--- trunk/KDE/kdelibs/kded/kbuildsycoca.h #1200846:1200847
@@ -54,6 +54,8 @@
void setTrackId(const QString &id) { m_trackId = id; }
+ QStringList changedResources() const { return m_changedResources; }
+
// Use our friendly-access-to-KSycoca to make this public
static void clearCaches() { KSycoca::clearCaches(); }
@@ -98,6 +100,7 @@
*/
virtual bool isBuilding() { return true; }
+ QStringList m_changedResources;
QStringList m_allResourceDirs;
QString m_trackId;
};
--- trunk/KDE/kdelibs/kded/kctimefactory.cpp #1200846:1200847
@@ -17,13 +17,78 @@
**/
#include "kctimefactory.h"
-#include "ksycoca.h"
-#include "ksycocatype.h"
+#include <ksycoca.h>
+#include <ksycocatype.h>
+#include <kdebug.h>
#include <assert.h>
+static inline QString key(const QString &path, const QByteArray& resource)
+{
+ return QString::fromLatin1(resource) + QLatin1Char('|') + path;
+}
+
+void KCTimeDict::addCTime(const QString &path, const QByteArray& resource, quint32 \
ctime) +{
+ assert(!path.isEmpty());
+ m_hash.insert(key(path, resource), ctime );
+}
+
+quint32 KCTimeDict::ctime(const QString &path, const QByteArray& resource) const
+{
+ return m_hash.value(key(path, resource), 0);
+}
+
+void KCTimeDict::remove(const QString &path, const QByteArray &resource)
+{
+ m_hash.remove(key(path, resource));
+}
+
+void KCTimeDict::dump() const
+{
+ kDebug() << m_hash.keys();
+}
+
+QStringList KCTimeDict::resourceList() const
+{
+ QSet<QString> resources;
+ Hash::const_iterator it = m_hash.constBegin();
+ const Hash::const_iterator end = m_hash.constEnd();
+ for ( ; it != end; ++it ) {
+ const QString key = it.key();
+ const QString res = key.left(key.indexOf('|'));
+ resources.insert(res);
+ }
+ return resources.toList();
+}
+
+void KCTimeDict::load(QDataStream &str)
+{
+ QString key;
+ quint32 ctime;
+ while(true)
+ {
+ KSycocaEntry::read(str, key);
+ str >> ctime;
+ if (key.isEmpty()) break;
+ m_hash.insert(key, ctime);
+ }
+}
+
+void KCTimeDict::save(QDataStream &str) const
+{
+ Hash::const_iterator it = m_hash.constBegin();
+ const Hash::const_iterator end = m_hash.constEnd();
+ for ( ; it != end; ++it ) {
+ str << it.key() << it.value();
+ }
+ str << QString() << (quint32) 0;
+}
+
+///////////
+
KCTimeInfo::KCTimeInfo()
- : KSycocaFactory( KST_CTimeInfo ), ctimeDict()
+ : KSycocaFactory( KST_CTimeInfo ), m_ctimeDict()
{
if (!KSycoca::self()->isBuilding()) {
QDataStream* str = stream();
@@ -45,52 +110,23 @@
str << m_dictOffset;
}
-void
-KCTimeInfo::save(QDataStream &str)
+void KCTimeInfo::save(QDataStream &str)
{
KSycocaFactory::save(str);
m_dictOffset = str.device()->pos();
- Dict::const_iterator it = ctimeDict.constBegin();
- const Dict::const_iterator end = ctimeDict.constEnd();
- for ( ; it != end; ++it )
- {
- str << it.key() << it.value();
- }
- str << QString() << (quint32) 0;
-
- int endOfFactoryData = str.device()->pos();
-
+ m_ctimeDict.save(str);
+ const int endOfFactoryData = str.device()->pos();
saveHeader(str);
str.device()->seek(endOfFactoryData);
}
-void
-KCTimeInfo::addCTime(const QString &path, quint32 ctime)
+KCTimeDict KCTimeInfo::loadDict() const
{
- assert(!path.isEmpty());
- ctimeDict.insert(path, ctime);
-}
-
-quint32
-KCTimeInfo::ctime(const QString &path)
-{
- return ctimeDict.value( path, 0 );
-}
-
-void
-KCTimeInfo::fillCTimeDict(Dict &dict)
-{
+ KCTimeDict dict;
QDataStream* str = stream();
assert(str);
str->device()->seek(m_dictOffset);
- QString path;
- quint32 ctime;
- while(true)
- {
- KSycocaEntry::read(*str, path);
- (*str) >> ctime;
- if (path.isEmpty()) break;
- dict.insert(path, ctime);
+ dict.load(*str);
+ return dict;
}
-}
--- trunk/KDE/kdelibs/kded/kctimefactory.h #1200846:1200847
@@ -23,10 +23,30 @@
#include <QtCore/QHash>
/**
- * Service group factory for building ksycoca
+ * Simple dict for assocating a timestamp with each file in ksycoca
+ */
+class KCTimeDict
+{
+public:
+ void addCTime(const QString &path, const QByteArray& resource, quint32 ctime);
+ quint32 ctime(const QString &path, const QByteArray& resource) const;
+ void remove(const QString &path, const QByteArray& resource);
+ void dump() const;
+ bool isEmpty() const { return m_hash.isEmpty(); }
+ QStringList resourceList() const;
+
+ void load(QDataStream &str);
+ void save(QDataStream &str) const;
+private:
+ typedef QHash<QString, quint32> Hash;
+ Hash m_hash;
+};
+
+/**
+ * Internal factory for storing the timestamp of each file in ksycoca
* @internal
*/
-class KCTimeInfo : public KSycocaFactory
+class KCTimeInfo : public KSycocaFactory // TODO rename to KCTimeFactory
{
K_SYCOCAFACTORY( KST_CTimeInfo )
public:
@@ -50,15 +70,15 @@
KSycocaEntry * createEntry(const QString &, const char *) const { return 0; }
KSycocaEntry * createEntry(int) const { return 0; }
- void addCTime(const QString &path, quint32 ctime);
+ // Loads the dict and returns it; does not set m_ctimeDict;
+ // this is only used in incremental mode for loading the old timestamps.
+ KCTimeDict loadDict() const;
- quint32 ctime(const QString &path);
+ // The API for inserting/looking up entries is in KCTimeDict.
+ KCTimeDict* dict() { return &m_ctimeDict; }
- typedef QHash<QString, quint32> Dict;
- void fillCTimeDict(Dict &dict);
-
-protected:
- Dict ctimeDict;
+private:
+ KCTimeDict m_ctimeDict;
int m_dictOffset;
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic