Redid much of the storage capability and implemented many suggestions.
svn path=/trunk/KDE/kdelibs/; revision=1156347
This commit is contained in:
parent
fb56692aa8
commit
1259ea24cd
@ -16,13 +16,10 @@
|
|||||||
* Free Software Foundation, Inc.,
|
* Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "datacontainer.h"
|
#include "datacontainer.h"
|
||||||
#include "private/datacontainer_p.h"
|
#include "private/datacontainer_p.h"
|
||||||
#include "private/storage_p.h"
|
#include "private/storage_p.h"
|
||||||
|
|
||||||
#include <QVariant>
|
|
||||||
|
|
||||||
#include <kdebug.h>
|
#include <kdebug.h>
|
||||||
|
|
||||||
#include "plasma.h"
|
#include "plasma.h"
|
||||||
@ -57,7 +54,15 @@ void DataContainer::setData(const QString &key, const QVariant &value)
|
|||||||
d->dirty = true;
|
d->dirty = true;
|
||||||
d->updateTs.start();
|
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()
|
void DataContainer::removeAllData()
|
||||||
@ -141,7 +146,12 @@ void DataContainer::connectVisualization(QObject *visualization, uint pollingInt
|
|||||||
|
|
||||||
void DataContainer::setStorageEnable(bool store)
|
void DataContainer::setStorageEnable(bool store)
|
||||||
{
|
{
|
||||||
|
QTime time = QTime::currentTime();
|
||||||
|
qsrand((uint)time.msec());
|
||||||
d->enableStorage = store;
|
d->enableStorage = store;
|
||||||
|
if (store) {
|
||||||
|
QTimer::singleShot(qrand() % (2000 + 1) , this, SLOT(retrieve()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataContainer::isStorageEnabled() const
|
bool DataContainer::isStorageEnabled() const
|
||||||
@ -151,7 +161,7 @@ bool DataContainer::isStorageEnabled() const
|
|||||||
|
|
||||||
bool DataContainer::needsToBeStored() const
|
bool DataContainer::needsToBeStored() const
|
||||||
{
|
{
|
||||||
return (d->enableStorage && !d->isStored);
|
return !d->isStored;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataContainer::setNeedsToBeStored(bool store)
|
void DataContainer::setNeedsToBeStored(bool store)
|
||||||
@ -159,6 +169,103 @@ void DataContainer::setNeedsToBeStored(bool store)
|
|||||||
d->isStored = !store;
|
d->isStored = !store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DataEngine* DataContainer::getDataEngine()
|
||||||
|
{
|
||||||
|
QObject *o = NULL;
|
||||||
|
DataEngine *de = NULL;
|
||||||
|
o = this;
|
||||||
|
while (de == NULL)
|
||||||
|
{
|
||||||
|
o = dynamic_cast<QObject *> (o->parent());
|
||||||
|
if (o == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
de = dynamic_cast<DataEngine *> (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<ServiceJob*>(job);
|
||||||
|
QHash<QString, QVariant> 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)
|
void DataContainer::disconnectVisualization(QObject *visualization)
|
||||||
{
|
{
|
||||||
QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
|
QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
|
|
||||||
#include <QtCore/QHash>
|
#include <QtCore/QHash>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
|
#include <kjob.h>
|
||||||
#include <plasma/plasma_export.h>
|
#include <plasma/plasma_export.h>
|
||||||
#include <plasma/dataengine.h>
|
#include <plasma/dataengine.h>
|
||||||
|
|
||||||
@ -144,6 +146,12 @@ class PLASMA_EXPORT DataContainer : public QObject
|
|||||||
*/
|
*/
|
||||||
void setNeedsToBeStored(bool store);
|
void setNeedsToBeStored(bool store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the DataEngine that the DataContainer is
|
||||||
|
* a child of.
|
||||||
|
*/
|
||||||
|
DataEngine* getDataEngine();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/**
|
/**
|
||||||
* Disconnects an object from this DataContainer.
|
* Disconnects an object from this DataContainer.
|
||||||
@ -159,6 +167,16 @@ class PLASMA_EXPORT DataContainer : public QObject
|
|||||||
*/
|
*/
|
||||||
void forceImmediateUpdate();
|
void forceImmediateUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the DataContainer to disk.
|
||||||
|
*/
|
||||||
|
void store();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the DataContainer from disk.
|
||||||
|
*/
|
||||||
|
void retrieve();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
/**
|
/**
|
||||||
* Emitted when the data has been updated, allowing visualizations to
|
* Emitted when the data has been updated, allowing visualizations to
|
||||||
@ -235,6 +253,12 @@ class PLASMA_EXPORT DataContainer : public QObject
|
|||||||
**/
|
**/
|
||||||
void checkUsage();
|
void checkUsage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the work of putting the data from disk into the DataContainer
|
||||||
|
* after retrieve() sets it up.
|
||||||
|
*/
|
||||||
|
void populateFromStoredData(KJob *job);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SignalRelay;
|
friend class SignalRelay;
|
||||||
DataContainerPrivate *const d;
|
DataContainerPrivate *const d;
|
||||||
|
@ -200,12 +200,6 @@ void DataEngine::setData(const QString &source, const QString &key, const QVaria
|
|||||||
emit sourceAdded(source);
|
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();
|
scheduleSourcesUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,12 +218,6 @@ void DataEngine::setData(const QString &source, const Data &data)
|
|||||||
++it;
|
++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) {
|
if (isNew) {
|
||||||
emit sourceAdded(source);
|
emit sourceAdded(source);
|
||||||
}
|
}
|
||||||
@ -333,7 +321,7 @@ void DataEngine::removeSource(const QString &source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d->storeSource(s);
|
s->store();
|
||||||
s->disconnect(this);
|
s->disconnect(this);
|
||||||
s->deleteLater();
|
s->deleteLater();
|
||||||
d->sources.erase(it);
|
d->sources.erase(it);
|
||||||
@ -680,7 +668,6 @@ void DataEnginePrivate::connectSource(DataContainer *s, QObject *visualization,
|
|||||||
!s->visualizationIsConnected(visualization);
|
!s->visualizationIsConnected(visualization);
|
||||||
}
|
}
|
||||||
|
|
||||||
retrieveStoredData(s);
|
|
||||||
s->connectVisualization(visualization, pollingInterval, align);
|
s->connectVisualization(visualization, pollingInterval, align);
|
||||||
|
|
||||||
if (immediateCall) {
|
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<QString, QVariant> h = retrieve->result().toHash();
|
|
||||||
QString key = h["key"].value<QString>();
|
|
||||||
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"
|
#include "dataengine.moc"
|
||||||
|
@ -500,8 +500,6 @@ NoAlignment) const;
|
|||||||
|
|
||||||
Q_PRIVATE_SLOT(d, void internalUpdateSource(DataContainer *source))
|
Q_PRIVATE_SLOT(d, void internalUpdateSource(DataContainer *source))
|
||||||
Q_PRIVATE_SLOT(d, void sourceDestroyed(QObject *object))
|
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;
|
DataEnginePrivate *const d;
|
||||||
};
|
};
|
||||||
|
@ -22,10 +22,11 @@
|
|||||||
|
|
||||||
#include <QtCore/QTimerEvent>
|
#include <QtCore/QTimerEvent>
|
||||||
#include <QtCore/QTime>
|
#include <QtCore/QTime>
|
||||||
|
#include "servicejob.h"
|
||||||
|
|
||||||
namespace Plasma
|
namespace Plasma
|
||||||
{
|
{
|
||||||
|
class ServiceJob;
|
||||||
class SignalRelay;
|
class SignalRelay;
|
||||||
|
|
||||||
class DataContainerPrivate
|
class DataContainerPrivate
|
||||||
@ -43,6 +44,7 @@ public:
|
|||||||
bool immediateUpdate);
|
bool immediateUpdate);
|
||||||
|
|
||||||
bool hasUpdates();
|
bool hasUpdates();
|
||||||
|
void populateFromStoredData(KJob *job);
|
||||||
|
|
||||||
DataEngine::Data data;
|
DataEngine::Data data;
|
||||||
QMap<QObject *, SignalRelay *> relayObjects;
|
QMap<QObject *, SignalRelay *> relayObjects;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA //
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA //
|
||||||
// 02110-1301 USA //
|
// 02110-1301 USA //
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "private/storage_p.h"
|
#include "private/storage_p.h"
|
||||||
#include <kdebug.h>
|
#include <kdebug.h>
|
||||||
|
|
||||||
@ -33,38 +32,25 @@ StorageJob::StorageJob(const QString& destination,
|
|||||||
|
|
||||||
void StorageJob::start()
|
void StorageJob::start()
|
||||||
{
|
{
|
||||||
static QStringList* keyList = NULL;
|
|
||||||
QMap<QString, QVariant> params = parameters();
|
QMap<QString, QVariant> params = parameters();
|
||||||
QString source = params["source"].toString();
|
QString source = params["source"].toString();
|
||||||
KConfig config("plasma-storagerc");
|
KConfig config("plasma-storagerc");
|
||||||
KConfigGroup destinationGroup(&config, destination());
|
KConfigGroup destinationGroup(&config, destination());
|
||||||
KConfigGroup sourceGroup(&destinationGroup, source);
|
KConfigGroup sourceGroup(&destinationGroup, source);
|
||||||
KConfigGroup data(&sourceGroup, "Data");
|
KConfigGroup dataGroup(&sourceGroup, "Data");
|
||||||
|
|
||||||
if (operationName() == "save") {
|
if (operationName() == "save") {
|
||||||
// KConfigGroup metaData(&sourceGroup, "MetaData");
|
dataGroup.writeEntry(params["key"].toString(), params["data"]);
|
||||||
// metaData.writeEntry("TimeStamp", QDateTime::currentDateTime());
|
setResult(true);
|
||||||
data.writeEntry(params["key"].toString(), params["data"]);
|
return;
|
||||||
setResult(true);
|
|
||||||
} else if (operationName() == "retrieve") {
|
} else if (operationName() == "retrieve") {
|
||||||
if (keyList == NULL) {
|
QHash<QString, QVariant> h;
|
||||||
kDebug() << "NULL";
|
foreach(QString key, dataGroup.keyList())
|
||||||
keyList = new QStringList;
|
{
|
||||||
*keyList = data.keyList();
|
QVariant v(dataGroup.readEntry(key));
|
||||||
|
h[key] = v;
|
||||||
}
|
}
|
||||||
if (keyList->isEmpty()) {
|
setResult(h);
|
||||||
setError(1);
|
return;
|
||||||
delete keyList;
|
|
||||||
keyList = NULL;
|
|
||||||
} else {
|
|
||||||
QString key = keyList->first();
|
|
||||||
QHash<QString, QVariant> h;
|
|
||||||
QVariant v(data.readEntry(key));
|
|
||||||
h["key"] = key;
|
|
||||||
h["data"] = v;
|
|
||||||
keyList->pop_front();
|
|
||||||
setResult(h);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
setError(1);
|
setError(1);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user