aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarja Hassinen <ext-marja.2.hassinen@nokia.com>2009-10-27 11:53:11 +0200
committerMarja Hassinen <ext-marja.2.hassinen@nokia.com>2009-10-27 11:53:11 +0200
commit9c2d4fe23f42d50d5a1efc2bd1efdd606afc359b (patch)
treeccadf4d037368d9d826b2b78efe026cd46c8a6e9
parent43feb629a330f829716001919b6c80f779eb7f65 (diff)
libcontextprovider, protocol change: Documentation update.
-rw-r--r--libcontextprovider/src/property.cpp3
-rw-r--r--libcontextprovider/src/property.h2
-rw-r--r--libcontextprovider/src/propertyadaptor.cpp33
-rw-r--r--libcontextprovider/src/propertyprivate.cpp42
-rw-r--r--libcontextprovider/src/propertyprivate.h9
-rw-r--r--libcontextprovider/src/servicebackend.h4
6 files changed, 75 insertions, 18 deletions
diff --git a/libcontextprovider/src/property.cpp b/libcontextprovider/src/property.cpp
index b1b3f82a..02181fdd 100644
--- a/libcontextprovider/src/property.cpp
+++ b/libcontextprovider/src/property.cpp
@@ -62,6 +62,9 @@ Property::Property(const QString &k, QObject* parent)
init(ServiceBackend::defaultServiceBackend, k);
}
+/// Initialize the private implementation: find the corresponding
+/// PropertyPrivate (create it if it doesn't exist), and connect
+/// signals from it.
void Property::init(ServiceBackend *serviceBackend, const QString &key)
{
contextDebug() << F_PROPERTY << "Creating new Property for key:" << key;
diff --git a/libcontextprovider/src/property.h b/libcontextprovider/src/property.h
index 837aa852..788a270d 100644
--- a/libcontextprovider/src/property.h
+++ b/libcontextprovider/src/property.h
@@ -53,7 +53,7 @@ public:
void unsetValue();
private:
- PropertyPrivate *priv;
+ PropertyPrivate *priv; ///< Private implementation
void init(ServiceBackend *serviceBackend, const QString &key);
signals:
diff --git a/libcontextprovider/src/propertyadaptor.cpp b/libcontextprovider/src/propertyadaptor.cpp
index 0d23accf..1751ab7e 100644
--- a/libcontextprovider/src/propertyadaptor.cpp
+++ b/libcontextprovider/src/propertyadaptor.cpp
@@ -30,6 +30,13 @@ namespace ContextProvider {
/*!
\class PropertyAdaptor
\brief A DBus adaptor for implementing the org.maemo.contextkit.Property
+
+ PropertyAdaptor represents the Property object on D-Bus. It also
+ keeps track of its clients and sets the PropertyPrivate to
+ subscribed or unsubscribed accordingly.
+
+ PropertyAdaptor also listens to values sent by other providers on
+ D-Bus and notifies the PropertyPrivate about them.
*/
/// Constructor. Creates new adaptor for the given manager with the given
@@ -43,6 +50,10 @@ PropertyAdaptor::PropertyAdaptor(PropertyPrivate* propertyPrivate, QDBusConnecti
sconnect(propertyPrivate, SIGNAL(valueChanged(const QVariantList&, const quint64&)),
this, SIGNAL(ValueChanged(const QVariantList&, const quint64&)));
+ // The same value can be provided on session and system bus by
+ // different providers. Unfortunately, each provider needs both a
+ // system bus connection and a session bus connection to listen to
+ // other providers.
QDBusConnection::sessionBus().connect("", objectPath(), DBUS_INTERFACE, "ValueChanged",
this, SLOT(onValueChanged(QVariantList, quint64)));
@@ -50,6 +61,7 @@ PropertyAdaptor::PropertyAdaptor(PropertyPrivate* propertyPrivate, QDBusConnecti
this, SLOT(onValueChanged(QVariantList, quint64)));
}
+/// Implementation of the D-Bus method Subscribe
void PropertyAdaptor::Subscribe(const QDBusMessage &msg, QVariantList& values, quint64& timestamp)
{
contextDebug() << "Subscribe called";
@@ -75,6 +87,7 @@ void PropertyAdaptor::Subscribe(const QDBusMessage &msg, QVariantList& values, q
Get(values, timestamp);
}
+/// Implementation of the D-Bus method Unsubscribe
void PropertyAdaptor::Unsubscribe(const QDBusMessage &msg)
{
contextDebug() << "Unsubscribe called";
@@ -94,6 +107,7 @@ void PropertyAdaptor::Unsubscribe(const QDBusMessage &msg)
}
}
+/// Implementation of the D-Bus method Get.
void PropertyAdaptor::Get(QVariantList& values, quint64& timestamp)
{
// Construct the return values
@@ -103,15 +117,16 @@ void PropertyAdaptor::Get(QVariantList& values, quint64& timestamp)
timestamp = propertyPrivate->timestamp;
}
+/// Called when a ValueChanged signal is overheard on D-Bus. Command
+/// PropertyPrivate to update its overheard value.
void PropertyAdaptor::onValueChanged(QVariantList values, quint64 timestamp)
{
propertyPrivate->updateOverheardValue(values, timestamp);
}
-
-/// Dbus interface slot. The PropertyAdaptor listens for dbus bus names changing
-/// to notify the managed Property that a bus name is gone. It does it through
-/// Property::busNameIsGone function.
+/// Called when a NameOwnerChanged signal is broadcast on D-Bus. If
+/// one of our clients has disappeared from D-Bus, update the client
+/// list.
void PropertyAdaptor::OnServiceOwnerChanged(const QString &name, const QString &oldName, const QString &newName)
{
@@ -126,6 +141,11 @@ void PropertyAdaptor::OnServiceOwnerChanged(const QString &name, const QString &
}
}
+/// Object path where the corresponding PropertyPrivate object should
+/// be registered at. For a core propertiy Property.Name (not starting
+/// with /), the path is /org/maemo/contextkit/Property/Name. For a
+/// non-core property /com/my/property, the object path is
+/// /com/my/property.
QString PropertyAdaptor::objectPath() const
{
if (!propertyPrivate->key.startsWith("/"))
@@ -133,11 +153,14 @@ QString PropertyAdaptor::objectPath() const
return QString(propertyPrivate->key);
}
+/// Called when the service is stopped and will disappear from
+/// D-Bus. If it appears again, the clients will resubscribe, and it
+/// shouldn't be a MultipleSubscribe error. Thus, we need to forget
+/// the clients when the service is stopped.
void PropertyAdaptor::forgetClients()
{
clientServiceNames.clear();
propertyPrivate->setUnsubscribed();
}
-
} // namespace ContextProvider
diff --git a/libcontextprovider/src/propertyprivate.cpp b/libcontextprovider/src/propertyprivate.cpp
index ad73b81c..48e3ca19 100644
--- a/libcontextprovider/src/propertyprivate.cpp
+++ b/libcontextprovider/src/propertyprivate.cpp
@@ -29,8 +29,20 @@
namespace ContextProvider {
+/*!
+ \class PropertyPrivate ContextProvider ContextProvider
+
+ \brief The private implementation of Property.
+
+ For each (ServiceBackend*, key) pair there exists only one
+ PropertyPrivate; multiple Property objects may share it.
+*/
+
+
QHash<QPair<ServiceBackend*,QString>, PropertyPrivate*> PropertyPrivate::propertyPrivateMap;
+/// Constructor. Register the PropertyPrivate to its ServiceBackend;
+/// this will make the Property object appear on D-Bus.
PropertyPrivate::PropertyPrivate(ServiceBackend* serviceBackend, const QString &key, QObject *parent)
: QObject(parent), refCount(0), serviceBackend(serviceBackend),
key(key), value(QVariant()), timestamp(currentTimestamp()), subscribed(false),
@@ -40,10 +52,11 @@ PropertyPrivate::PropertyPrivate(ServiceBackend* serviceBackend, const QString &
serviceBackend->addProperty(key, this);
}
-PropertyPrivate::~PropertyPrivate()
-{
-}
-
+/// Set value for the PropertyPrivate. Results in a valueChanged
+/// signal emission, if 1) the value was different than the current
+/// value of the PropertyPrivate, or 2) The provider has overheard
+/// another provider setting a different value having a more recent
+/// time stamp than our last emission.
void PropertyPrivate::setValue(const QVariant& v)
{
contextDebug() << F_PROPERTY << "Setting key:" << key << "to type:" << v.typeName();
@@ -67,9 +80,12 @@ void PropertyPrivate::setValue(const QVariant& v)
}
}
+/// Emit the valueChanged signal and update the emittedValue and
+/// emittedTimestamp. (If subscribed is false, no value is emitted.)
void PropertyPrivate::emitValue()
{
- // No difference between intention and emitted value, nothing happens
+ // No difference between intention and emitted value, nothing
+ // happens
if (emittedTimestamp == timestamp && emittedValue == value
&& emittedValue.isNull() == value.isNull())
return;
@@ -91,6 +107,9 @@ void PropertyPrivate::emitValue()
emit valueChanged(values, timestamp);
}
+/// Set the PropertyPrivate to subscribed state. If it was in the
+/// unsubscribed state, the firstSubscriberAppeared signal is
+/// emitted. (Property transmits the signal forward.)
void PropertyPrivate::setSubscribed()
{
if (subscribed == false) {
@@ -99,6 +118,9 @@ void PropertyPrivate::setSubscribed()
}
}
+/// Set the PropertyPrivate to unsubscribed state. If it was in the
+/// subscribed state, the lastSubscriberDisappeared signal is
+/// emitted. (Property transmits the signal forward.)
void PropertyPrivate::setUnsubscribed()
{
if (subscribed == true) {
@@ -107,6 +129,11 @@ void PropertyPrivate::setUnsubscribed()
}
}
+/// Called by PropertyAdaptor when it has overheard another provider
+/// sending a value on D-Bus. Check if the value is different and more
+/// recent than the value we've emitted last. If so, emit our value
+/// again. This way we ensure that the client gets the correct time
+/// stamp for our value.
void PropertyPrivate::updateOverheardValue(const QVariantList& v, const quint64& t)
{
contextDebug() << "Updating overheard value" << v << t;
@@ -119,7 +146,7 @@ void PropertyPrivate::updateOverheardValue(const QVariantList& v, const quint64&
else {
overheardValue = v[0];
}
- if (t > emittedTimestamp && overheardValue != emittedValue){
+ if (t > emittedTimestamp && overheardValue != emittedValue){
// record that a different and more recent value than the one
// emitted has been overheard
overheard = true;
@@ -129,6 +156,8 @@ void PropertyPrivate::updateOverheardValue(const QVariantList& v, const quint64&
}
}
+/// Compute a unique time stamp for our value. The time stamp is based
+/// on monotonic clock and its value is: seconds * 10e9 + nanoseconds.
quint64 PropertyPrivate::currentTimestamp()
{
struct timespec time;
@@ -138,6 +167,5 @@ quint64 PropertyPrivate::currentTimestamp()
return toReturn;
}
-
} // end namespace
diff --git a/libcontextprovider/src/propertyprivate.h b/libcontextprovider/src/propertyprivate.h
index 2e5a4ad0..f626f773 100644
--- a/libcontextprovider/src/propertyprivate.h
+++ b/libcontextprovider/src/propertyprivate.h
@@ -37,7 +37,6 @@ class PropertyPrivate : public QObject
public:
explicit PropertyPrivate(ServiceBackend* serviceBackend, const QString &key, QObject *parent = 0);
- virtual ~PropertyPrivate();
void setValue(const QVariant& v);
void updateOverheardValue(const QVariantList&, const quint64&);
@@ -53,16 +52,20 @@ private:
static quint64 currentTimestamp();
void emitValue();
- int refCount;
+ int refCount; ///< Number of Property instance sharing this PropertyPrivate
ServiceBackend* serviceBackend; ///< Pointer to the serviceBackend taking care of D-Bus related things
QString key; ///< Key of this property
QVariant value; ///< Current value of the property, set by this provider. QVariant() if null.
quint64 timestamp; ///< Time when the value was set
- bool subscribed;
+
+ bool subscribed; ///< True if this Property is subscribed to by the clients.
QVariant emittedValue; ///< Last value emitted by this provider.
quint64 emittedTimestamp; ///< Time when the emittedValue was emitted.
bool overheard; ///< True if provider overheard a value over D-Bus (must be different and more recent than emitted)
+
+ /// Map of PropertyPrivate instances
static QHash<QPair<ServiceBackend*, QString>, PropertyPrivate*> propertyPrivateMap;
+
friend class Property;
friend class PropertyAdaptor;
};
diff --git a/libcontextprovider/src/servicebackend.h b/libcontextprovider/src/servicebackend.h
index c69e40b8..1073d3f2 100644
--- a/libcontextprovider/src/servicebackend.h
+++ b/libcontextprovider/src/servicebackend.h
@@ -70,12 +70,12 @@ public:
private:
bool registerProperty(const QString& key, PropertyPrivate* property);
+ int refCount; ///< Number of Service objects using this as their backend
+
/// Shared or private QDBusConnection used for registering objects
/// (and possibly bus names)
QDBusConnection connection;
- int refCount; ///< Number of Service objects using this as their backend
-
/// The bus name that should be registered by this ServiceBackend;
/// "" if the ServiceBackend shouldn't register any.
QString busName;