This adds the first iteration of data caching for dataengines.

svn path=/trunk/KDE/kdelibs/; revision=1149185
This commit is contained in:
Brian David Pritchett 2010-07-12 20:51:12 +00:00
parent 8002b2415b
commit 53a227a43f
9 changed files with 247 additions and 0 deletions

View File

@ -135,6 +135,7 @@ set(plasma_LIB_SRCS
private/remoteservicejob.cpp
private/runnerjobs.cpp
private/serviceprovider.cpp
private/storage.cpp
private/style.cpp
private/trustedonlyauthorization.cpp
private/internaltoolbox.cpp
@ -418,4 +419,5 @@ install(FILES data/kconfig_updates/plasma_popupapplet_fix_groups.upd DESTINATION
install(PROGRAMS data/kconfig_updates/plasma_popupapplet_fix_groups.pl DESTINATION ${KCONF_UPDATE_INSTALL_DIR})
install(FILES data/operations/dataengineservice.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
install(FILES data/operations/plasmoidservice.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
install(FILES data/operations/storage.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kcfg SYSTEM
"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
<kcfg>
<group name="save">
<entry name="source" type="String">
<label>Name of the source</label>
</entry>
<entry name="key" type="String">
<label>Fill</label>
</entry>
<entry name="data" type="Int">
<label>The actual data to be stored.</label>
</entry>
<entry name="data" type="String">
<label>The actual data to be stored.</label>
</entry>
<entry name="data" type="StringList">
<label>The actual data to be stored.</label>
</entry>
</group>
<group name="retrieve">
<entry name="source" type="String">
<label>Name of the source</label>
</entry>
</group>
</kcfg>

View File

@ -19,6 +19,7 @@
#include "datacontainer.h"
#include "private/datacontainer_p.h"
#include "private/storage_p.h"
#include <QVariant>
@ -33,6 +34,8 @@ DataContainer::DataContainer(QObject *parent)
: QObject(parent),
d(new DataContainerPrivate)
{
d->enableStorage = false;
d->isStored = true;
}
DataContainer::~DataContainer()
@ -55,6 +58,8 @@ void DataContainer::setData(const QString &key, const QVariant &value)
d->dirty = true;
d->updateTs.start();
d->isStored = false;
}
void DataContainer::removeAllData()
@ -136,6 +141,26 @@ void DataContainer::connectVisualization(QObject *visualization, uint pollingInt
}
}
void DataContainer::setStorageEnable(bool store)
{
d->enableStorage = store;
}
bool DataContainer::isStorageEnabled() const
{
return d->enableStorage;
}
bool DataContainer::needsToBeStored() const
{
return (d->enableStorage && !d->isStored);
}
void DataContainer::setNeedsToBeStored(bool store)
{
d->isStored = !store;
}
void DataContainer::disconnectVisualization(QObject *visualization)
{
QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);

View File

@ -122,6 +122,28 @@ class PLASMA_EXPORT DataContainer : public QObject
void connectVisualization(QObject *visualization, uint pollingInterval,
Plasma::IntervalAlignment alignment);
/**
* sets this data container to be automatically stored.
* @param whether this data container should be stored
*/
void setStorageEnable(bool store);
/**
* @return true if the data container has been marked for storage
*/
bool isStorageEnabled() const;
/**
* @return true if the data container has been updated, but not stored
*/
bool needsToBeStored() const;
/**
* sets that the data container needs to be stored or not.
* @param whether the data container needs to be stored
*/
void setNeedsToBeStored(bool store);
public Q_SLOTS:
/**
* Disconnects an object from this DataContainer.

View File

@ -41,6 +41,7 @@
#include "private/dataengineservice_p.h"
#include "private/remotedataengine_p.h"
#include "private/service_p.h"
#include "private/storage_p.h"
namespace Plasma
{
@ -199,6 +200,10 @@ void DataEngine::setData(const QString &source, const QString &key, const QVaria
emit sourceAdded(source);
}
if (s->isStorageEnabled()) {
QTimer::singleShot(180000, this, SLOT(storeSource(objectName())));
}
scheduleSourcesUpdated();
}
@ -217,6 +222,10 @@ void DataEngine::setData(const QString &source, const Data &data)
++it;
}
if (s->isStorageEnabled()) {
QTimer::singleShot(180000, this, SLOT(storeSource(objectName())));
}
if (isNew) {
emit sourceAdded(source);
}
@ -320,6 +329,7 @@ void DataEngine::removeSource(const QString &source)
}
}
d->storeSource(source);
s->disconnect(this);
s->deleteLater();
d->sources.erase(it);
@ -500,6 +510,12 @@ void DataEngine::setName(const QString &name)
setObjectName(name);
}
void DataEngine::setStorageEnable(const QString &source, bool store)
{
DataContainer *s = d->source(source, false);
s->setStorageEnable(store);
}
// Private class implementations
DataEnginePrivate::DataEnginePrivate(DataEngine *e, KService::Ptr service)
: q(e),
@ -661,6 +677,7 @@ void DataEnginePrivate::connectSource(DataContainer *s, QObject *visualization,
!s->visualizationIsConnected(visualization);
}
retrieveStoredData(s);
s->connectVisualization(visualization, pollingInterval, align);
if (immediateCall) {
@ -743,6 +760,72 @@ void DataEnginePrivate::setupScriptSupport()
}
}
void DataEnginePrivate::storeAllSources()
{
//kDebug() << "cache all sources";
foreach (QString sourceName, q->sources()) {
storeSource(sourceName);
}
}
void DataEnginePrivate::storeSource(const QString &sourceName) const
{
DataContainer *s = q->d->source(sourceName, false);
if (s) {
if (s->isStorageEnabled() && s->needsToBeStored()) {
s->setNeedsToBeStored(false);
Storage* store = new Storage(q->name(), 0);
KConfigGroup op = store->operationDescription("save");
op.writeEntry("source", sourceName);
DataEngine::Data dataToStore = s->data();
DataEngine::Data::const_iterator it = dataToStore.constBegin();
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();
}
store->deleteLater();
}
}
}
void DataEnginePrivate::retrieveStoredData(DataContainer *s)
{
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

@ -450,6 +450,16 @@ NoAlignment) const;
*/
void setDefaultService(const QString &serviceName);
/**
* Sets a source to be stored for easy retrieval
* when the real source of the data (usually a network connection)
* is unavailable.
* @param source the name of the source
* @param store if source should be stored
*/
void setStorageEnable(const QString &source, bool store);
protected Q_SLOTS:
/**
* Call this method when you call setData directly on a DataContainer instead
@ -490,6 +500,8 @@ 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(const QString &sourceName) const)
DataEnginePrivate *const d;
};

View File

@ -47,6 +47,8 @@ public:
QTime updateTs;
bool dirty : 1;
bool cached : 1;
bool enableStorage;
bool isStored;
};
class SignalRelay : public QObject

View File

@ -84,6 +84,23 @@ class DataEnginePrivate
*/
void sourceDestroyed(QObject *object);
/**
* stores the source
* @param sourceName the name of the source to store
*/
void storeSource(const QString &sourceName) const;
/**
* stores all sources marked for storage
*/
void storeAllSources();
/**
* retrieves source data
* @param the data container to populate
*/
void retrieveStoredData(DataContainer *s);
DataEngine *q;
KPluginInfo dataEngineDescription;
int refCount;

57
private/storage_p.h Normal file
View File

@ -0,0 +1,57 @@
/////////////////////////////////////////////////////////////////////////
// storage.h //
// //
// Copyright (C) 2010 Brian Pritchett <batenkaitos@gmail.com> //
// //
// 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 Street, Fifth Floor, Boston, MA //
// 02110-1301 USA //
/////////////////////////////////////////////////////////////////////////
#ifndef PLASMA_STORAGE_H
#define PLASMA_STORAGE_H
#include <Plasma/Service>
#include <Plasma/ServiceJob>
//Begin StorageJob
class StorageJob : public Plasma::ServiceJob
{
Q_OBJECT
public:
StorageJob(const QString& destination,
const QString& operation,
const QMap<QString, QVariant>& parameters,
QObject *parent = 0);
void start();
};
//End StorageJob
class Storage : public Plasma::Service
{
Q_OBJECT
public:
Storage(const QString& destination, QObject* parent);
~Storage();
protected:
Plasma::ServiceJob* createJob(const QString &operation, QMap<QString, QVariant> &parameters);
private:
QString m_serviceName;
};
#endif //PLASMA_STORAGE_H