26 #ifndef _HACLIENTIMPL_H_ 27 #define _HACLIENTIMPL_H_ 34 #if __cplusplus >= 201103L || _MSC_VER >= 1900 41 class HAClientImpl :
public ClientImpl
44 HAClientImpl(
const std::string& name_)
45 : ClientImpl(name_), _timeout(AMPS_HACLIENT_TIMEOUT_DEFAULT)
46 , _reconnectDelay(AMPS_HACLIENT_RECONNECT_DEFAULT)
47 , _reconnectDelayStrategy(new ExponentialDelayStrategy(_reconnectDelay))
48 , _disconnected(false)
50 setDisconnectHandler(HADisconnectHandler());
51 setSubscriptionManager(
new MemorySubscriptionManager());
60 void setTimeout(
int timeout_)
65 int getTimeout()
const 70 unsigned int getReconnectDelay(
void)
const 72 return _reconnectDelay;
75 void setReconnectDelay(
unsigned int reconnectDelay_)
77 _reconnectDelay = reconnectDelay_;
78 setReconnectDelayStrategy(
new FixedDelayStrategy(
79 (
unsigned int)reconnectDelay_));
82 void setReconnectDelayStrategy(
const ReconnectDelayStrategy& strategy_)
84 _reconnectDelayStrategy = strategy_;
88 ReconnectDelayStrategy getReconnectDelayStrategy(
void)
const 90 return _reconnectDelayStrategy;
93 std::string getLogonOptions(
void)
const 98 void setLogonOptions(
const std::string& logonOptions_)
100 _logonOptions = logonOptions_;
103 void setLogonOptions(
const char* logonOptions_)
105 _logonOptions = logonOptions_;
108 ServerChooser getServerChooser()
const 110 return _serverChooser;
113 void setServerChooser(
const ServerChooser& serverChooser_)
115 _serverChooser = serverChooser_;
118 class HADisconnectHandler
121 HADisconnectHandler() {}
122 static void invoke(Client& client,
void* );
123 void operator()(Client& client)
125 invoke(client, NULL);
128 void connectAndLogon()
130 Lock<Mutex> l(_connectAndLogonLock);
133 _reconnectDelayStrategy.reset();
134 _reconnectDelay = _reconnectDelayStrategy.getConnectWaitDuration(
"DUMMY_URI");
135 _reconnectDelayStrategy.reset();
138 _disconnected =
false;
139 connectAndLogonInternal();
141 catch (
const RetryOperationException&)
153 virtual void connect(
const std::string& )
158 virtual std::string logon(
long , Authenticator& ,
163 throw DisconnectedException(
"Attempt to call logon on a disconnected HAClient. Use connectAndLogon() instead.");
165 throw AlreadyConnectedException(
"Attempt to call logon on an HAClient. Use connectAndLogon() instead.");
168 class DisconnectHandlerDisabler
171 DisconnectHandlerDisabler()
172 : _pClient(NULL), _queueAckTimeout(0), _disconnect(false) { }
173 DisconnectHandlerDisabler(HAClientImpl* pClient_)
175 , _queueAckTimeout(0)
179 _queueAckTimeout = _pClient->getAckTimeout();
180 _pClient->setAckTimeout(0);
182 ~DisconnectHandlerDisabler()
192 throw DisconnectedException(
"Client disconnected during logon.");
200 _pClient->getHandle(),
201 (amps_handler)ClientImpl::ClientImplDisconnectHandler,
203 if (_queueAckTimeout)
205 _pClient->setAckTimeout(_queueAckTimeout);
206 _queueAckTimeout = 0;
211 void setClient(HAClientImpl* pClient_)
217 _queueAckTimeout = _pClient->getAckTimeout();
218 _pClient->setAckTimeout(0);
227 _pClient->getHandle(),
228 (amps_handler)HAClientImpl::DisconnectHandlerDisabler::HADoNothingDisconnectHandler,
229 (
void*)&_disconnect);
231 static void HADoNothingDisconnectHandler(
amps_handle ,
234 *(
bool*)pDisconnect_ =
true;
238 HAClientImpl* _pClient;
239 int _queueAckTimeout;
243 void connectAndLogonInternal()
245 if (!_serverChooser.isValid())
247 throw ConnectionException(
"No server chooser registered with HAClient");
250 DisconnectHandlerDisabler disconnectDisabler;
251 TryLock<Mutex> l(_connectLock);
254 throw RetryOperationException(
"Retry, another thread is handling reconnnect");
256 while (!_disconnected)
258 std::string uri = _serverChooser.getCurrentURI();
261 throw ConnectionException(
"No AMPS instances available for connection. " + _serverChooser.getError());
263 Authenticator& auth = _serverChooser.getCurrentAuthenticator();
264 _sleepBeforeConnecting(uri);
274 throw RetryOperationException(
"Another thread has reconnected.");
277 disconnectDisabler.setClient((HAClientImpl*)
this);
280 Lock<Mutex> clientLock(_lock);
281 ClientImpl::_connect(uri);
284 captureSubscriptionManagerGenerationCount();
285 if (_logonOptions.empty())
287 ClientImpl::_logon(_timeout, auth);
291 ClientImpl::_logon(_timeout, auth, _logonOptions.c_str());
294 catch (
const AuthenticationException&)
296 ClientImpl::setDisconnected();
299 catch (
const NotEntitledException&)
301 ClientImpl::setDisconnected();
304 catch (
const DuplicateLogonException&)
306 ClientImpl::setDisconnected();
309 catch (
const NameInUseException&)
311 ClientImpl::setDisconnected();
314 catch (
const TimedOutException&)
316 ClientImpl::setDisconnected();
321 _serverChooser.reportSuccess(getConnectionInfo());
323 _reconnectDelayStrategy.reset();
324 _reconnectDelay = _reconnectDelayStrategy.getConnectWaitDuration(
"DUMMY_URI");
325 _reconnectDelayStrategy.reset();
327 catch (
const AMPSException&)
329 Unlock<Mutex> clientUnlock(_lock);
330 ClientImpl::disconnect();
335 && _subscriptionManager)
337 Client c(
this,
false);
339 Unlock<Mutex> clientUnlock(_lock);
340 _subscriptionManager->resubscribe(c);
345 disconnectDisabler.clear();
347 broadcastConnectionStateChanged(ConnectionStateListener::Resubscribed);
351 disconnectDisabler.clear();
354 catch (
const RetryOperationException&)
358 catch (
const AMPSException& ex)
360 ConnectionInfo ci = getConnectionInfo();
362 ci[
"client.uri"] = std::move(uri);
363 _serverChooser.reportFailure(ex, ci);
366 ClientImpl::setDisconnected();
368 catch (
const std::exception& e)
372 _exceptionListener->exceptionThrown(e);
380 _exceptionListener->exceptionThrown(UnknownException(
"Unknown exception calling setDisconnected"));
390 ConnectionInfo gatherConnectionInfo()
const 392 return getConnectionInfo();
395 ConnectionInfo getConnectionInfo()
const 397 ConnectionInfo info = ClientImpl::getConnectionInfo();
398 std::ostringstream writer;
400 writer << getReconnectDelay();
401 info[
"haClient.reconnectDelay"] = writer.str();
402 writer.clear(); writer.str(
"");
404 info[
"haClient.timeout"] = writer.str();
409 bool disconnected()
const 411 return _disconnected;
417 _disconnected =
true;
419 Lock<Mutex> l(_connectLock);
420 ClientImpl::disconnect();
422 void _millisleep(
unsigned int millis_)
428 double waitTime = (double)millis_;
429 Timer timer(waitTime);
431 while (!timer.checkAndGetRemaining(&waitTime))
433 if (waitTime - 1000.0 > 0.0)
435 AMPS_USLEEP(1000000);
439 AMPS_USLEEP(1000UL * (
unsigned int)waitTime);
441 amps_invoke_waiting_function();
444 void _sleepBeforeConnecting(
const std::string& uri_)
448 _reconnectDelay = _reconnectDelayStrategy.getConnectWaitDuration(uri_);
449 _millisleep(_reconnectDelay);
451 catch (
const ConnectionException&)
455 catch (
const std::exception& ex_)
457 _exceptionListener->exceptionThrown(ex_);
458 throw ConnectionException(ex_.what());
462 throw ConnectionException(
"Unknown exception thrown by " 463 "the HAClient's delay strategy.");
468 Mutex _connectAndLogonLock;
470 unsigned int _reconnectDelay;
471 ReconnectDelayStrategy _reconnectDelayStrategy;
472 ServerChooser _serverChooser;
473 #if __cplusplus >= 201103L || _MSC_VER >= 1900 474 std::atomic<bool> _disconnected;
476 volatile bool _disconnected;
478 std::string _logonOptions;
484 #endif //_HACLIENTIMPL_H_ AMPSDLL void amps_client_set_disconnect_handler(amps_handle client, amps_handler disconnectHandler, void *userData)
Sets the disconnect handler function to be called when a disconnect occurs.
AMPSDLL void amps_client_disconnect(amps_handle handle)
Disconnects from the AMPS server, if connected.
Provides AMPS::MemorySubscriptionManager, used by an AMPS::HAClient to resubmit subscriptions if conn...
void * amps_handle
Opaque handle type used to refer to objects in the AMPS api.
Definition: amps.h:211
Core type, function, and class declarations for the AMPS C++ client.
Provides AMPS::ReconnectDelayStrategy, called by an AMPS::HAClient to determine how long to wait betw...
Provides AMPS::ServerChooser, the abstract base class that defines the interface that an AMPS::HAClie...
Definition: AMPSException.hpp:32