[asterisk-scf-commits] asterisk-scf/integration/statereplicator.git branch "master" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon Sep 27 15:42:20 CDT 2010


branch "master" has been updated
       via  69291de42b84ff0a6a2968bf7a81836860137784 (commit)
      from  a9fb72738fb89252f60086992444a07a3a89d2a8 (commit)

Summary of changes:
 src/StateReplicator.h        |   70 +++++++++++++++++++-----------
 test/SharedTestData.h        |    3 +-
 test/TestStateReplicator.cpp |   96 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 139 insertions(+), 30 deletions(-)


- Log -----------------------------------------------------------------
commit 69291de42b84ff0a6a2968bf7a81836860137784
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Mon Sep 27 15:38:55 2010 -0500

    Altered implementation to always present state items to listeners in the same
    order they were added to the State Replicator.

diff --git a/src/StateReplicator.h b/src/StateReplicator.h
index 91f0921..fc0233b 100644
--- a/src/StateReplicator.h
+++ b/src/StateReplicator.h
@@ -15,7 +15,9 @@ namespace StateReplication
 {
 
 /**
- * Templatization of a state replicator.  
+ * Templatization of a state replicator.  This particular implementation preserves the order 
+ * 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:
@@ -37,6 +39,7 @@ namespace StateReplication
    };
 
  * NOTE: - The process should be made asynchronous.  
+ * NOTE: - Should probably use IceStorm for forwarding to all listeners. 
  */
 template<typename R, typename S, typename K, typename L>  
 class StateReplicator : public R
@@ -81,6 +84,15 @@ public:
       T mListener;
    };
 
+   template<typename T, typename D> class MatchItem
+   {
+   public:
+      MatchItem(const D& key) : mKey(key) {}
+      ~MatchItem() {}
+      bool operator() (T x) {return (x->key == mKey); }
+      D mKey;
+   };
+
 public:
    StateReplicator() {};
    virtual ~StateReplicator() {};
@@ -92,6 +104,9 @@ public:
    void addListener(const L& listener, const Ice::Current& = ::Ice::Current())
    {
       mListeners.push_back(listener);
+
+      // Give this listener the current state.
+      listener->stateSet(mStateItems);
    }
 
    /**
@@ -123,14 +138,14 @@ public:
    {
       std::vector<K> allIds;
 
-      for(typename std::map<K, S>::const_iterator it = mStateItemMap.begin(); it != mStateItemMap.end(); ++it)
+      for(typename std::vector<S>::const_iterator it = mStateItems.begin(); it != mStateItems.end(); ++it)
       {
-         allIds.push_back(it->first);
+         allIds.push_back((*it)->key);
       }
 
-      for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<K> >(allIds));
+      mStateItems.clear();
 
-      mStateItemMap.clear();
+      for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<K> >(allIds));
    }
 
    /**
@@ -142,15 +157,15 @@ public:
       for (typename std::vector<S>::const_iterator iter = items.begin();
             iter != items.end(); ++iter)
       {
-         typename std::map<K, S>::iterator mapItem = mStateItemMap.find((*iter)->key);
+         typename std::vector<S>::iterator it = std::find_if(mStateItems.begin(), mStateItems.end(), MatchItem<S,K >((*iter)->key));
 
-         if (mapItem != mStateItemMap.end())
-         {
-            (*mapItem).second = (*iter);
+         if (it != mStateItems.end())
+         { 
+            (*it) = (*iter);
          }
          else
          {
-            mStateItemMap[(*iter)->key] = (*iter);
+            mStateItems.push_back(*iter);
          }
       }
 
@@ -163,9 +178,14 @@ public:
     */
    void removeState(const std::vector<K>& ids, const Ice::Current& = ::Ice::Current())
    {
-      for (typename std::vector<K>::const_iterator iter = ids.begin(); iter != ids.end(); ++iter)
+      for (typename std::vector<K>::const_iterator keyIter = ids.begin(); keyIter != ids.end(); ++keyIter)
       {
-         mStateItemMap.erase(*iter);
+         typename std::vector<S>::iterator locateIt = std::find_if(mStateItems.begin(), mStateItems.end(), MatchItem<S,K >(*keyIter));
+
+         if (locateIt != mStateItems.end())
+         {
+            mStateItems.erase(locateIt);
+         }
       }
 
       for_each(mListeners.begin(), mListeners.end(), RemoveStateNotice<L,std::vector<K> >(ids));
@@ -179,9 +199,15 @@ public:
    { 
       std::vector<S> results;
 
-      for(typename std::vector<K>::const_iterator it = itemKeys.begin(); it != itemKeys.end(); ++it)
+      for(typename std::vector<K>::const_iterator keyIt = itemKeys.begin(); keyIt != itemKeys.end(); ++keyIt)
       {
-         results.push_back(mStateItemMap[(*it)]);
+         typename std::vector<S>::iterator locateIt = std::find_if(mStateItems.begin(), mStateItems.end(), MatchItem<S,K >(*keyIt));
+
+         if (locateIt != mStateItems.end())
+         {
+            results.push_back(*locateIt);
+         }
+
       }
       return results;
    }
@@ -192,13 +218,7 @@ public:
     */
    std::vector<S> getAllState(const Ice::Current& = ::Ice::Current())
    {
-      std::vector<S> results;
-
-      for(typename std::map<K, S>::const_iterator it = mStateItemMap.begin(); it != mStateItemMap.end(); ++it)
-      {
-         results.push_back(it->second);
-      }
-      return results;
+      return mStateItems;
    }
 
    /**
@@ -211,9 +231,9 @@ public:
 
 private:
    std::vector<L> mListeners;
-   std::map<K, S > mStateItemMap;
+   std::vector<S> mStateItems;
+   
 };
 
-
-};
-};
+} // end namespace StateReplication
+} // end namespace AsteriskSCF
diff --git a/test/SharedTestData.h b/test/SharedTestData.h
index 5a89e94..8a93591 100644
--- a/test/SharedTestData.h
+++ b/test/SharedTestData.h
@@ -41,10 +41,11 @@ public:
 
    MockStateReplicatorListenerImplPtr mMockStateListener1Ptr;
    MockStateReplicatorListenerImplPtr mMockStateListener2Ptr;
+   MockStateReplicatorListenerImplPtr mMockStateListener3Ptr;
    
    AsteriskSCF::StateReplicatorTest::V1::TestStateReplicatorListenerPrx mTestStateListener1Prx;
    AsteriskSCF::StateReplicatorTest::V1::TestStateReplicatorListenerPrx mTestStateListener2Prx;
-
+   AsteriskSCF::StateReplicatorTest::V1::TestStateReplicatorListenerPrx mTestStateListener3Prx;
 };
 
 }; // StateReplicatorTest
diff --git a/test/TestStateReplicator.cpp b/test/TestStateReplicator.cpp
index b4afdce..d121ca2 100644
--- a/test/TestStateReplicator.cpp
+++ b/test/TestStateReplicator.cpp
@@ -76,6 +76,10 @@ struct GlobalIceFixture
          SharedTestData::instance.mMockStateListener2Ptr = new MockStateReplicatorListenerImpl();
          SharedTestData::instance.adapter_in->add(SharedTestData::instance.mMockStateListener2Ptr, SharedTestData::instance.communicator_in->stringToIdentity(listenerId2));
 
+         string listenerId3("Listener3");
+         SharedTestData::instance.mMockStateListener3Ptr = new MockStateReplicatorListenerImpl();
+         SharedTestData::instance.adapter_in->add(SharedTestData::instance.mMockStateListener3Ptr, SharedTestData::instance.communicator_in->stringToIdentity(listenerId3));
+
          SharedTestData::instance.adapter_in->activate();
 
          // Now that the adapter has been activated, get a local proxy to the replicator. 
@@ -88,6 +92,9 @@ struct GlobalIceFixture
          Ice::ObjectPrx listener2ObjectPrx = SharedTestData::instance.adapter_in->createDirectProxy(SharedTestData::instance.communicator_in->stringToIdentity(listenerId2));
          SharedTestData::instance.mTestStateListener2Prx = TestStateReplicatorListenerPrx::checkedCast(listener2ObjectPrx);
 
+         Ice::ObjectPrx listener3ObjectPrx = SharedTestData::instance.adapter_in->createDirectProxy(SharedTestData::instance.communicator_in->stringToIdentity(listenerId3));
+         SharedTestData::instance.mTestStateListener3Prx = TestStateReplicatorListenerPrx::checkedCast(listener3ObjectPrx);
+
       }
       catch (const Ice::Exception& ex)
       {
@@ -276,6 +283,7 @@ BOOST_FIXTURE_TEST_CASE(ForwardRemoveState, PerTestFixture)
 	try
    {
       SharedTestData::instance.mTestStateReplicatorPrx->setState(mTestValues);
+      // {FooBabar, BarMouse, FooDumbo} 
 
       Ice::StringSeq keys;
       keys.push_back("FooBabar");
@@ -302,7 +310,7 @@ BOOST_FIXTURE_TEST_CASE(ForwardRemoveState, PerTestFixture)
 
    BOOST_CHECK(SharedTestData::instance.mMockStateListener1Ptr->mItemKeys.front() == "FooBabar");
  
-   BOOST_TEST_MESSAGE("Completed RemoveState test.");
+   BOOST_TEST_MESSAGE("Completed ForwardRemoveState test.");
 
 }
 
@@ -315,7 +323,8 @@ BOOST_FIXTURE_TEST_CASE(RemoveState, PerTestFixture)
 
 	try
    {
-      // Set the basic 3 items of state.
+      // Set the basic 3 items of state. 
+      // {FooBabar, BarMouse, FooDumbo} 
       SharedTestData::instance.mTestStateReplicatorPrx->setState(mTestValues);
 
       // Try removing two of them.
@@ -342,7 +351,6 @@ BOOST_FIXTURE_TEST_CASE(RemoveState, PerTestFixture)
    }
 
    BOOST_CHECK(retrievedValues.size() == 1);
-   BOOST_CHECK(retrievedValues.size() == 1);
 
    BOOST_CHECK(retrievedValues.front()->key == "BarMouse");
  
@@ -359,6 +367,7 @@ BOOST_FIXTURE_TEST_CASE(GetSomeState, PerTestFixture)
 	try
    {
       SharedTestData::instance.mTestStateReplicatorPrx->setState(mTestValues);
+      // {FooBabar, BarMouse, FooDumbo} 
 
       Ice::StringSeq keys;
       keys.push_back("FooBabar");
@@ -381,9 +390,88 @@ BOOST_FIXTURE_TEST_CASE(GetSomeState, PerTestFixture)
    }
 
    BOOST_CHECK(retrievedValues.size() == 2);
-   BOOST_CHECK(retrievedValues.size() == 2);
 
    BOOST_CHECK(retrievedValues.front()->key == "FooBabar");
  
    BOOST_TEST_MESSAGE("Completed GetSomeState test.");
+}
+
+/**
+ * Test order of data sent to listeners.
+ */
+BOOST_FIXTURE_TEST_CASE(PreserveOrder, PerTestFixture)
+{
+   TestStateItemSeq retrievedValues;
+
+	try
+   {
+      SharedTestData::instance.mTestStateReplicatorPrx->setState(mTestValues);
+
+      // {FooBabar, BarMouse, FooDumbo} 
+      Ice::StringSeq keys;
+      keys.push_back("BarMouse");
+      SharedTestData::instance.mTestStateReplicatorPrx->removeState(keys);
+      // {FooBabar, FooDumbo} 
+
+      TestStateItemSeq moreItems;
+      TestStateItemBarPtr item1 = new TestStateItemBar();
+      item1->key = "Extra";
+      moreItems.push_back(item1);
+
+      // Re-add BarMouse
+      TestStateItemBarPtr item2 = new TestStateItemBar();
+      item2->key = "BarMouse";
+      moreItems.push_back(item2);
+
+      SharedTestData::instance.mTestStateReplicatorPrx->setState(moreItems);
+      // {FooBabar, FooDumbo, Extra, BarMouse} 
+
+      retrievedValues = SharedTestData::instance.mTestStateReplicatorPrx->getAllState();
+   }
+   catch(const IceUtil::Exception &ie)
+   {
+      bool IceException(false);
+      string msg = "Exception altering state data.";
+      msg += ie.what();
+      BOOST_TEST_MESSAGE(msg);
+      BOOST_CHECK(IceException);
+   }
+   catch (...)
+   {
+      bool unknownException(false);
+      BOOST_CHECK(unknownException);
+   }
+
+   BOOST_CHECK(retrievedValues.size() == 4);
+
+   BOOST_CHECK(retrievedValues[0]->key == "FooBabar");
+   BOOST_CHECK(retrievedValues[1]->key == "FooDumbo");
+   BOOST_CHECK(retrievedValues[2]->key == "Extra");
+   BOOST_CHECK(retrievedValues[3]->key == "BarMouse");
+
+   try
+   {
+      //Insure that a late joiner is pushed the correct current state, in correct order.
+      SharedTestData::instance.mTestStateReplicatorPrx->addListener(SharedTestData::instance.mTestStateListener3Prx);
+
+      // NOTE: This test currently is reliable only because we are NOT doing asynchronous sends to the listeners. 
+      // Will need a delay when asynch.
+      BOOST_CHECK(SharedTestData::instance.mMockStateListener3Ptr->mStateItems.size() == 4);
+
+      BOOST_CHECK(SharedTestData::instance.mMockStateListener3Ptr->mStateItems[0]->key == "FooBabar");
+      BOOST_CHECK(SharedTestData::instance.mMockStateListener3Ptr->mStateItems[1]->key == "FooDumbo");
+      BOOST_CHECK(SharedTestData::instance.mMockStateListener3Ptr->mStateItems[2]->key == "Extra");
+      BOOST_CHECK(SharedTestData::instance.mMockStateListener3Ptr->mStateItems[3]->key == "BarMouse");
+   }
+   catch(const IceUtil::Exception &ie)
+   {
+      bool IceException(false);
+      string msg = "Exception adding a late listener.";
+      msg += ie.what();
+      BOOST_TEST_MESSAGE(msg);
+      BOOST_CHECK(IceException);
+   }
+
+   BOOST_TEST_MESSAGE("Completed PreserveOrder test.");
+
 }
\ No newline at end of file

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


-- 
asterisk-scf/integration/statereplicator.git



More information about the asterisk-scf-commits mailing list