[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