[Telepathy-commits] [telepathy-qt4/master] ReadinessHelper: Added critical feature concept.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Fri Mar 6 09:11:16 PST 2009


Added critical feature concept and make FeatureCore critical in all classes.
isReady/becomeReady will fail if a critical feature cannot
not be satisfied.
---
 TelepathyQt4/Client/account-manager.cpp    |    6 ++--
 TelepathyQt4/Client/account.cpp            |    6 ++--
 TelepathyQt4/Client/channel.cpp            |    6 ++--
 TelepathyQt4/Client/connection-manager.cpp |    6 ++--
 TelepathyQt4/Client/connection.cpp         |    6 ++--
 TelepathyQt4/Client/readiness-helper.cpp   |   51 ++++++++++++++++++++++------
 TelepathyQt4/Client/readiness-helper.h     |   27 ++++++++++++---
 TelepathyQt4/Client/text-channel.cpp       |   10 +++---
 8 files changed, 82 insertions(+), 36 deletions(-)

diff --git a/TelepathyQt4/Client/account-manager.cpp b/TelepathyQt4/Client/account-manager.cpp
index a930076..32cdcf4 100644
--- a/TelepathyQt4/Client/account-manager.cpp
+++ b/TelepathyQt4/Client/account-manager.cpp
@@ -150,7 +150,7 @@ void AccountManager::Private::setAccountPaths(QSet<QString> &set,
  * Object representing a Telepathy account manager.
  */
 
-const Feature AccountManager::FeatureCore = Feature(AccountManager::staticMetaObject.className(), 0);
+const Feature AccountManager::FeatureCore = Feature(AccountManager::staticMetaObject.className(), 0, true);
 
 /**
  * Construct a new AccountManager object.
@@ -374,9 +374,9 @@ PendingAccount *AccountManager::createAccount(const QString &connectionManager,
 bool AccountManager::isReady(const Features &features) const
 {
     if (features.isEmpty()) {
-        return mPriv->readinessHelper->isReady(Features() << FeatureCore, true);
+        return mPriv->readinessHelper->isReady(Features() << FeatureCore);
     }
-    return mPriv->readinessHelper->isReady(features, features.contains(FeatureCore));
+    return mPriv->readinessHelper->isReady(features);
 }
 
 /**
diff --git a/TelepathyQt4/Client/account.cpp b/TelepathyQt4/Client/account.cpp
index 6358a72..d605ad6 100644
--- a/TelepathyQt4/Client/account.cpp
+++ b/TelepathyQt4/Client/account.cpp
@@ -195,7 +195,7 @@ Account::Private::~Private()
  * and will cease to be useful.
  */
 
-const Feature Account::FeatureCore = Feature(Account::staticMetaObject.className(), 0);
+const Feature Account::FeatureCore = Feature(Account::staticMetaObject.className(), 0, true);
 const Feature Account::FeatureAvatar = Feature(Account::staticMetaObject.className(), 1);
 const Feature Account::FeatureProtocolInfo = Feature(Account::staticMetaObject.className(), 2);
 
@@ -658,9 +658,9 @@ PendingOperation *Account::remove()
 bool Account::isReady(const Features &features) const
 {
     if (features.isEmpty()) {
-        return mPriv->readinessHelper->isReady(Features() << FeatureCore, true);
+        return mPriv->readinessHelper->isReady(Features() << FeatureCore);
     }
-    return mPriv->readinessHelper->isReady(features, features.contains(FeatureCore));
+    return mPriv->readinessHelper->isReady(features);
 }
 
 /**
diff --git a/TelepathyQt4/Client/channel.cpp b/TelepathyQt4/Client/channel.cpp
index 0a8685a..8f5bdf4 100644
--- a/TelepathyQt4/Client/channel.cpp
+++ b/TelepathyQt4/Client/channel.cpp
@@ -949,7 +949,7 @@ void Channel::Private::setReady()
  * will transition to closed too.
  */
 
-const Feature Channel::FeatureCore = Feature(Channel::staticMetaObject.className(), 0);
+const Feature Channel::FeatureCore = Feature(Channel::staticMetaObject.className(), 0, true);
 
 /**
  * Construct a new Channel object.
@@ -1113,9 +1113,9 @@ QSharedPointer<Contact> Channel::initiatorContact() const
 bool Channel::isReady(const Features &features) const
 {
     if (features.isEmpty()) {
-        return mPriv->readinessHelper->isReady(Features() << FeatureCore, true);
+        return mPriv->readinessHelper->isReady(Features() << FeatureCore);
     }
-    return mPriv->readinessHelper->isReady(features, features.contains(FeatureCore));
+    return mPriv->readinessHelper->isReady(features);
 }
 
 /**
diff --git a/TelepathyQt4/Client/connection-manager.cpp b/TelepathyQt4/Client/connection-manager.cpp
index 4898da7..82f67a4 100644
--- a/TelepathyQt4/Client/connection-manager.cpp
+++ b/TelepathyQt4/Client/connection-manager.cpp
@@ -348,7 +348,7 @@ ProtocolInfo *ConnectionManager::Private::protocol(const QString &protocolName)
  * applications.
  */
 
-const Feature ConnectionManager::FeatureCore = Feature(ConnectionManager::staticMetaObject.className(), 0);
+const Feature ConnectionManager::FeatureCore = Feature(ConnectionManager::staticMetaObject.className(), 0, true);
 
 /**
  * Construct a new ConnectionManager object.
@@ -473,9 +473,9 @@ PendingConnection *ConnectionManager::requestConnection(const QString &protocol,
 bool ConnectionManager::isReady(const Features &features) const
 {
     if (features.isEmpty()) {
-        return mPriv->readinessHelper->isReady(Features() << FeatureCore, true);
+        return mPriv->readinessHelper->isReady(Features() << FeatureCore);
     }
-    return mPriv->readinessHelper->isReady(features, features.contains(FeatureCore));
+    return mPriv->readinessHelper->isReady(features);
 }
 
 /**
diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index d99c462..1bbda28 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -449,7 +449,7 @@ QMutex Connection::Private::handleContextsLock;
  * in the different states.
  */
 
-const Feature Connection::FeatureCore = Feature(Connection::staticMetaObject.className(), 0);
+const Feature Connection::FeatureCore = Feature(Connection::staticMetaObject.className(), 0, true);
 const Feature Connection::FeatureSelfContact = Feature(Connection::staticMetaObject.className(), 1);
 const Feature Connection::FeatureSimplePresence = Feature(Connection::staticMetaObject.className(), 2);
 const Feature Connection::FeatureRoster = Feature(Connection::staticMetaObject.className(), 3);
@@ -1262,9 +1262,9 @@ PendingHandles *Connection::referenceHandles(uint handleType, const UIntList &ha
 bool Connection::isReady(const Features &features) const
 {
     if (features.isEmpty()) {
-        return mPriv->readinessHelper->isReady(Features() << FeatureCore, true);
+        return mPriv->readinessHelper->isReady(Features() << FeatureCore);
     }
-    return mPriv->readinessHelper->isReady(features, features.contains(FeatureCore));
+    return mPriv->readinessHelper->isReady(features);
 }
 
 /**
diff --git a/TelepathyQt4/Client/readiness-helper.cpp b/TelepathyQt4/Client/readiness-helper.cpp
index 3006253..999f103 100644
--- a/TelepathyQt4/Client/readiness-helper.cpp
+++ b/TelepathyQt4/Client/readiness-helper.cpp
@@ -44,7 +44,7 @@ struct ReadinessHelper::Private
     ~Private();
 
     void setCurrentStatus(uint newStatus);
-    void setIntrospectCompleted(Feature feature, bool success);
+    void setIntrospectCompleted(const Feature &feature, bool success);
     void iterateIntrospection();
 
     void abortOperations(const QString &errorName, const QString &errorMessage);
@@ -121,7 +121,7 @@ void ReadinessHelper::Private::setCurrentStatus(uint newStatus)
     }
 }
 
-void ReadinessHelper::Private::setIntrospectCompleted(Feature feature, bool success)
+void ReadinessHelper::Private::setIntrospectCompleted(const Feature &feature, bool success)
 {
     debug() << "ReadinessHelper::setIntrospectCompleted: feature:" << feature <<
         "- success:" << success;
@@ -187,7 +187,14 @@ void ReadinessHelper::Private::iterateIntrospection()
     // satisfiedFeatures + missingFeatures has
     foreach (PendingReady *operation, pendingOperations) {
         if ((operation->requestedFeatures() - (satisfiedFeatures + missingFeatures)).isEmpty()) {
-            operation->setFinished();
+            if (parent->isReady(operation->requestedFeatures())) {
+                operation->setFinished();
+            } else {
+                // TODO get the error from somewhere, maybe add an error param
+                //      to setIntrospectCompleted
+                operation->setFinishedWithError(TELEPATHY_ERROR_NOT_AVAILABLE,
+                        "Some features not available");
+            }
             pendingOperations.removeOne(operation);
         }
     }
@@ -204,7 +211,7 @@ void ReadinessHelper::Private::iterateIntrospection()
 
     // find out which features don't have dependencies that are still pending
     Features readyToIntrospect;
-    foreach (Feature feature, pendingFeatures) {
+    foreach (const Feature &feature, pendingFeatures) {
         // missing doesn't have to be considered here anymore
         if ((introspectables[feature].dependsOnFeatures - satisfiedFeatures).isEmpty()) {
             readyToIntrospect.insert(feature);
@@ -213,7 +220,7 @@ void ReadinessHelper::Private::iterateIntrospection()
 
     // now readyToIntrospect should contain all the features which have
     // all their feature dependencies satisfied
-    foreach (Feature feature, readyToIntrospect) {
+    foreach (const Feature &feature, readyToIntrospect) {
         if (inFlightFeatures.contains(feature)) {
             continue;
         }
@@ -334,7 +341,28 @@ Features ReadinessHelper::missingFeatures() const
     return mPriv->missingFeatures;
 }
 
-bool ReadinessHelper::isReady(const Features &features, bool onlySatisfied) const
+bool ReadinessHelper::isReady(const Feature &feature) const
+{
+    if (!mPriv->proxy->isValid()) {
+        return false;
+    }
+
+    if (feature.isCritical()) {
+        if (!mPriv->satisfiedFeatures.contains(feature)) {
+            debug() << "ReadinessHelper::isReady: critical feature" << feature << "not ready";
+            return false;
+        }
+    } else {
+        if (!mPriv->satisfiedFeatures.contains(feature) &&
+            !mPriv->missingFeatures.contains(feature)) {
+            debug() << "ReadinessHelper::isReady: feature" << feature << "not ready";
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ReadinessHelper::isReady(const Features &features) const
 {
     if (!mPriv->proxy->isValid()) {
         return false;
@@ -342,11 +370,12 @@ bool ReadinessHelper::isReady(const Features &features, bool onlySatisfied) cons
 
     Q_ASSERT(!features.isEmpty());
 
-    if (onlySatisfied) {
-        return (features - mPriv->satisfiedFeatures).isEmpty();
-    } else {
-        return (features - (mPriv->satisfiedFeatures + mPriv->missingFeatures)).isEmpty();
+    foreach (const Feature &feature, features) {
+        if (!isReady(feature)) {
+            return false;
+        }
     }
+    return true;
 }
 
 PendingReady *ReadinessHelper::becomeReady(const Features &requestedFeatures)
@@ -391,7 +420,7 @@ PendingReady *ReadinessHelper::becomeReady(const Features &requestedFeatures)
     return operation;
 }
 
-void ReadinessHelper::setIntrospectCompleted(Feature feature, bool success)
+void ReadinessHelper::setIntrospectCompleted(const Feature &feature, bool success)
 {
     if (!mPriv->proxy->isValid()) {
         // proxy became invalid, ignore here
diff --git a/TelepathyQt4/Client/readiness-helper.h b/TelepathyQt4/Client/readiness-helper.h
index 4389fea..c0cf916 100644
--- a/TelepathyQt4/Client/readiness-helper.h
+++ b/TelepathyQt4/Client/readiness-helper.h
@@ -39,7 +39,20 @@ namespace Client
 
 class PendingReady;
 
-typedef QPair<QString, uint> Feature;
+class Feature : public QPair<QString, uint>
+{
+public:
+    Feature(const QString &className, uint id, bool critical = false)
+        : QPair<QString, uint>(className, id), critical(critical)
+    {
+    }
+
+    bool isCritical() const { return critical; }
+
+private:
+    bool critical;
+};
+
 typedef QSet<Feature> Features;
 
 class ReadinessHelper : public QObject
@@ -61,12 +74,14 @@ public:
                 const Features &dependsOnFeatures,
                 const QStringList &dependsOnInterfaces,
                 IntrospectFunc introspectFunc,
-                void *introspectFuncData)
+                void *introspectFuncData,
+                bool critical = false)
             : makesSenseForStatuses(makesSenseForStatuses),
               dependsOnFeatures(dependsOnFeatures),
               dependsOnInterfaces(dependsOnInterfaces),
               introspectFunc(introspectFunc),
-              introspectFuncData(introspectFuncData)
+              introspectFuncData(introspectFuncData),
+              critical(critical)
         {
         }
 
@@ -78,6 +93,7 @@ public:
         QStringList dependsOnInterfaces;
         IntrospectFunc introspectFunc;
         void *introspectFuncData;
+        bool critical;
     };
     typedef QMap<Feature, Introspectable> Introspectables;
 
@@ -99,10 +115,11 @@ public:
     Features actualFeatures() const;
     Features missingFeatures() const;
 
-    bool isReady(const Features &features, bool onlySatisfied) const;
+    bool isReady(const Feature &feature) const;
+    bool isReady(const Features &features) const;
     PendingReady *becomeReady(const Features &requestedFeatures);
 
-    void setIntrospectCompleted(Feature feature, bool success);
+    void setIntrospectCompleted(const Feature &feature, bool success);
 
 Q_SIGNALS:
     void statusReady(uint status);
diff --git a/TelepathyQt4/Client/text-channel.cpp b/TelepathyQt4/Client/text-channel.cpp
index 906258e..72a627f 100644
--- a/TelepathyQt4/Client/text-channel.cpp
+++ b/TelepathyQt4/Client/text-channel.cpp
@@ -285,7 +285,7 @@ void TextChannel::Private::introspectMessageSentSignal(
 void TextChannel::Private::updateInitialMessages()
 {
     if (!readinessHelper->requestedFeatures().contains(FeatureMessageQueue) ||
-        readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+        readinessHelper->isReady(Features() << FeatureMessageQueue)) {
         return;
     }
 
@@ -302,7 +302,7 @@ void TextChannel::Private::updateInitialMessages()
 void TextChannel::Private::updateCapabilities()
 {
     if (!readinessHelper->requestedFeatures().contains(FeatureMessageCapabilities) ||
-        readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+        readinessHelper->isReady(Features() << FeatureMessageQueue)) {
         return;
     }
 
@@ -715,7 +715,7 @@ void TextChannel::processQueue()
 
     if (mPriv->incompleteMessages.isEmpty()) {
         if (mPriv->readinessHelper->requestedFeatures().contains(FeatureMessageQueue) &&
-            !mPriv->readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+            !mPriv->readinessHelper->isReady(Features() << FeatureMessageQueue)) {
             debug() << "incompleteMessages empty for the first time: "
                 "FeatureMessageQueue is now ready";
             mPriv->readinessHelper->setIntrospectCompleted(FeatureMessageQueue, true);
@@ -952,12 +952,12 @@ void TextChannel::gotProperties(QDBusPendingCallWatcher *watcher)
 
         ReadinessHelper *readinessHelper = mPriv->readinessHelper;
         if (readinessHelper->requestedFeatures().contains(FeatureMessageQueue) &&
-            !readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+            !readinessHelper->isReady(Features() << FeatureMessageQueue)) {
             readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false);
         }
 
         if (readinessHelper->requestedFeatures().contains(FeatureMessageCapabilities) &&
-            !readinessHelper->isReady(Features() << FeatureMessageCapabilities, false)) {
+            !readinessHelper->isReady(Features() << FeatureMessageCapabilities)) {
             readinessHelper->setIntrospectCompleted(FeatureMessageCapabilities, false);
         }
         return;
-- 
1.5.6.5




More information about the telepathy-commits mailing list