[asterisk-scf-commits] asterisk-scf/integration/servicediscovery.git branch "retry_deux" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Fri Apr 6 08:09:47 CDT 2012
branch "retry_deux" has been updated
via f9677e4b65bb86cf31058c423dcae52d47558990 (commit)
from bf24a105985c98d18103138fab480ecf4e263f88 (commit)
Summary of changes:
.../ServiceLocatorStateReplicationIf.ice | 99 +++++-----
src/ServiceLocator.cpp | 131 ++++++++++---
src/ServiceLocatorManagement.cpp | 114 +++++++++---
src/ServiceLocatorStateListener.cpp | 200 ++++++++++++--------
src/ServiceManagement.cpp | 135 ++++++++++----
test/TestServiceLocator.cpp | 135 +++++++++++++-
6 files changed, 587 insertions(+), 227 deletions(-)
- Log -----------------------------------------------------------------
commit f9677e4b65bb86cf31058c423dcae52d47558990
Author: David M. Lee <dlee at digium.com>
Date: Fri Apr 6 08:09:10 2012 -0500
Retry logic, thread safety and formatting.
diff --git a/slice/AsteriskSCF/Replication/ServiceLocator/ServiceLocatorStateReplicationIf.ice b/slice/AsteriskSCF/Replication/ServiceLocator/ServiceLocatorStateReplicationIf.ice
index 8fabc6c..65c0420 100755
--- a/slice/AsteriskSCF/Replication/ServiceLocator/ServiceLocatorStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/ServiceLocator/ServiceLocatorStateReplicationIf.ice
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2010-2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
@@ -33,52 +33,57 @@ module ServiceLocator
["suppress"]
module V1
{
- const string StateReplicatorComponentCategory = "ServiceLocatorStateReplicatorComponent";
- const string StateReplicatorDiscoveryCategory = "ServiceLocatorStateReplicator";
-
- class ServiceLocatorStateItem
- {
- string key;
- };
-
- sequence<ServiceLocatorStateItem> ServiceLocatorStateItemSeq;
-
- interface ServiceLocatorStateReplicatorListener
- {
- void stateRemoved(AsteriskSCF::System::V1::OperationContext operationContext, Ice::StringSeq itemKeys);
- void stateSet(AsteriskSCF::System::V1::OperationContext operationContext, ServiceLocatorStateItemSeq items);
- };
-
- interface ServiceLocatorStateReplicator
- {
- void addListener(AsteriskSCF::System::V1::OperationContext operationContext, ServiceLocatorStateReplicatorListener *listener);
- void removeListener(AsteriskSCF::System::V1::OperationContext operationContext, ServiceLocatorStateReplicatorListener *listener);
- void setState (AsteriskSCF::System::V1::OperationContext operationContext, ServiceLocatorStateItemSeq items);
- void removeState(AsteriskSCF::System::V1::OperationContext operationContext, Ice::StringSeq items);
- idempotent ServiceLocatorStateItemSeq getState(Ice::StringSeq itemKeys);
- idempotent ServiceLocatorStateItemSeq getAllState();
- };
-
- class ServiceLocatorServiceStateItem extends ServiceLocatorStateItem
- {
- bool suspended;
- Object *service;
- Ice::Identity managementIdentity;
- string guid;
- };
-
- class ServiceLocatorParamsStateItem extends ServiceLocatorStateItem
- {
- string serviceKey;
- AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams params;
- string compareGuid;
- };
-
- class ServiceLocatorComparatorStateItem extends ServiceLocatorStateItem
- {
- string name;
- AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsCompare *comparator;
- };
+
+const string StateReplicatorComponentCategory = "ServiceLocatorStateReplicatorComponent";
+const string StateReplicatorDiscoveryCategory = "ServiceLocatorStateReplicator";
+
+class ServiceLocatorStateItem
+{
+ string key;
+};
+
+sequence<ServiceLocatorStateItem> ServiceLocatorStateItemSeq;
+
+interface ServiceLocatorStateReplicatorListener
+{
+ idempotent void stateRemoved(AsteriskSCF::System::V1::OperationContext operationContext, Ice::StringSeq itemKeys);
+ idempotent void stateSet(AsteriskSCF::System::V1::OperationContext operationContext,
+ ServiceLocatorStateItemSeq items);
+};
+
+interface ServiceLocatorStateReplicator
+{
+ idempotent void addListener(AsteriskSCF::System::V1::OperationContext operationContext,
+ ServiceLocatorStateReplicatorListener *listener);
+ idempotent void removeListener(AsteriskSCF::System::V1::OperationContext operationContext,
+ ServiceLocatorStateReplicatorListener *listener);
+ idempotent void setState (AsteriskSCF::System::V1::OperationContext operationContext,
+ ServiceLocatorStateItemSeq items);
+ idempotent void removeState(AsteriskSCF::System::V1::OperationContext operationContext, Ice::StringSeq items);
+ idempotent ServiceLocatorStateItemSeq getState(Ice::StringSeq itemKeys);
+ idempotent ServiceLocatorStateItemSeq getAllState();
+};
+
+class ServiceLocatorServiceStateItem extends ServiceLocatorStateItem
+{
+ bool suspended;
+ Object *service;
+ Ice::Identity managementIdentity;
+ string guid;
+};
+
+class ServiceLocatorParamsStateItem extends ServiceLocatorStateItem
+{
+ string serviceKey;
+ AsteriskSCF::Core::Discovery::V1::ServiceLocatorParams params;
+ string compareGuid;
+};
+
+class ServiceLocatorComparatorStateItem extends ServiceLocatorStateItem
+{
+ string name;
+ AsteriskSCF::Core::Discovery::V1::ServiceLocatorParamsCompare *comparator;
+};
}; /* module V1 */
diff --git a/src/ServiceLocator.cpp b/src/ServiceLocator.cpp
index d1ff0ca..ea37540 100644
--- a/src/ServiceLocator.cpp
+++ b/src/ServiceLocator.cpp
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2010-2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
@@ -13,12 +13,11 @@
* the GNU General Public License Version 2. See the LICENSE.txt file
* at the top of the source tree.
*/
-
+
//
// These are moved up in include order because boost seems to have some kind of name collision on Windows.
//
#include <boost/thread.hpp>
-#include <boost/thread/shared_mutex.hpp>
#include <Ice/Ice.h>
#include <IceStorm/IceStorm.h>
@@ -32,19 +31,23 @@
#include <AsteriskSCF/System/Component/ReplicaIf.h>
#include <AsteriskSCF/CollocatedIceStorm/CollocatedIceStorm.h>
#include <AsteriskSCF/Operations/OperationContext.h>
+#include <AsteriskSCF/Operations/OperationContextCache.h>
+#include <AsteriskSCF/Operations/OperationMonitor.h>
#include "ServiceLocatorManagement.h"
#include "ServiceManagement.h"
#include "ServiceLocatorStateReplicator.h"
-using namespace std;
-using namespace AsteriskSCF;
-using namespace AsteriskSCF::System::Discovery;
-using namespace AsteriskSCF::System::Logging;
using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Operations;
using namespace AsteriskSCF::Replication::ServiceLocator::V1;
using namespace AsteriskSCF::ServiceDiscovery;
using namespace AsteriskSCF::System::Component::V1;
+using namespace AsteriskSCF::System::Discovery;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF;
+using namespace std;
namespace
{
@@ -78,53 +81,126 @@ private:
class ReplicaImpl : public Replica
{
public:
- ReplicaImpl(Ice::ObjectAdapterPtr adapter) : mAdapter(adapter), mPaused(false), mActive(true) { }
+ ReplicaImpl(Ice::ObjectAdapterPtr adapter) :
+ mOperationContextCache(OperationContextCache::create(DEFAULT_TTL_SECONDS)),
+ mAdapter(adapter),
+ mActive(true) { }
bool isActive(const Ice::Current&)
{
+ // naturally idempotent
+ boost::shared_lock<boost::shared_mutex> lock(mMutex);
return mActive;
}
- bool activate(const AsteriskSCF::System::V1::OperationContextPtr& context, const Ice::Current&)
+ bool activate(const OperationContextPtr& context, const Ice::Current&)
{
- mActive = true;
+ ContextDataPtr data = checkAndThrow(mOperationContextCache, context);
+
+ if (!data)
+ {
+ // retry detected
+ return true; // always returns true.
+ }
+
+ try
+ {
+ // it's not good to loop through the listeners while holding the lock, so make a copy
+ vector<ReplicaListenerPrx> listeners;
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mMutex);
+ mActive = true;
+ listeners = mListeners;
+ }
- for (vector<AsteriskSCF::System::Component::V1::ReplicaListenerPrx>::const_iterator listener = mListeners.begin(); listener != mListeners.end(); ++listener)
+ for (vector<ReplicaListenerPrx>::const_iterator listener = listeners.begin();
+ listener != listeners.end();
+ ++listener)
+ {
+ (*listener)->activated(AsteriskSCF::Operations::createContext(context),
+ ReplicaPrx::uncheckedCast(mAdapter->createDirectProxy(mAdapter->getCommunicator()->stringToIdentity(ReplicaServiceId))));
+ }
+ }
+ catch (const std::exception& e)
+ {
+ data->setException(e);
+ }
+ catch (...)
{
- (*listener)->activated(AsteriskSCF::Operations::createContext(context),
- ReplicaPrx::uncheckedCast(mAdapter->createDirectProxy(mAdapter->getCommunicator()->stringToIdentity(ReplicaServiceId))));
+ data->setException();
}
return true;
}
- void standby(const AsteriskSCF::System::V1::OperationContextPtr& context, const Ice::Current&)
+ void standby(const OperationContextPtr& context, const Ice::Current&)
{
- mActive = false;
+ ContextDataPtr data = checkAndThrow(mOperationContextCache, context);
- for (vector<AsteriskSCF::System::Component::V1::ReplicaListenerPrx>::const_iterator listener = mListeners.begin(); listener != mListeners.end(); ++listener)
+ if (!data)
{
- (*listener)->onStandby(AsteriskSCF::Operations::createContext(context),
- ReplicaPrx::uncheckedCast(mAdapter->createDirectProxy(mAdapter->getCommunicator()->stringToIdentity(ReplicaServiceId))));
+ // retry detected
+ return;
+ }
+
+ try
+ {
+ // it's not good to loop through the listeners while holding the lock, so make a copy
+ vector<ReplicaListenerPrx> listeners;
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mMutex);
+ mActive = false;
+ listeners = mListeners;
+ }
+
+ for (vector<ReplicaListenerPrx>::const_iterator listener = listeners.begin();
+ listener != listeners.end();
+ ++listener)
+ {
+ (*listener)->onStandby(AsteriskSCF::Operations::createContext(context),
+ ReplicaPrx::uncheckedCast(mAdapter->createDirectProxy(mAdapter->getCommunicator()->stringToIdentity(ReplicaServiceId))));
+ }
+ }
+ catch (const std::exception& e)
+ {
+ data->setException(e);
+ }
+ catch (...)
+ {
+ data->setException();
}
}
- void addListener(const AsteriskSCF::System::V1::OperationContextPtr&, const AsteriskSCF::System::Component::V1::ReplicaListenerPrx& listener, const Ice::Current&)
+ void addListener(const OperationContextPtr& context, const ReplicaListenerPrx& listener, const Ice::Current&)
{
+ if (!mOperationContextCache->addOperationContext(context))
+ {
+ // retry detected
+ return;
+ }
+ boost::unique_lock<boost::shared_mutex> lock(mMutex);
mListeners.push_back(listener);
}
- void removeListener(const AsteriskSCF::System::V1::OperationContextPtr&, const AsteriskSCF::System::Component::V1::ReplicaListenerPrx& listener, const Ice::Current&)
+ void removeListener(const OperationContextPtr& context, const ReplicaListenerPrx& listener, const Ice::Current&)
{
+ if (!mOperationContextCache->addOperationContext(context))
+ {
+ // retry detected
+ return;
+ }
+ boost::unique_lock<boost::shared_mutex> lock(mMutex);
mListeners.erase(std::remove(mListeners.begin(), mListeners.end(), listener), mListeners.end());
}
private:
- Ice::ObjectAdapterPtr mAdapter;
+ boost::shared_mutex mMutex;
+
+ OperationContextCachePtr mOperationContextCache;
- vector<AsteriskSCF::System::Component::V1::ReplicaListenerPrx> mListeners;
+ Ice::ObjectAdapterPtr mAdapter;
- bool mPaused;
+ vector<ReplicaListenerPrx> mListeners;
bool mActive;
};
@@ -155,7 +231,7 @@ private:
* actually stored. Our ServiceLocator implementation simply acts as a read-only
* frontend to it.
*/
- ServiceLocatorManagementImplPtr mLocatorServiceManagement;
+ const ServiceLocatorManagementImplPtr mLocatorServiceManagement;
};
}
@@ -165,6 +241,7 @@ void ServiceLocatorImpl::locate_async(const AMD_ServiceLocator_locatePtr& cb,
const ::Ice::Current&)
{
// delegate to the management object, where the data is kept
+ // mLocatorServiceManagement is const; no lock needed
mLocatorServiceManagement->locate(cb, params);
}
@@ -173,6 +250,7 @@ void ServiceLocatorImpl::locateAll_async(const AMD_ServiceLocator_locateAllPtr&
const ::Ice::Current&)
{
// delegate to the management object, where the data is kept
+ // mLocatorServiceManagement is const; no lock needed
mLocatorServiceManagement->locateAll(cb, params);
}
@@ -333,10 +411,7 @@ void ServiceLocatorApp::stop()
mIceStorm->stop();
}
-extern "C"
-{
-ASTSCF_DLL_EXPORT IceBox::Service* create(Ice::CommunicatorPtr)
+extern "C" ASTSCF_DLL_EXPORT IceBox::Service* create(Ice::CommunicatorPtr)
{
return new ServiceLocatorApp;
}
-}
diff --git a/src/ServiceLocatorManagement.cpp b/src/ServiceLocatorManagement.cpp
index a04fd3f..11e31dd 100644
--- a/src/ServiceLocatorManagement.cpp
+++ b/src/ServiceLocatorManagement.cpp
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2010-2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
@@ -28,19 +28,21 @@
#include <AsteriskSCF/Logger.h>
#include <AsteriskSCF/Async/ResponseCollector.h>
#include <AsteriskSCF/Operations/OperationContext.h>
+#include <AsteriskSCF/Operations/OperationMonitor.h>
#include "ServiceLocatorStateReplicationIf.h"
#include "ServiceLocatorManagement.h"
#include "ServiceManagement.h"
-using namespace std;
-using namespace AsteriskSCF::System::Discovery;
-using namespace AsteriskSCF::System::Logging;
using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Operations;
using namespace AsteriskSCF::Replication::ServiceLocator::V1;
using namespace AsteriskSCF::ServiceDiscovery;
+using namespace AsteriskSCF::System::Discovery;
+using namespace AsteriskSCF::System::Logging;
using namespace AsteriskSCF;
+using namespace std;
//
// Normally would use an anonymous namespace here, but there is a compiler
@@ -51,6 +53,9 @@ namespace ServiceLocatorManagementImplNS
const Logger& lg = getLoggerFactory().getLogger("AsteriskSCF.System.Discovery");
+typedef ContextResultData<ServiceManagementPrx> AddServiceResultData;
+typedef boost::shared_ptr<AddServiceResultData> AddServiceResultDataPtr;
+
/** Parameter type for Locator, to allow use of ResponseCollector. */
typedef std::pair<bool, ServiceManagementImplPtr> LocateParam;
@@ -321,9 +326,10 @@ public:
ServiceLocatorManagementImplPriv(const Ice::ObjectAdapterPtr& adapter,
const EventsPrx& serviceDiscoveryTopic,
const AsteriskSCF::System::Component::V1::ReplicaPtr replicaService) :
+ mOperationContextCache(OperationContextCache::create(DEFAULT_TTL_SECONDS)),
mAdapter(adapter), mLocatorTopic(serviceDiscoveryTopic), mReplicaService(replicaService)
{
- };
+ }
/**
* Shared mutex lock which protects the services and comparators.
@@ -331,6 +337,11 @@ public:
boost::shared_mutex mLock;
/**
+ * Context cache for retry detection.
+ */
+ OperationContextCachePtr mOperationContextCache;
+
+ /**
* Object adapter that our service management proxies originate from, it is
* houses the main management service.
*/
@@ -424,9 +435,16 @@ void ServiceLocatorManagementImpl::locateAll(
* Implementation of the addService method as defined in service_locator.ice
*/
ServiceManagementPrx ServiceLocatorManagementImpl::addService(
- const AsteriskSCF::System::V1::OperationContextPtr&,
+ const AsteriskSCF::System::V1::OperationContextPtr& context,
const Ice::ObjectPrx& service, const string& guid, const Ice::Current&)
{
+ std::pair<bool, AddServiceResultDataPtr> cacheHit = getContextSync<AddServiceResultDataPtr>(mImpl->mOperationContextCache, context);
+
+ if (cacheHit.first)
+ {
+ return cacheHit.second->getResult();
+ }
+
lg(Debug) << "addService(" << guid << ')';
boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
@@ -439,10 +457,12 @@ ServiceManagementPrx ServiceLocatorManagementImpl::addService(
mImpl->mServices.push_back(new_service);
- return new_service->getServiceManagementPrx();
+ ServiceManagementPrx r = new_service->getServiceManagementPrx();
+ cacheHit.second->setResult(r);
+ return r;
}
-ServiceManagementImplPtr ServiceLocatorManagementImpl::addService(const Ice::ObjectPrx& service,
+ServiceManagementImplPtr ServiceLocatorManagementImpl::addService(const Ice::ObjectPrx& service,
const std::string& guid, const Ice::Identity& identity)
{
lg(Debug) << "addService(" << guid << ')';
@@ -492,40 +512,84 @@ ServiceInfo ServiceLocatorManagementImpl::getService(const std::string &guid, co
void ServiceLocatorManagementImpl::addCompare(const AsteriskSCF::System::V1::OperationContextPtr& context, const string& guid,
const ServiceLocatorParamsComparePrx& service, const Ice::Current&)
{
- lg(Debug) << "addCompare(" << guid << ')';
- boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
-
- pair<map<string, ServiceLocatorParamsComparePrx>::iterator, bool> insertPair =
- mImpl->mCompares.insert(make_pair(guid, service));
+ ContextDataPtr data = checkAndThrow(mImpl->mOperationContextCache, context);
- if (insertPair.second == false)
+ if (!data)
{
- throw DuplicateCompare();
+ // retry detected
+ return;
}
- if (mImpl->mLocatorTopic)
+ try
+ {
+ lg(Debug) << "addCompare(" << guid << ')';
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+ pair<map<string, ServiceLocatorParamsComparePrx>::iterator, bool> insertPair =
+ mImpl->mCompares.insert(make_pair(guid, service));
+
+ if (insertPair.second == false)
+ {
+ throw DuplicateCompare();
+ }
+
+ if (mImpl->mLocatorTopic)
+ {
+ mImpl->mLocatorTopic->comparisonRegistered(AsteriskSCF::Operations::createContext(context), guid);
+ }
+ data->setCompleted();
+ }
+ catch(const std::exception& e)
{
- mImpl->mLocatorTopic->comparisonRegistered(AsteriskSCF::Operations::createContext(context), guid);
+ data->setException(e);
+ throw;
+ }
+ catch(...)
+ {
+ data->setException();
+ throw;
}
}
/**
* Implementation of the removeCompare method as defined in service_locator.ice
*/
-void ServiceLocatorManagementImpl::removeCompare(const AsteriskSCF::System::V1::OperationContextPtr& context,
+void ServiceLocatorManagementImpl::removeCompare(const AsteriskSCF::System::V1::OperationContextPtr& context,
const string& guid, const Ice::Current&)
{
- lg(Debug) << "removeCompare(" << guid << ')';
- boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
- std::map<std::string, ServiceLocatorParamsComparePrx>::size_type erased = mImpl->mCompares.erase(guid);
+ ContextDataPtr data = checkAndThrow(mImpl->mOperationContextCache, context);
- if (!erased)
+ if (!data)
{
- throw CompareNotFound();
+ // retry detected
+ return;
}
- else if (mImpl->mLocatorTopic)
+
+ try
+ {
+ lg(Debug) << "removeCompare(" << guid << ')';
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+ std::map<std::string, ServiceLocatorParamsComparePrx>::size_type erased = mImpl->mCompares.erase(guid);
+
+ if (!erased)
+ {
+ throw CompareNotFound();
+ }
+ else if (mImpl->mLocatorTopic)
+ {
+ mImpl->mLocatorTopic->comparisonUnregistered(AsteriskSCF::Operations::createContext(context), guid);
+ }
+ data->setCompleted();
+ }
+ catch(const std::exception& e)
+ {
+ data->setException(e);
+ throw;
+ }
+ catch(...)
{
- mImpl->mLocatorTopic->comparisonUnregistered(AsteriskSCF::Operations::createContext(context), guid);
+ data->setException();
+ throw;
}
}
diff --git a/src/ServiceLocatorStateListener.cpp b/src/ServiceLocatorStateListener.cpp
index fbc6bf4..fd27b06 100644
--- a/src/ServiceLocatorStateListener.cpp
+++ b/src/ServiceLocatorStateListener.cpp
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2010-2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
@@ -20,11 +20,11 @@
#include <IceUtil/UUID.h>
#include <AsteriskSCF/System/Component/ReplicaIf.h>
-// #include <AsteriskSCF/Discovery/SmartProxy.h>
-
#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
#include <AsteriskSCF/Core/Discovery/ServiceLocatorEventsIf.h>
#include <AsteriskSCF/Operations/OperationContext.h>
+#include <AsteriskSCF/Operations/OperationContextCache.h>
+#include <AsteriskSCF/Operations/OperationMonitor.h>
#include "ServiceLocatorManagement.h"
#include "ServiceManagement.h"
@@ -34,13 +34,15 @@
using namespace AsteriskSCF::Core::Discovery::V1;
using namespace AsteriskSCF::Replication::ServiceLocator::V1;
using namespace AsteriskSCF::ServiceDiscovery;
+using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::Operations;
class ServiceLocatorStateReplicatorItem
{
public:
ServiceLocatorStateReplicatorItem(const ServiceLocatorManagementImplPtr& locatorManagement) :
- mLocatorManagement(locatorManagement)
- {
+ mLocatorManagement(locatorManagement)
+ {
}
~ServiceLocatorStateReplicatorItem()
@@ -89,95 +91,126 @@ private:
struct ServiceLocatorStateReplicatorListenerImpl
{
public:
- ServiceLocatorStateReplicatorListenerImpl(ServiceLocatorManagementImplPtr management)
- : mId(IceUtil::generateUUID()), mLocatorManagement(management) {}
+ ServiceLocatorStateReplicatorListenerImpl(ServiceLocatorManagementImplPtr management) :
+ mOperationContextCache(OperationContextCache::create(DEFAULT_TTL_SECONDS)),
+ mId(IceUtil::generateUUID()), mLocatorManagement(management) {}
+
void removeStateNoticeImpl(const Ice::StringSeq& itemKeys)
{
+ boost::mutex::scoped_lock lock(mMutex);
for (Ice::StringSeq::const_iterator key = itemKeys.begin(); key != itemKeys.end(); ++key)
{
// Just erasing this from the map will cause the destructor to actually shut things down
mStateItems.erase((*key));
}
}
- void setStateNoticeImpl(const ServiceLocatorStateItemSeq& items)
+ void setStateNoticeImpl(const OperationContextPtr& context, const ServiceLocatorStateItemSeq& items)
{
- for (ServiceLocatorStateItemSeq::const_iterator item = items.begin(); item != items.end(); ++item)
+ ContextDataPtr data = checkAndThrow(mOperationContextCache, context);
+
+ if (!data)
+ {
+ // retry detected
+ return;
+ }
+
+ boost::mutex::scoped_lock lock(mMutex);
+
+ try
{
- ServiceLocatorServiceStateItemPtr serviceState;
- ServiceLocatorParamsStateItemPtr paramsState;
- ServiceLocatorComparatorStateItemPtr comparatorState;
-
- if ((serviceState = ServiceLocatorServiceStateItemPtr::dynamicCast((*item))))
- {
- std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> >::iterator i = mStateItems.find((*item)->key);
- boost::shared_ptr<ServiceLocatorStateReplicatorItem> localitem;
-
- if ((i == mStateItems.end()))
- {
- boost::shared_ptr<ServiceLocatorStateReplicatorItem> newitem(new ServiceLocatorStateReplicatorItem(mLocatorManagement));
- localitem = newitem;
- mStateItems.insert(std::make_pair((*item)->key, newitem));
- ServiceManagementImplPtr service = mLocatorManagement->addService(
- serviceState->service, serviceState->guid, serviceState->managementIdentity);
- newitem->setService(service);
- }
- else
- {
- localitem = i->second;
- }
-
- // The only thing that can be changed by a subsequent state item is the suspend status
- if (serviceState->suspended == true)
- {
- localitem->getService()->suspend(AsteriskSCF::Operations::createContext());
- }
- else
+ for (ServiceLocatorStateItemSeq::const_iterator item = items.begin(); item != items.end(); ++item)
+ {
+ ServiceLocatorServiceStateItemPtr serviceState;
+ ServiceLocatorParamsStateItemPtr paramsState;
+ ServiceLocatorComparatorStateItemPtr comparatorState;
+
+ if ((serviceState = ServiceLocatorServiceStateItemPtr::dynamicCast((*item))))
+ {
+ std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> >::iterator i = mStateItems.find((*item)->key);
+ boost::shared_ptr<ServiceLocatorStateReplicatorItem> localitem;
+
+ if ((i == mStateItems.end()))
+ {
+ boost::shared_ptr<ServiceLocatorStateReplicatorItem> newitem(new ServiceLocatorStateReplicatorItem(mLocatorManagement));
+ localitem = newitem;
+ mStateItems.insert(std::make_pair((*item)->key, newitem));
+ ServiceManagementImplPtr service = mLocatorManagement->addService(
+ serviceState->service, serviceState->guid, serviceState->managementIdentity);
+ newitem->setService(service);
+ }
+ else
+ {
+ localitem = i->second;
+ }
+
+ // The only thing that can be changed by a subsequent state item is the suspend status
+ if (serviceState->suspended == true)
+ {
+ localitem->getService()->suspend(AsteriskSCF::Operations::createContext(context));
+ }
+ else
+ {
+ localitem->getService()->unsuspend(AsteriskSCF::Operations::createContext(context));
+ }
+ }
+ else if ((paramsState = ServiceLocatorParamsStateItemPtr::dynamicCast((*item))))
{
- localitem->getService()->unsuspend(AsteriskSCF::Operations::createContext());
- }
- }
- else if ((paramsState = ServiceLocatorParamsStateItemPtr::dynamicCast((*item))))
- {
- // This is special, we have to find the respective service and then add parameters to it
- std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> >::iterator i = mStateItems.find(paramsState->serviceKey);
-
- if ((i == mStateItems.end()))
- {
- continue;
- }
-
- // Parameters are only ever added, they are never modified or removed
- i->second->getService()->addLocatorParams(AsteriskSCF::Operations::createContext(),
- paramsState->params, paramsState->compareGuid);
- }
- else if ((comparatorState = ServiceLocatorComparatorStateItemPtr::dynamicCast((*item))))
- {
- std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> >::iterator i = mStateItems.find((*item)->key);
-
- if ((i != mStateItems.end()))
- {
- // If this happens we essentially got a duplicate state item for something that should never change, so ignore it
- continue;
- }
-
- try
- {
- Ice::Current current;
- mLocatorManagement->addCompare(AsteriskSCF::Operations::createContext(), comparatorState->name, comparatorState->comparator, current);
- boost::shared_ptr<ServiceLocatorStateReplicatorItem> newitem(new ServiceLocatorStateReplicatorItem(mLocatorManagement));
- mStateItems.insert(std::make_pair((*item)->key, newitem));
- newitem->setComparator(comparatorState->name);
- }
- catch (...)
- {
- // It is possible for this to get reached if a comparator exists locally with the same name as the one we just tried to add
- }
- }
+ // This is special, we have to find the respective service and then add parameters to it
+ std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> >::iterator i = mStateItems.find(paramsState->serviceKey);
+
+ if ((i == mStateItems.end()))
+ {
+ continue;
+ }
+
+ // Parameters are only ever added, they are never modified or removed
+ i->second->getService()->addLocatorParams(AsteriskSCF::Operations::createContext(context),
+ paramsState->params, paramsState->compareGuid);
+ }
+ else if ((comparatorState = ServiceLocatorComparatorStateItemPtr::dynamicCast((*item))))
+ {
+ std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> >::iterator i = mStateItems.find((*item)->key);
+
+ if ((i != mStateItems.end()))
+ {
+ // If this happens we essentially got a duplicate state item for something that should never change, so ignore it
+ continue;
+ }
+
+ try
+ {
+ Ice::Current current;
+ mLocatorManagement->addCompare(AsteriskSCF::Operations::createContext(context), comparatorState->name, comparatorState->comparator, current);
+ boost::shared_ptr<ServiceLocatorStateReplicatorItem> newitem(new ServiceLocatorStateReplicatorItem(mLocatorManagement));
+ mStateItems.insert(std::make_pair((*item)->key, newitem));
+ newitem->setComparator(comparatorState->name);
+ }
+ catch (...)
+ {
+ // It is possible for this to get reached if a comparator exists locally with the same name as the one we just tried to add
+ }
+ }
+ }
+ }
+ catch (const std::exception& e)
+ {
+ data->setException(e);
+ }
+ catch (...)
+ {
+ assert(false);
+ data->setException();
}
}
- std::string mId;
+
+ const std::string& getId() const { return mId; }
+
+private:
+ boost::mutex mMutex;
+ OperationContextCachePtr mOperationContextCache;
+ const std::string mId;
std::map<std::string, boost::shared_ptr<ServiceLocatorStateReplicatorItem> > mStateItems;
- ServiceLocatorManagementImplPtr mLocatorManagement;
+ const ServiceLocatorManagementImplPtr mLocatorManagement;
};
ServiceLocatorStateReplicatorListenerI::ServiceLocatorStateReplicatorListenerI(const ServiceLocatorManagementImplPtr& management)
@@ -187,15 +220,16 @@ ServiceLocatorStateReplicatorListenerI::ServiceLocatorStateReplicatorListenerI(c
void ServiceLocatorStateReplicatorListenerI::stateRemoved(const AsteriskSCF::System::V1::OperationContextPtr&, const Ice::StringSeq& itemKeys, const Ice::Current&)
{
+ // naturally idempotent
mImpl->removeStateNoticeImpl(itemKeys);
}
-void ServiceLocatorStateReplicatorListenerI::stateSet(const AsteriskSCF::System::V1::OperationContextPtr&, const ServiceLocatorStateItemSeq& items, const Ice::Current&)
+void ServiceLocatorStateReplicatorListenerI::stateSet(const AsteriskSCF::System::V1::OperationContextPtr& context, const ServiceLocatorStateItemSeq& items, const Ice::Current&)
{
- mImpl->setStateNoticeImpl(items);
+ mImpl->setStateNoticeImpl(context, items);
}
bool ServiceLocatorStateReplicatorListenerI::operator==(const ServiceLocatorStateReplicatorListenerI &rhs)
{
- return mImpl->mId == rhs.mImpl->mId;
+ return mImpl->getId() == rhs.mImpl->getId();
}
diff --git a/src/ServiceManagement.cpp b/src/ServiceManagement.cpp
index d5d186a..493238a 100644
--- a/src/ServiceManagement.cpp
+++ b/src/ServiceManagement.cpp
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2010-2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
@@ -24,24 +24,28 @@
#include <IceUtil/UUID.h>
#include <boost/shared_ptr.hpp>
-#include <AsteriskSCF/Operations/OperationContext.h>
-#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
+#include <AsteriskSCF/Async/ResponseCollector.h>
#include <AsteriskSCF/Core/Discovery/ServiceLocatorEventsIf.h>
+#include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
#include <AsteriskSCF/Logger.h>
-#include <AsteriskSCF/Async/ResponseCollector.h>
+#include <AsteriskSCF/Operations/OperationContext.h>
+#include <AsteriskSCF/Operations/OperationContextCache.h>
+#include <AsteriskSCF/Operations/OperationMonitor.h>
#include "ServiceLocatorStateReplicationIf.h"
#include "ServiceLocatorManagement.h"
#include "ServiceManagement.h"
-using namespace std;
using namespace AsteriskSCF::Core::Discovery::V1;
+using namespace AsteriskSCF::Operations;
using namespace AsteriskSCF::Replication::ServiceLocator::V1;
using namespace AsteriskSCF::ServiceDiscovery;
using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::V1;
using namespace AsteriskSCF;
+using namespace std;
namespace
{
@@ -106,6 +110,7 @@ public:
ServiceManagementImplPriv(ServiceManagementImpl* impl, ServiceLocatorManagementImplPtr management,
const Ice::ObjectPrx& service, const Ice::ObjectAdapterPtr& adapter, const AsteriskSCF::System::Discovery::EventsPrx& serviceDiscoveryTopic,
const string& guid, const Ice::Identity& identity) :
+ mOperationContextCache(OperationContextCache::create(DEFAULT_TTL_SECONDS)),
mStateItem(new ServiceLocatorServiceStateItem()),
mManagement(management), mAdapter(adapter), mLocatorTopic(serviceDiscoveryTopic)
{
@@ -127,6 +132,8 @@ public:
*/
boost::shared_mutex mLock;
+ OperationContextCachePtr mOperationContextCache;
+
/**
* Service state replication item.
*/
@@ -280,8 +287,8 @@ void ServiceManagementImpl::isSupported(const ServiceLocatorParamsPtr& params, c
{
if ((*spec)->isSupported(params, myCallback))
{
- // If we get here, a match was found without needing to call an external comparator.
- // We are done.
+ // If we get here, a match was found without needing to call an external comparator.
+ // We are done.
break;
}
}
@@ -300,13 +307,13 @@ const std::string& ServiceManagementImpl::getGuid() const
* that is trying to be found.
* @param callback Callback to asynchronously rx the results.
*
- * @return True only if we determined a match without any need for calling a custom comparator.
- * Otherwise, the callback may be accumulating the results, or it's not a match.
+ * @return True only if we determined a match without any need for calling a custom comparator.
+ * Otherwise, the callback may be accumulating the results, or it's not a match.
*/
bool ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params, const IsSupportedCallbackPtr& callback)
{
- // Does the component doing the locate
- // want to filter based on category.
+ // Does the component doing the locate
+ // want to filter based on category.
if (!params->category.empty())
{
// Is this the wrong category?
@@ -319,18 +326,18 @@ bool ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params
}
}
- // Does the component doing the locate
- // want all services in the category?
+ // Does the component doing the locate
+ // want all services in the category?
if (params->service.empty())
{
- // If a comparator was provided then yield to it.
+ // If a comparator was provided then yield to it.
if (!mStateItem->compareGuid.empty())
{
mManagement->isSupported(mStateItem->compareGuid, params, callback);
return false;
}
- // Ignore the id and treat this as a wildcard search.
+ // Ignore the id and treat this as a wildcard search.
lg(Trace) << " ...isSupported" << debugPrintParams(params) + " = true. Category match explicit, wildcard match service.";
callback->result(true);
@@ -357,15 +364,15 @@ bool ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params
}
}
- // If a comparator was provided then yield to it.
+ // If a comparator was provided then yield to it.
if (!mStateItem->compareGuid.empty())
{
mManagement->isSupported(mStateItem->compareGuid, params, callback);
return false;
}
- // If we get here we have a match on service and id.
- // (and category, if one was passed in.)
+ // If we get here we have a match on service and id.
+ // (and category, if one was passed in.)
lg(Trace) << " ...isSupported" << debugPrintParams(params) + " = true";
callback->result(true);
return true;
@@ -375,9 +382,15 @@ bool ServiceLocatorParamsSpec::isSupported(const ServiceLocatorParamsPtr& params
* Implementation of the addLocatorParams method as defined in service_locator.ice
*/
void ServiceManagementImpl::addLocatorParams(
- const AsteriskSCF::System::V1::OperationContextPtr&,
+ const AsteriskSCF::System::V1::OperationContextPtr& context,
const ServiceLocatorParamsPtr& params, const std::string& compareGuid, const Ice::Current&)
{
+ if (!mImpl->mOperationContextCache->addOperationContext(context))
+ {
+ // retry detected
+ return;
+ }
+
boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
boost::shared_ptr<ServiceLocatorParamsSpec> spec(new ServiceLocatorParamsSpec(params, compareGuid, mImpl->mManagement, mImpl->mStateItem));
@@ -390,18 +403,39 @@ void ServiceManagementImpl::addLocatorParams(
*/
void ServiceManagementImpl::suspend(const AsteriskSCF::System::V1::OperationContextPtr& context, const Ice::Current&)
{
- boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+ ContextDataPtr data = checkAndThrow(mImpl->mOperationContextCache, context);
- if (!mImpl->mStateItem->suspended)
+ if (!data)
{
- lg(Info) << "Suspending " << mImpl->mStateItem->guid << " " << mImpl->mStateItem->service->ice_toString();
- mImpl->mStateItem->suspended = true;
- mImpl->mManagement->replicateState(mImpl->mStateItem);
+ // retry detected
+ return;
}
- if (mImpl->mLocatorTopic)
+ try
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+ if (!mImpl->mStateItem->suspended)
+ {
+ lg(Info) << "Suspending " << mImpl->mStateItem->guid << " " << mImpl->mStateItem->service->ice_toString();
+ mImpl->mStateItem->suspended = true;
+ mImpl->mManagement->replicateState(mImpl->mStateItem);
+ }
+
+ if (mImpl->mLocatorTopic)
+ {
+ mImpl->mLocatorTopic->serviceSuspended(AsteriskSCF::Operations::createContext(context), mImpl->mStateItem->guid);
+ }
+ data->setCompleted();
+ }
+ catch (const std::exception& e)
{
- mImpl->mLocatorTopic->serviceSuspended(AsteriskSCF::Operations::createContext(context), mImpl->mStateItem->guid);
+ data->setException(e);
+ }
+ catch (...)
+ {
+ assert(false);
+ data->setException();
}
}
@@ -410,18 +444,38 @@ void ServiceManagementImpl::suspend(const AsteriskSCF::System::V1::OperationCont
*/
void ServiceManagementImpl::unsuspend(const AsteriskSCF::System::V1::OperationContextPtr& context, const Ice::Current&)
{
- boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+ ContextDataPtr data = checkAndThrow(mImpl->mOperationContextCache, context);
- if (mImpl->mStateItem->suspended)
+ if (!data)
{
- lg(Info) << "Un-suspending " << mImpl->mStateItem->guid << " " << mImpl->mStateItem->service->ice_toString();
- mImpl->mStateItem->suspended = false;
- mImpl->mManagement->replicateState(mImpl->mStateItem);
+ // retry detected
+ return;
}
- if (mImpl->mLocatorTopic)
+ try
{
- mImpl->mLocatorTopic->serviceUnsuspended(context, mImpl->mStateItem->guid);
+ boost::unique_lock<boost::shared_mutex> lock(mImpl->mLock);
+
+ if (mImpl->mStateItem->suspended)
+ {
+ lg(Info) << "Un-suspending " << mImpl->mStateItem->guid << " " << mImpl->mStateItem->service->ice_toString();
+ mImpl->mStateItem->suspended = false;
+ mImpl->mManagement->replicateState(mImpl->mStateItem);
+ }
+
+ if (mImpl->mLocatorTopic)
+ {
+ mImpl->mLocatorTopic->serviceUnsuspended(context, mImpl->mStateItem->guid);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ data->setException(e);
+ }
+ catch (...)
+ {
+ assert(false);
+ data->setException();
}
}
@@ -440,7 +494,6 @@ ServiceStatus ServiceManagementImpl::getStatus() const
ServiceLocatorParamsSeq ServiceManagementImpl::getLocatorParams(const Ice::Current&)
{
-
boost::shared_lock<boost::shared_mutex> lock(mImpl->mLock);
ServiceLocatorParamsSeq result;
for (std::vector<boost::shared_ptr<ServiceLocatorParamsSpec> >::const_iterator iter = mImpl->mSupportedLocatorParams.begin();
@@ -456,6 +509,14 @@ ServiceLocatorParamsSeq ServiceManagementImpl::getLocatorParams(const Ice::Curre
*/
void ServiceManagementImpl::unregister(const AsteriskSCF::System::V1::OperationContextPtr& context, const Ice::Current&)
{
+ ContextDataPtr data = checkAndThrow(mImpl->mOperationContextCache, context);
+
+ if (!data)
+ {
+ // retry detected
+ return;
+ }
+
/* You'll notice no lock here. That's because we aren't actually modifying any internal state that should
* be protected, and if we did lock here there is a chance for a deadlock which is super sad.
*/
@@ -473,17 +534,19 @@ void ServiceManagementImpl::unregister(const AsteriskSCF::System::V1::OperationC
{
mImpl->mLocatorTopic->serviceUnregistered(AsteriskSCF::Operations::createContext(context), mImpl->mStateItem->guid);
}
+
+ data->setCompleted();
}
catch(const std::exception& e)
{
lg(Error) << BOOST_CURRENT_FUNCTION << " : " << e.what();
+ data->setException(e);
throw;
}
catch(...)
{
lg(Error) << BOOST_CURRENT_FUNCTION << " : " << "Unknown exception.";
+ data->setException();
throw;
}
}
-
-
diff --git a/test/TestServiceLocator.cpp b/test/TestServiceLocator.cpp
index 2572171..aebc687 100644
--- a/test/TestServiceLocator.cpp
+++ b/test/TestServiceLocator.cpp
@@ -1,7 +1,7 @@
/*
* Asterisk SCF -- An open-source communications framework.
*
- * Copyright (C) 2010, Digium, Inc.
+ * Copyright (C) 2010-2012, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk SCF project. Please do not directly contact
@@ -104,7 +104,7 @@ public:
params->category = category;
params->service = service;
- // Actually do the locate request
+ // Actually do the locate request
foundCompare = ServiceLocatorParamsComparePrx::uncheckedCast(discovery->locate(params));
/* If we get here we didn't get an exception back telling us no service found... which is wrong! */
@@ -113,7 +113,7 @@ public:
{
found = false;
}
- catch (const Ice::Exception &e)
+ catch (const Ice::Exception& e)
{
BOOST_TEST_MESSAGE(e.ice_name());
BOOST_TEST_MESSAGE(e.what());
@@ -200,7 +200,7 @@ struct GlobalIceFixture
{
throw "Invalid service discovery proxy";
}
-
+
} // end Fixture() constructor
~GlobalIceFixture()
@@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE(AddService)
*/
try
{
- testbed.compareManagement = testbed.management->addService(AsteriskSCF::Operations::createContext(),
+ testbed.compareManagement = testbed.management->addService(AsteriskSCF::Operations::createContext(),
testbed.compare, "testcompare");
added = true;
}
@@ -309,6 +309,19 @@ BOOST_AUTO_TEST_CASE(AddService)
}
/**
+ * Test retry logic for adding a service
+ */
+BOOST_AUTO_TEST_CASE(AddServiceRetry)
+{
+ AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+
+ ServiceManagementPrx expected = testbed.management->addService(context, testbed.compare, "testcompare");
+ ServiceManagementPrx actual = testbed.management->addService(context, testbed.compare, "testcompare");
+
+ BOOST_CHECK_EQUAL(expected, actual);
+}
+
+/**
* Confirm that we can't find a service after we have added one but before we add parameters.
*/
BOOST_AUTO_TEST_CASE(ServiceNotFoundAfterAdd)
@@ -357,6 +370,26 @@ BOOST_AUTO_TEST_CASE(AddLocatorParamsWithoutCompareService)
BOOST_CHECK(added);
}
+BOOST_AUTO_TEST_CASE(AddLocatorParamsRetry)
+{
+ AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+
+ ServiceLocatorParamsPtr params = new ServiceLocatorParams;
+ params->category = "retry-test";
+ params->service = "default";
+
+ size_t originalLocatorCount = testbed.compareManagement->getLocatorParams().size();
+
+ testbed.compareManagement->addLocatorParams(context, params, "");
+ testbed.compareManagement->addLocatorParams(context, params, "");
+
+ size_t expected = originalLocatorCount + 1;
+ size_t actual = testbed.compareManagement->getLocatorParams().size();
+
+ BOOST_CHECK_EQUAL(expected, actual);
+}
+
+
/**
* Confirm that we can find a service after we add discovery params that do not use a compare service.
*/
@@ -449,6 +482,7 @@ BOOST_AUTO_TEST_CASE(AddDuplicateCompare)
}
catch (const DuplicateCompare&)
{
+ // expected
}
catch (const Ice::Exception &e)
{
@@ -463,6 +497,46 @@ BOOST_AUTO_TEST_CASE(AddDuplicateCompare)
}
/**
+ * Tests retry logic in addCompare.
+ */
+BOOST_AUTO_TEST_CASE(AddCompareRetry)
+{
+ AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+ testbed.management->addCompare(context, "testcompareretry", testbed.compare);
+ BOOST_CHECK_NO_THROW(testbed.management->addCompare(context, "testcompareretry", testbed.compare));
+}
+
+/**
+ * Tests retry logic in addCompare.
+ */
+BOOST_AUTO_TEST_CASE(AddCompareDuplicateRetry)
+{
+ testbed.management->addCompare(AsteriskSCF::Operations::createContext(), "testcompareduplicateretry", testbed.compare);
+
+ AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+
+ try
+ {
+ testbed.management->addCompare(context, "testcompareretry", testbed.compare);
+ BOOST_FAIL("Expected exception");
+ }
+ catch (const DuplicateCompare&)
+ {
+ // expected
+ }
+
+ try
+ {
+ testbed.management->addCompare(context, "testcompareretry", testbed.compare);
+ BOOST_FAIL("Expected exception");
+ }
+ catch (const DuplicateCompare&)
+ {
+ // expected
+ }
+}
+
+/**
* Confirm that we can add discovery parameters with a compare service.
*/
BOOST_AUTO_TEST_CASE(AddLocatorParamsWithCompareService)
@@ -536,7 +610,7 @@ BOOST_AUTO_TEST_CASE(UseServiceFoundWithCompareService)
BOOST_AUTO_TEST_CASE(FindMultipleServices)
{
ServiceLocatorParamsPtr params = new ServiceLocatorParams;
- ServiceManagementPrx compareManagement = testbed.management->addService(AsteriskSCF::Operations::createContext(),
+ ServiceManagementPrx compareManagement = testbed.management->addService(AsteriskSCF::Operations::createContext(),
testbed.compare, "testcompare2");
params->category = "test";
@@ -557,7 +631,7 @@ BOOST_AUTO_TEST_CASE(FindMultipleServices)
BOOST_AUTO_TEST_CASE(FindMultipleServicesUsingEmptyCategory)
{
ServiceLocatorParamsPtr params = new ServiceLocatorParams;
- ServiceManagementPrx compareManagement = testbed.management->addService(AsteriskSCF::Operations::createContext(),
+ ServiceManagementPrx compareManagement = testbed.management->addService(AsteriskSCF::Operations::createContext(),
testbed.compare, "testcompare2");
params->category = "test";
@@ -667,6 +741,33 @@ BOOST_AUTO_TEST_CASE(RemoveNonexistentCompareService)
BOOST_CHECK(!removed);
}
+BOOST_AUTO_TEST_CASE(RemoveNonexistentCompareRetry)
+{
+ AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+
+ try
+ {
+ testbed.management->removeCompare(context, "does-not-exist");
+ BOOST_FAIL("Expected exception");
+ }
+ catch(const CompareNotFound&)
+ {
+ // expected
+ }
+
+ testbed.management->addCompare(AsteriskSCF::Operations::createContext(), "does-not-exist", testbed.compare);
+
+ try
+ {
+ testbed.management->removeCompare(context, "does-not-exist");
+ BOOST_FAIL("Expected exception");
+ }
+ catch(const CompareNotFound&)
+ {
+ // expected
+ }
+}
+
/**
* Confirm that we can remove a compare service.
*/
@@ -681,8 +782,9 @@ BOOST_AUTO_TEST_CASE(RemoveCompareService)
}
catch (const CompareNotFound&)
{
+ // expected
}
- catch (const Ice::Exception &e)
+ catch (const Ice::Exception& e)
{
BOOST_TEST_MESSAGE(e.ice_name());
BOOST_TEST_MESSAGE(e.what());
@@ -694,6 +796,23 @@ BOOST_AUTO_TEST_CASE(RemoveCompareService)
BOOST_CHECK(removed);
}
+BOOST_AUTO_TEST_CASE(RemoveCompareServiceRetry)
+{
+ testbed.management->addCompare(AsteriskSCF::Operations::createContext(), "remove-retry-compare", testbed.compare);
+
+ AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+ testbed.management->removeCompare(context, "remove-retry-compare");
+
+ try
+ {
+ testbed.management->removeCompare(context, "remove-retry-compare");
+ }
+ catch (const CompareNotFound& e)
+ {
+ BOOST_FAIL(std::string("Unexpected exception: ") + e.what());
+ }
+}
+
/**
* Confirm that we can't remove a compare service a second time.
*/
-----------------------------------------------------------------------
--
asterisk-scf/integration/servicediscovery.git
More information about the asterisk-scf-commits
mailing list