[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