Redid much of the storage capability and implemented many suggestions.

svn path=/trunk/KDE/kdelibs/; revision=1156347
This commit is contained in:
Brian David Pritchett 2010-07-28 23:28:31 +00:00
parent fb56692aa8
commit 1259ea24cd
6 changed files with 151 additions and 125 deletions

View File

@ -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 <QVariant>
#include <kdebug.h>
#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<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)
{
QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);

View File

@ -22,7 +22,9 @@
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtCore/QTimer>
#include <kjob.h>
#include <plasma/plasma_export.h>
#include <plasma/dataengine.h>
@ -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;

View File

@ -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<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"

View File

@ -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;
};

View File

@ -22,10 +22,11 @@
#include <QtCore/QTimerEvent>
#include <QtCore/QTime>
#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<QObject *, SignalRelay *> relayObjects;

View File

@ -18,7 +18,6 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA //
// 02110-1301 USA //
/////////////////////////////////////////////////////////////////////////
#include "private/storage_p.h"
#include <kdebug.h>
@ -33,38 +32,25 @@ StorageJob::StorageJob(const QString& destination,
void StorageJob::start()
{
static QStringList* keyList = NULL;
QMap<QString, QVariant> 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<QString, QVariant> 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<QString, QVariant> h;
QVariant v(data.readEntry(key));
h["key"] = key;
h["data"] = v;
keyList->pop_front();
setResult(h);
}
setResult(h);
return;
}
setError(1);
}