Summary: | kbuildsycoca can't recreate the ksycoca database after initial startup | ||
---|---|---|---|
Product: | [Frameworks and Libraries] kdelibs | Reporter: | devsk <funtoos> |
Component: | kded | Assignee: | Unassigned bugs mailing-list <unassigned-bugs> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | faure, lex.lists |
Priority: | NOR | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Compiled Sources | ||
OS: | Cygwin | ||
Latest Commit: | Version Fixed In: |
Description
devsk
2005-05-10 07:21:40 UTC
following comes from Ralf on kde-cygwin list, and its more detailed:
--------------------------------------------------------------------------------
all access to the ksycoca database is encapsulated by the class
KSycoca,
which contains a signal handler notifyDatabaseChanged(), wich closes
the
database. from kdecore/ksycoca.cpp
void KSycoca::notifyDatabaseChanged(const QStringList &changeList)
{
d->changeList = changeList;
//kdDebug(7011) << "got a notifyDatabaseChanged signal !" << endl;
// kded tells us the database file changed
// Close the database and forget all about what we knew
// The next call to any public method will recreate
// everything that's needed.
closeDatabase();
// Now notify applications
emit databaseChanged();
}
The relating signal is send after updating the database in
kbuildsycoca:kdemain():
if (args->isSet("signal"))
{
// Notify ALL applications that have a ksycoca object, using a
broadcast
QByteArray data;
QDataStream stream(data, IO_WriteOnly);
stream << *g_changeList;
dcopClient->send( "*", "ksycoca",
"notifyDatabaseChanged(QStringList)",
data );
}
The problem is that this signal is send to late. A workaround could be
to send
this signal immediatly before the call to KBuildSycoca::recreate() in
kbuildsycoca:kdemain()
KBuildSycoca *sycoca= new KBuildSycoca; // Build data base
if (args->isSet("track"))
sycoca->setTrackId(QString::fromLocal8Bit(args->getOption("track")));
>>>>>>>>>>>>>>>>>>>>
if (args->isSet("signal"))
{
// Notify ALL applications that have a ksycoca object, using a
broadcast
QByteArray data;
QDataStream stream(data, IO_WriteOnly);
stream << *g_changeList;
dcopClient->send( "*", "ksycoca",
"notifyDatabaseChanged(QStringList)",
data );
}
<<<<<<<<<<<<<<<<<<<
if (!sycoca->recreate()) {
but I don't do if this works in any cases.
A generic approach is to introduce a new signal for example
notifyDatabaseUpdatePending or so, which could close and lock any
unwanted
access to the database until the notifyDatabaseChanged is send. If the
workaround doesn't work we can implemented this.
-------------------------------------------------------------------------------
notifyDatabaseUpdatePending would need to call all clients one-by-one and wait for each call to return. Even then it's still not guaranteed to work. Whatever solution you come up with, please do not change the behavior under unix. what is the right solution in your mind then? > notifyDatabaseUpdatePending would need to call all clients one-by-one and wait for each call to return. This could be done by using the synchronous call() method instead of the asynchronous send(). Unfortunally call() could not send the messages to all related applications instead The applications has to be enumerated. Currently I don't know which dcop function could be used. Any hints ? >Even then it's still not guaranteed to work. Why You can use DCOPClient::registeredApplications() to get a list of all apps.
> >Even then it's still not guaranteed to work.
> Why
A new application can start in the mean time and open the database.
> A new application can start in the mean time and open the database.
I don't thoughed about
What about if kbuildsycoca would update the database, rename it to a new (unused) name, store the name in a configfile and send all related applications the new name for updating their database ?
I saw that the name is currently hardcoded in from kdecore/ksycoca.cpp
-- path = KGlobal::dirs()->saveLocation("cache") + "ksycoca";
For the record: One problem is that kio_xxx processes does not have a dcop instance and does not handle dcop signals, so they don't got any notice about the ksycoca database change :-(. > they don't got any notice about the ksycoca database change
One question: is this a feature or a whole in the design ?
this is what I did temporarily. Basically, close the database in all before recreate and execute normally. hopefully recreate() takes long enough before issuing rename() that existing apps can close() and but short enough that no other application comes along to open the database. This doesn't solve the problem in all corner cases. ------------------------------------------------------------- $ diff -u kdecore/ksycoca.kidl.orig kdecore/ksycoca.kidl --- kdecore/ksycoca.kidl.orig 2005-05-14 15:48:22.000000000 -0700 +++ kdecore/ksycoca.kidl 2005-05-14 15:59:08.000000000 -0700 @@ -12,6 +12,10 @@ <SUPER>DCOPObject</SUPER> <FUNC> <TYPE>void</TYPE> + <NAME>closeDatabase</NAME> + </FUNC> + <FUNC> + <TYPE>void</TYPE> <NAME>notifyDatabaseChanged</NAME> <ARG><TYPE qleft="const" qright="&">QStringList</TYPE></ARG> </FUNC> $ diff -u kded/kbuildsycoca.cpp.orig kded/kbuildsycoca.cpp --- kded/kbuildsycoca.cpp.orig 2005-05-14 15:34:28.000000000 -0700 +++ kded/kbuildsycoca.cpp 2005-05-14 16:02:20.000000000 -0700 @@ -908,6 +908,13 @@ KBuildSycoca *sycoca= new KBuildSycoca; // Build data base if (args->isSet("track")) sycoca->setTrackId(QString::fromLocal8Bit(args->getOption("track"))); + + if (args->isSet("signal")) + { + // Notify ALL applications that have a ksycoca object, using a broadcast + dcopClient->send( "*", "ksycoca", "closeDatabase()", ""); + } + if (!sycoca->recreate()) { #ifdef KBUILDSYCOCA_GUI if (!silent || showprogress) ------------------------------------ Still relevant to recent KDE version? If not please close the bug. Thanks, Lex. ksycoca uses shared memory on Windows these days, this problem is long gone. |