Hello people,

as I told Sebastian earlier today, I discovered a severe bug in 
nepomukqueryservice. With telepathy-kde, I need to run several 
QueryServiceClient (at least two) at the same time. Note that the application 
has a single thread and every call to each qsc is asynchronous (I'm always 
using sparqlQuery()).

If I instantiate and start more than a QSC, the dbus service crashes all the 
time when calling Soprano::Client::ClientModel::executeQuery() and accessing 
the mutex which is inside it. This situation is always reproducible in a short 
time when instantiating at least 3 QSC.

To test some stuff, I created a workaround that I attached. I created a queue 
that starts a query at a time, waits for its listing to finish, and then 
starts the other queries in queue. This works perfectly for the first round, 
but queryservice always crashes afterwards when trying to pick up changes. 
Probably such a solution needs to be implemented right in queryservice, 
letting one query at a time hit soprano.

If you want to test this yourself, you can apply this merge request: 
http://reviewboard.kde.org/r/3650/ which also includes my "workaround"

-- 
-------------------

Dario Freddi
KDE Developer
GPG Key Signature: 511A9A3B
/*
 * This file is part of telepathy-contactslist-prototype
 *
 * Copyright (C) 2010 Collabora Ltd. <[email protected]>
 *   @Author Dario Freddi <[email protected]>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "nepomuk-query-query-pool.h"
#include <QHash>
#include <Nepomuk/Query/QueryServiceClient>
#include <QQueue>

namespace Nepomuk
{
namespace Query {

class QueryPool::Private {
    Q_DECLARE_PUBLIC(QueryPool)
    QueryPool * const q_ptr;
public:
    Private(QueryPool *parent) : q_ptr(parent), isRunning(false) {}
    virtual ~Private() {}

    QQueue< QueryServiceClient* > queue;
    QHash< QueryServiceClient*, QPair< QString, RequestPropertyMap > > queryData;
    QueryServiceClient *current;
    bool isRunning;

    void processNext();

    // Q_PRIVATE_SLOTS
    void __k__onListingFinished();
};

void QueryPool::Private::__k__onListingFinished()
{
    Q_Q(QueryPool);
    // Disconnect
    q->disconnect(current, SIGNAL(finishedListing()),
                  q, SLOT(__k__onListingFinished()));
    // Remove current from data
    queryData.remove(current);
    // No longer running
    isRunning = false;
    // Go next
    processNext();
}

void QueryPool::Private::processNext()
{
    // If it's running, pass by
    if (isRunning) {
        return;
    }

    // Get the current item, if any
    if (queue.isEmpty()) {
        return;
    }

    current = queue.dequeue();

    Q_Q(QueryPool);

    // Go
    isRunning = true;
    q->connect(current, SIGNAL(finishedListing()),
               q, SLOT(__k__onListingFinished()));
    current->sparqlQuery(queryData[current].first, queryData[current].second);
}

class QueryPoolHelper
{
public:
    QueryPoolHelper() : q(0) {}
    ~QueryPoolHelper() {
        delete q;
    }
    QueryPool *q;
};

K_GLOBAL_STATIC(QueryPoolHelper, s_globalQueryPool)

QueryPool *QueryPool::instance()
{
    if (!s_globalQueryPool->q) {
        new QueryPool;
    }

    return s_globalQueryPool->q;
}

QueryPool::QueryPool(QObject *parent)
        : QObject(parent)
        , d(new Private(this))
{
    Q_ASSERT(!s_globalQueryPool->q);
    s_globalQueryPool->q = this;
}

QueryPool::~QueryPool()
{
    delete d;
}

void QueryPool::appendClient(QueryServiceClient* client, const QString& sparqlQuery, const RequestPropertyMap &map)
{
    d->queryData.insert(client, qMakePair(sparqlQuery, map));
    d->queue.enqueue(client);
    d->processNext();
}

void QueryPool::appendClient(QueryServiceClient* client, const Query& query, const RequestPropertyMap &map)
{
    d->queryData.insert(client, qMakePair(query.toSparqlQuery(), map));
    d->queue.enqueue(client);
    d->processNext();
}

}
}

#include "nepomuk-query-query-pool.moc"
/*
 * This file is part of telepathy-contactslist-prototype
 *
 * Copyright (C) 2010 Collabora Ltd. <[email protected]>
 *   @Author Dario Freddi <[email protected]>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef NEPOMUK_QUERY_NEPOMUK_QUERY_QUERY_POOL_H
#define NEPOMUK_QUERY_NEPOMUK_QUERY_QUERY_POOL_H

#include <QtCore/QObject>
#include <nepomuk/query.h>


namespace Nepomuk {

namespace Query {

class QueryServiceClient;
class Query;


class QueryPool : public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(QueryPool)
public:
    static QueryPool *instance();

    virtual ~QueryPool();

    void appendClient(QueryServiceClient *client, const QString &sparqlQuery,
                      const RequestPropertyMap &map = RequestPropertyMap());
    void appendClient(QueryServiceClient *client, const Query &query,
                      const RequestPropertyMap &map = RequestPropertyMap());

private:
    QueryPool(QObject* parent = 0);

    class Private;
    Private * const d;

    Q_PRIVATE_SLOT(d, void __k__onListingFinished())
};

}

}

#endif // NEPOMUK_QUERY_NEPOMUK_QUERY_QUERY_POOL_H

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Nepomuk mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/nepomuk

Reply via email to