From 1259ea24cd26e30d7fdcc97947b78865b86ea5fe Mon Sep 17 00:00:00 2001 From: Brian David Pritchett Date: Wed, 28 Jul 2010 23:28:31 +0000 Subject: [PATCH] Redid much of the storage capability and implemented many suggestions. svn path=/trunk/KDE/kdelibs/; revision=1156347 --- datacontainer.cpp | 117 ++++++++++++++++++++++++++++++++++++-- datacontainer.h | 24 ++++++++ dataengine.cpp | 93 +----------------------------- dataengine.h | 2 - private/datacontainer_p.h | 4 +- private/storage.cpp | 36 ++++-------- 6 files changed, 151 insertions(+), 125 deletions(-) diff --git a/datacontainer.cpp b/datacontainer.cpp index 3b377494f..2dc8e1910 100644 --- a/datacontainer.cpp +++ b/datacontainer.cpp @@ -16,13 +16,10 @@ * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #include "datacontainer.h" #include "private/datacontainer_p.h" #include "private/storage_p.h" -#include - #include #include "plasma.h" @@ -57,7 +54,15 @@ void DataContainer::setData(const QString &key, const QVariant &value) d->dirty = true; d->updateTs.start(); - d->isStored = false; + //check if storage is enabled and if storage is needed. + //If it is not set to be stored,then this is the first + //setData() since the last time it was stored. This + //gives us only one singleShot timer. + if (isStorageEnabled() && !needsToBeStored()) { + QTimer::singleShot(180000, this, SLOT(store())); + } + + setNeedsToBeStored(true); } void DataContainer::removeAllData() @@ -141,7 +146,12 @@ void DataContainer::connectVisualization(QObject *visualization, uint pollingInt void DataContainer::setStorageEnable(bool store) { + QTime time = QTime::currentTime(); + qsrand((uint)time.msec()); d->enableStorage = store; + if (store) { + QTimer::singleShot(qrand() % (2000 + 1) , this, SLOT(retrieve())); + } } bool DataContainer::isStorageEnabled() const @@ -151,7 +161,7 @@ bool DataContainer::isStorageEnabled() const bool DataContainer::needsToBeStored() const { - return (d->enableStorage && !d->isStored); + return !d->isStored; } void DataContainer::setNeedsToBeStored(bool store) @@ -159,6 +169,103 @@ void DataContainer::setNeedsToBeStored(bool store) d->isStored = !store; } +DataEngine* DataContainer::getDataEngine() +{ + QObject *o = NULL; + DataEngine *de = NULL; + o = this; + while (de == NULL) + { + o = dynamic_cast (o->parent()); + if (o == NULL) { + return NULL; + } + de = dynamic_cast (o); + } + return de; +} + +void DataContainer::store() +{ + if (!needsToBeStored()){ + return; + } + DataEngine* de = getDataEngine(); + if (de == NULL) { + return; + } + setNeedsToBeStored(false); + Storage* store = new Storage(de->name(), 0); + KConfigGroup op = store->operationDescription("save"); + op.writeEntry("source", objectName()); + DataEngine::Data dataToStore = data(); + DataEngine::Data::const_iterator it = dataToStore.constBegin(); + while (it != dataToStore.constEnd() && dataToStore.constEnd() == data().constEnd()) { + QVariant v = it.value(); + if ((it.value().type() == QVariant::String) || (it.value().type() == QVariant::Int)) { + op.writeEntry("key", it.key()); + op.writeEntry("data", it.value()); + } else { + QByteArray b; + QDataStream ds(&b, QIODevice::WriteOnly); + ds << it.value(); + op.writeEntry("key", "base64-" + it.key()); + op.writeEntry("data", b.toBase64()); + } + ++it; + ServiceJob* job = store->startOperationCall(op); + job->start(); + } + + //FIXME: this may result in the service being deleted before the jobs ... resulting in the + //jobs potentially being terminated prematurely + store->deleteLater(); +} + +void DataContainer::retrieve() +{ + DataEngine* de = getDataEngine(); + if (de == NULL) { + return; + } + Storage* store = new Storage(de->name(), 0); + KConfigGroup retrieveGroup = store->operationDescription("retrieve"); + retrieveGroup.writeEntry("source", objectName()); + ServiceJob* retrieveJob = store->startOperationCall(retrieveGroup); + connect(retrieveJob, SIGNAL(result(KJob*)), this, + SLOT(populateFromStoredData(KJob*))); +} + +void DataContainer::populateFromStoredData(KJob *job) +{ + if (job->error()) { + return; + } + DataEngine::Data dataToInsert; + ServiceJob* ret = dynamic_cast(job); + QHash h = ret->result().toHash(); + foreach (QString key, h.keys()) { + if (key.startsWith("base64-")) { + QByteArray b = QByteArray::fromBase64(h[key].toString().toAscii()); + QDataStream ds(&b, QIODevice::ReadOnly); + QVariant v(ds); + key.remove(0, 7); + dataToInsert.insert(key, v); + } else { + dataToInsert.insert(key, h[key]); + } + } + if (!(d->data.isEmpty())) + { + //Do not fill the source with old stored + //data if it is already populated with new data. + return; + } + d->data = dataToInsert; + d->dirty = true; + checkForUpdate(); +} + void DataContainer::disconnectVisualization(QObject *visualization) { QMap::iterator objIt = d->relayObjects.find(visualization); diff --git a/datacontainer.h b/datacontainer.h index 580754915..5eb123254 100644 --- a/datacontainer.h +++ b/datacontainer.h @@ -22,7 +22,9 @@ #include #include +#include +#include #include #include @@ -144,6 +146,12 @@ class PLASMA_EXPORT DataContainer : public QObject */ void setNeedsToBeStored(bool store); + /** + * @return the DataEngine that the DataContainer is + * a child of. + */ + DataEngine* getDataEngine(); + public Q_SLOTS: /** * Disconnects an object from this DataContainer. @@ -159,6 +167,16 @@ class PLASMA_EXPORT DataContainer : public QObject */ void forceImmediateUpdate(); + /** + * Stores the DataContainer to disk. + */ + void store(); + + /** + * Retrieves the DataContainer from disk. + */ + void retrieve(); + Q_SIGNALS: /** * Emitted when the data has been updated, allowing visualizations to @@ -235,6 +253,12 @@ class PLASMA_EXPORT DataContainer : public QObject **/ void checkUsage(); + /** + * Does the work of putting the data from disk into the DataContainer + * after retrieve() sets it up. + */ + void populateFromStoredData(KJob *job); + private: friend class SignalRelay; DataContainerPrivate *const d; diff --git a/dataengine.cpp b/dataengine.cpp index 4dbebadc5..2365baaa1 100644 --- a/dataengine.cpp +++ b/dataengine.cpp @@ -200,12 +200,6 @@ void DataEngine::setData(const QString &source, const QString &key, const QVaria emit sourceAdded(source); } - if (s->isStorageEnabled()) { - //FIXME: broken. one can't pass in parameters to a slot like this. - // this probably belongs in DataContainer in any case - QTimer::singleShot(180000, this, SLOT(storeSource(objectName()))); - } - scheduleSourcesUpdated(); } @@ -224,12 +218,6 @@ void DataEngine::setData(const QString &source, const Data &data) ++it; } - if (s->isStorageEnabled()) { - //FIXME: broken. one can't pass in parameters to a slot like this. - // this probably belongs in DataContainer in any case - QTimer::singleShot(180000, this, SLOT(storeSource(objectName()))); - } - if (isNew) { emit sourceAdded(source); } @@ -333,7 +321,7 @@ void DataEngine::removeSource(const QString &source) } } - d->storeSource(s); + s->store(); s->disconnect(this); s->deleteLater(); d->sources.erase(it); @@ -680,7 +668,6 @@ void DataEnginePrivate::connectSource(DataContainer *s, QObject *visualization, !s->visualizationIsConnected(visualization); } - retrieveStoredData(s); s->connectVisualization(visualization, pollingInterval, align); if (immediateCall) { @@ -763,84 +750,6 @@ void DataEnginePrivate::setupScriptSupport() } } -void DataEnginePrivate::storeAllSources() -{ - //kDebug() << "cache all sources"; - foreach (QString sourceName, q->sources()) { - DataContainer *s = q->d->source(sourceName, false); - storeSource(s); - } -} - -void DataEnginePrivate::storeSource(DataContainer *s) const -{ - return; - if (!s || !s->needsToBeStored()) { - return; - } - - // FIXME: this should probably be moved into DataContainer, e.g. DataContainer::store() - s->setNeedsToBeStored(false); - Storage* store = new Storage(q->name(), 0); - KConfigGroup op = store->operationDescription("save"); - op.writeEntry("source", s->objectName()); - DataEngine::Data dataToStore = s->data(); - DataEngine::Data::const_iterator it = dataToStore.constBegin(); - //FIXME: this shouldn't be one job per key/value pair, but one job for the entire container - while (it != dataToStore.constEnd() && dataToStore.constEnd() == s->data().constEnd()) { - QVariant v = it.value(); - if ((it.value().type() == QVariant::String) || (it.value().type() == QVariant::Int)) { - op.writeEntry("key", it.key()); - op.writeEntry("data", it.value()); - } else { - QByteArray b; - QDataStream ds(&b, QIODevice::WriteOnly); - ds << it.value(); - op.writeEntry("key", "base64-" + it.key()); - op.writeEntry("data", b.toBase64()); - } - ++it; - ServiceJob* job = store->startOperationCall(op); - job->start(); - } - - //FIXME: this may result in the service being deleted before the jobs ... resulting in the - //jobs potentially being terminated prematurely - store->deleteLater(); -} - -void DataEnginePrivate::retrieveStoredData(DataContainer *s) -{ - if (!s || !s->isStorageEnabled()) { - return; - } - - //FIXME: this should probably move into DataContainer, and be triggered in setStorageEnabled - // when it is set to true - Storage* store = new Storage(q->name(), 0); - KConfigGroup ret = store->operationDescription("retrieve"); - ret.writeEntry("source", s->objectName()); - ServiceJob* retrieve = store->startOperationCall(ret); - QVariant retrievedData; - retrieve->start(); - while (!retrieve->error()) { - QHash h = retrieve->result().toHash(); - QString key = h["key"].value(); - if (key.startsWith("base64-")) { - QByteArray b = QByteArray::fromBase64(h["data"].toString().toAscii()); - QDataStream ds(&b, QIODevice::ReadOnly); - QVariant v(ds); - key.remove(0, 7); - retrievedData = v; - } else { - retrievedData = h["data"]; - } - s->setData(key, retrievedData); - retrieve->start(); - } - s->checkForUpdate(); -} - } #include "dataengine.moc" diff --git a/dataengine.h b/dataengine.h index 5113a5dfc..3b39d48f3 100644 --- a/dataengine.h +++ b/dataengine.h @@ -500,8 +500,6 @@ NoAlignment) const; Q_PRIVATE_SLOT(d, void internalUpdateSource(DataContainer *source)) Q_PRIVATE_SLOT(d, void sourceDestroyed(QObject *object)) - Q_PRIVATE_SLOT(d, void storeAllSources()) - Q_PRIVATE_SLOT(d, void storeSource(DataContainer *source) const) DataEnginePrivate *const d; }; diff --git a/private/datacontainer_p.h b/private/datacontainer_p.h index 9ed0869ef..26f923304 100644 --- a/private/datacontainer_p.h +++ b/private/datacontainer_p.h @@ -22,10 +22,11 @@ #include #include +#include "servicejob.h" namespace Plasma { - +class ServiceJob; class SignalRelay; class DataContainerPrivate @@ -43,6 +44,7 @@ public: bool immediateUpdate); bool hasUpdates(); + void populateFromStoredData(KJob *job); DataEngine::Data data; QMap relayObjects; diff --git a/private/storage.cpp b/private/storage.cpp index b654f1b4f..1776d34af 100644 --- a/private/storage.cpp +++ b/private/storage.cpp @@ -18,7 +18,6 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // // 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// - #include "private/storage_p.h" #include @@ -33,38 +32,25 @@ StorageJob::StorageJob(const QString& destination, void StorageJob::start() { - static QStringList* keyList = NULL; QMap params = parameters(); QString source = params["source"].toString(); KConfig config("plasma-storagerc"); KConfigGroup destinationGroup(&config, destination()); KConfigGroup sourceGroup(&destinationGroup, source); - KConfigGroup data(&sourceGroup, "Data"); - + KConfigGroup dataGroup(&sourceGroup, "Data"); if (operationName() == "save") { - // KConfigGroup metaData(&sourceGroup, "MetaData"); - // metaData.writeEntry("TimeStamp", QDateTime::currentDateTime()); - data.writeEntry(params["key"].toString(), params["data"]); - setResult(true); + dataGroup.writeEntry(params["key"].toString(), params["data"]); + setResult(true); + return; } else if (operationName() == "retrieve") { - if (keyList == NULL) { - kDebug() << "NULL"; - keyList = new QStringList; - *keyList = data.keyList(); + QHash h; + foreach(QString key, dataGroup.keyList()) + { + QVariant v(dataGroup.readEntry(key)); + h[key] = v; } - if (keyList->isEmpty()) { - setError(1); - delete keyList; - keyList = NULL; - } else { - QString key = keyList->first(); - QHash h; - QVariant v(data.readEntry(key)); - h["key"] = key; - h["data"] = v; - keyList->pop_front(); - setResult(h); - } + setResult(h); + return; } setError(1); }