[asterisk-scf-commits] asterisk-scf/release/ice-util-cpp.git branch "master" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri May 6 10:24:49 CDT 2011


branch "master" has been updated
       via  2d8c9dee3f4fa63ff0125bf4ccb1fc6862612f76 (commit)
      from  196bcc8df23a43034975385357819c14557c9530 (commit)

Summary of changes:
 .../include/AsteriskSCF/StateReplicator.h          |  117 ++++++++++++++------
 StateReplicator/test/MockStateReplicatorListener.h |   51 +++++++++-
 StateReplicator/test/TestStateReplicator.cpp       |   25 +---
 .../testslice/StateReplicatorTestIf.ice            |    4 +-
 4 files changed, 140 insertions(+), 57 deletions(-)


- Log -----------------------------------------------------------------
commit 2d8c9dee3f4fa63ff0125bf4ccb1fc6862612f76
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Apr 18 22:23:49 2011 -0500

    Added support for removing state by items rather than just string ids to allow visitors in remove implementations.

diff --git a/StateReplicator/include/AsteriskSCF/StateReplicator.h b/StateReplicator/include/AsteriskSCF/StateReplicator.h
index 6ecebce..0186142 100644
--- a/StateReplicator/include/AsteriskSCF/StateReplicator.h
+++ b/StateReplicator/include/AsteriskSCF/StateReplicator.h
@@ -30,14 +30,15 @@ namespace StateReplication
  * of the fields from the order in which they were added to the collection. If an item is removed and
  * re-added later, it goes to the back of the list.
  *  - The state item type is assumed to have a public field named "key" which is of type "K".
-
- The Replicator should implement (at a minimum) these operations:
+ *
+  The Replicator should implement (at a minimum) these operations:
  interface FooStateReplicator
  {
  void addListener(TestStateReplicatorListener *listener);
  void removeListener(TestStateReplicatorListener *listener);
  void setState (FooStateItemSeq items);
- void removeState(FooKeySeq items);
+ void removeState(FooKeySeq items);       // deprecated
+ void removeStateForItems(FooStateItemSeq items);
  idempotent TestStateItemSeq getState(FooKeySeq itemKeys);
  idempotent TestStateItemSeq getAllState();
  };
@@ -45,12 +46,15 @@ namespace StateReplication
  The Listener should implement (at a minimum) these operations:
  interface FooStateReplicatorListener
  {
- void stateRemoved(FooKeySeq itemKeys);
+ void stateRemoved(FooKeySeq itemKeys); // deprecated 
+ void stateRemovedForItems(FooStateItemSeq items);
  void stateSet(FooStateItemSeq items);
  };
 
  * NOTE: - The process should be made asynchronous.
  * NOTE: - Should probably use IceStorm for forwarding to all listeners.
+ * One-way proxies can be passed in as listeners, but this may alter the order
+ * in which updates are received by the listener.
  */
 template<typename R, typename S, typename K, typename L>
 class StateReplicator : public R
@@ -66,45 +70,73 @@ public:
     public:
         SetStateNotice(const U& stateSeq) : mStateSeq(stateSeq) {}
         ~SetStateNotice() {}
-        void operator() (T x)
+        void operator() (const T& x)
         {
             try
             {
                 x->stateSet(mStateSeq);
             }
-            catch(const Ice::Exception&)
-            {
-            }
             catch(...)
             {
+                // For now we're silently consuming exceptions to 
+                // insure all listeners are notified. Future efforts
+                // in creating a robust state replication back-end 
+                // should at the very least log these exceptions.
             }
         }
         U mStateSeq;
     };
 
     /**
-     * Functor for forwarding removeState() notices.
+     * Functor for forwarding removeStateByKey() notices.
      */
-    template<typename T, typename V> class RemoveStateNotice
+    template<typename T, typename V> class RemoveStateByKeyNotice
     {
         // Types: T - Listener type, V - Key Item seq.
     public:
-        RemoveStateNotice(const V& keys) : mKeys(keys) {}
-        ~RemoveStateNotice() {}
-        void operator() (T x)
+        RemoveStateByKeyNotice(const V& keys) : mKeys(keys) {}
+        ~RemoveStateByKeyNotice() {}
+        void operator() (const T& x)
         {
             try
             {
                 x->stateRemoved(mKeys);
             }
-            catch(const Ice::Exception&)
+            catch(...)
             {
+                // For now we're silently consuming exceptions to 
+                // insure all listeners are notified. Future efforts
+                // in creating a robust state replication back-end 
+                // should at the very least log these exceptions.
+            }
+        }
+        V mKeys;
+    };
+
+    /**
+     * Functor for forwarding removeState() notices.
+     */
+    template<typename T, typename U> class RemoveStateNotice
+    {
+        // Types: T - Listener type, U - State Item seq.
+    public:
+        RemoveStateNotice(const U& stateSeq) : mStateSeq(stateSeq) {}
+        ~RemoveStateNotice() {}
+        void operator() (T x)
+        {
+            try
+            {
+                x->stateRemovedForItems(mStateSeq);
             }
             catch(...)
             {
+                // For now we're silently consuming exceptions to 
+                // insure all listeners are notified. Future efforts
+                // in creating a robust state replication back-end 
+                // should at the very least log these exceptions.
             }
         }
-        V mKeys;
+        U mStateSeq;
     };
 
     /**
@@ -115,7 +147,7 @@ public:
     public:
         IdentifyListener(const T& listener) : mListener(listener) {}
         ~IdentifyListener() {}
-        bool operator() (T x) {return (x->ice_getIdentity() == mListener->ice_getIdentity());}
+        bool operator() (const T& x) {return (x->ice_getIdentity() == mListener->ice_getIdentity());}
         T mListener;
     };
 
@@ -124,7 +156,7 @@ public:
     public:
         MatchItem(const D& key) : mKey(key) {}
         ~MatchItem() {}
-        bool operator() (T x) {return (x->key == mKey); }
+        bool operator() (const T& x) {return (x->key == mKey); }
         D mKey;
     };
 
@@ -143,18 +175,9 @@ public:
             mListeners.push_back(listener);
         }
 
-        // Give this listener the current state.
+        // Give this new listener the current state.
         boost::shared_lock<boost::shared_mutex> lock(mStateLock);
-        try
-        {
-            listener->stateSet(mStateItems);
-        }
-        catch(const Ice::Exception&)
-        {
-        }
-        catch(...)
-        {
-        }
+        listener->stateSet(mStateItems);
     }
 
     /**
@@ -186,19 +209,16 @@ public:
      */
     void clearState()
     {
-        std::vector<K> allIds;
+        std::vector<S> items;
 
         {   // critical scope
             boost::unique_lock<boost::shared_mutex> lock(mStateLock);
-            for(typename std::vector<S>::const_iterator it = mStateItems.begin(); it != mStateItems.end(); ++it)
-            {
-                allIds.push_back((*it)->key);
-            }
+            items = mStateItems;
             mStateItems.clear();
         }
 
         boost::shared_lock<boost::shared_mutex> lock(mListenerLock);
-        for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<K> >(allIds));
+        for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<S> >(items));
     }
 
     /**
@@ -231,7 +251,7 @@ public:
     }
 
     /**
-     * Remove the specified state variables, and notify listeners.
+     * Remove specified state variables identified by the specified keys, and notify listeners.
      * @Override
      */
     void removeState(const std::vector<K>& ids, const Ice::Current& = ::Ice::Current())
@@ -251,7 +271,32 @@ public:
         }
 
         boost::shared_lock<boost::shared_mutex> lock(mListenerLock);
-        for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<K> >(ids));
+        for_each(mListeners.begin(), mListeners.end(), RemoveStateByKeyNotice<L,std::vector<K> >(ids));
+    }
+
+    /**
+     * Remove state variables, and notify listeners. 
+     * The item's key is used to identify the item to remove. Any other field is ignored. 
+     * @Override
+     */
+    void removeStateForItems(const std::vector<S>& items, const Ice::Current& = ::Ice::Current())
+    {
+        {   // critical scope
+            boost::unique_lock<boost::shared_mutex> lock(mStateLock);
+
+            for (typename std::vector<S>::const_iterator itemIter = items.begin(); itemIter != items.end(); ++itemIter)
+            {
+                typename std::vector<S>::iterator locateIt = std::find_if(mStateItems.begin(), mStateItems.end(), MatchItem<S,K >((*itemIter)->key));
+
+                if (locateIt != mStateItems.end())
+                {
+                    mStateItems.erase(locateIt);
+                }
+            }
+        }
+
+        boost::shared_lock<boost::shared_mutex> lock(mListenerLock);
+        for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<S> >(items));
     }
 
     /**
diff --git a/StateReplicator/test/MockStateReplicatorListener.h b/StateReplicator/test/MockStateReplicatorListener.h
index 33dba6d..e91da85 100644
--- a/StateReplicator/test/MockStateReplicatorListener.h
+++ b/StateReplicator/test/MockStateReplicatorListener.h
@@ -23,10 +23,19 @@ namespace AsteriskSCF
 namespace StateReplicatorTest
 {
 
+class MatchItem
+{
+public:
+    MatchItem(const std::string& key) : mKey(key) {}
+    ~MatchItem() {}
+    bool operator() (const ::AsteriskSCF::StateReplicatorTest::V1::TestStateItemPtr& x) {return (x->key == mKey); }
+    std::string mKey;
+};
+
 class MockStateReplicatorListenerImpl : public AsteriskSCF::StateReplicatorTest::V1::TestStateReplicatorListener
 {
 public:
-    MockStateReplicatorListenerImpl() : mRemoveStateCalled(false), mSetStateCalled(true)
+    MockStateReplicatorListenerImpl() : mRemoveStateCalled(false), mRemoveStateForItemsCalled(false), mSetStateCalled(true)
     {
     }
 
@@ -34,6 +43,16 @@ public:
     {
         mItemKeys = itemKeys;
         mRemoveStateCalled = true;
+
+        removeByKeys(itemKeys);
+    }
+
+    void stateRemovedForItems(const ::AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq& items,  const ::Ice::Current& )
+    {
+        mRemoveItems = items;
+        mRemoveStateForItemsCalled = true;
+
+        removeByItems(items);
     }
 
     void stateSet(const ::AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq& items, const ::Ice::Current& )
@@ -45,15 +64,45 @@ public:
     void reset()
     {
         mRemoveStateCalled = false;
+        mRemoveStateForItemsCalled = false;
         mSetStateCalled = false;
         mStateItems.clear();
         mItemKeys.clear();
+        mRemoveItems.clear();
+    }
+
+    void removeByKeys(const ::Ice::StringSeq& itemKeys)
+    {
+        for (::Ice::StringSeq::const_iterator keyIter = itemKeys.begin(); keyIter != itemKeys.end(); ++keyIter)
+        {
+            ::AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq::iterator locateIt = std::find_if(mStateItems.begin(), mStateItems.end(), MatchItem(*keyIter));
+
+            if (locateIt != mStateItems.end())
+            {
+                mStateItems.erase(locateIt);
+            }
+        }
+    }
+
+    void removeByItems(const ::AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq& itemSeq)
+    {
+        for (::AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq::const_iterator itemIter = itemSeq.begin(); itemIter != itemSeq.end(); ++itemIter)
+        {
+            ::AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq::iterator locateIt = std::find_if(mStateItems.begin(), mStateItems.end(), MatchItem((*itemIter)->key));
+
+            if (locateIt != mStateItems.end())
+            {
+                mStateItems.erase(locateIt);
+            }
+        }
     }
 
 public:
     bool mRemoveStateCalled;
+    bool mRemoveStateForItemsCalled;
     bool mSetStateCalled;
     AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq mStateItems;
+    AsteriskSCF::StateReplicatorTest::V1::TestStateItemSeq mRemoveItems;
     Ice::StringSeq mItemKeys;
 };
 typedef ::IceInternal::ProxyHandle<MockStateReplicatorListenerImpl> MockStateReplicatorListenerImplPrx;
diff --git a/StateReplicator/test/TestStateReplicator.cpp b/StateReplicator/test/TestStateReplicator.cpp
index 6058916..13d712e 100644
--- a/StateReplicator/test/TestStateReplicator.cpp
+++ b/StateReplicator/test/TestStateReplicator.cpp
@@ -215,7 +215,6 @@ public:
  */
 BOOST_AUTO_TEST_CASE(AddRemoveListeners)
 {
-    bool addListenerSucceeded(true);
     try
     {
         SharedTestData::instance.mTestStateReplicatorPrx->addListener(SharedTestData::instance.mTestStateListener1Prx);
@@ -223,14 +222,11 @@ BOOST_AUTO_TEST_CASE(AddRemoveListeners)
     }
     catch (...)
     {
-        addListenerSucceeded = false;
-        BOOST_TEST_MESSAGE("Exception adding Listeners.");
+        BOOST_FAIL("Exception adding Listeners.");
     }
 
-    BOOST_CHECK(addListenerSucceeded);
     BOOST_CHECK(SharedTestData::instance.mTestReplicatorImplPtr->getListenerCount() == 2);
 
-    bool removeListenerSucceeded(true);
     try
     {
         SharedTestData::instance.mTestStateReplicatorPrx->removeListener(SharedTestData::instance.mTestStateListener1Prx);
@@ -238,10 +234,8 @@ BOOST_AUTO_TEST_CASE(AddRemoveListeners)
     }
     catch (...)
     {
-        removeListenerSucceeded = false;
-        BOOST_TEST_MESSAGE("Exception removing Listener.");
+        BOOST_FAIL("Exception removing Listener.");
     }
-    BOOST_CHECK(removeListenerSucceeded);
     BOOST_CHECK(SharedTestData::instance.mTestReplicatorImplPtr->getListenerCount() == 0);
 
 
@@ -256,20 +250,16 @@ BOOST_FIXTURE_TEST_CASE(PushData, PerTestFixture)
     try
     {
         SharedTestData::instance.mTestStateReplicatorPrx->setState(mTestValues);
-
     }
     catch(const IceUtil::Exception &ie)
     {
-        bool IceException(false);
         string msg = "Exception pushing state data.";
         msg += ie.what();
-        BOOST_TEST_MESSAGE(msg);
-        BOOST_CHECK(IceException);
+        BOOST_FAIL(msg);
     }
     catch (...)
     {
-        bool unknownException(false);
-        BOOST_CHECK(unknownException);
+        BOOST_FAIL("Unknown exception.");
     }
 
     BOOST_CHECK(SharedTestData::instance.mMockStateListener1Ptr->mStateItems.size() == 3);
@@ -301,16 +291,13 @@ BOOST_FIXTURE_TEST_CASE(ForwardRemoveState, PerTestFixture)
     }
     catch(const IceUtil::Exception &ie)
     {
-        bool IceException(false);
         string msg = "Exception removing state data.";
         msg += ie.what();
-        BOOST_TEST_MESSAGE(msg);
-        BOOST_CHECK(IceException);
+        BOOST_FAIL(msg);
     }
     catch (...)
     {
-        bool unknownException(false);
-        BOOST_CHECK(unknownException);
+        BOOST_FAIL("Unknown exception.");
     }
 
     BOOST_CHECK(SharedTestData::instance.mMockStateListener1Ptr->mItemKeys.size() == 2);
diff --git a/StateReplicator/testslice/StateReplicatorTestIf.ice b/StateReplicator/testslice/StateReplicatorTestIf.ice
index 6288901..bd54489 100644
--- a/StateReplicator/testslice/StateReplicatorTestIf.ice
+++ b/StateReplicator/testslice/StateReplicatorTestIf.ice
@@ -34,6 +34,7 @@ module V1
    interface TestStateReplicatorListener
    {
       void stateRemoved(Ice::StringSeq itemKeys);
+	  void stateRemovedForItems(TestStateItemSeq items);
 	  void stateSet(TestStateItemSeq items);
    };
 
@@ -42,7 +43,8 @@ module V1
       void addListener(TestStateReplicatorListener *listener);
 	  void removeListener(TestStateReplicatorListener *listener);
 	  void setState (TestStateItemSeq items);
-	  void removeState(Ice::StringSeq items);
+	  void removeState(Ice::StringSeq itemKeys);
+	  void removeStateForItems(TestStateItemSeq items);
 	  idempotent TestStateItemSeq getState(Ice::StringSeq itemKeys);
 	  idempotent TestStateItemSeq getAllState();
    };

-----------------------------------------------------------------------


-- 
asterisk-scf/release/ice-util-cpp.git



More information about the asterisk-scf-commits mailing list