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 #ifdef AMPS_USE_FUNCTIONAL 51 setDisconnectHandler(HADisconnectHandler());
55 setSubscriptionManager(
new MemorySubscriptionManager());
64 void setTimeout(
int timeout_)
69 int getTimeout()
const 74 unsigned int getReconnectDelay(
void)
const 76 return _reconnectDelay;
79 void setReconnectDelay(
unsigned int reconnectDelay_)
81 _reconnectDelay = reconnectDelay_;
82 setReconnectDelayStrategy(
new FixedDelayStrategy(
83 (
unsigned int)reconnectDelay_));
86 void setReconnectDelayStrategy(
const ReconnectDelayStrategy& strategy_)
88 _reconnectDelayStrategy = strategy_;
91 ReconnectDelayStrategy getReconnectDelayStrategy(
void)
const 93 return _reconnectDelayStrategy;
96 std::string getLogonOptions(
void)
const 101 void setLogonOptions(
const std::string& logonOptions_)
103 _logonOptions = logonOptions_;
106 void setLogonOptions(
const char* logonOptions_)
108 _logonOptions = logonOptions_;
111 ServerChooser getServerChooser()
const 113 return _serverChooser;
116 void setServerChooser(
const ServerChooser& serverChooser_)
118 _serverChooser = serverChooser_;
121 class HADisconnectHandler
124 HADisconnectHandler() {}
125 static void invoke(Client& client,
void* );
126 #ifdef AMPS_USE_FUNCTIONAL 127 void operator()(Client& client)
129 invoke(client, NULL);
133 void connectAndLogon()
135 Lock<Mutex> l(_connectAndLogonLock);
137 _reconnectDelayStrategy.reset();
142 _disconnected =
false;
143 connectAndLogonInternal();
147 if (_subscriptionManager)
150 _subscriptionManager->resubscribe(c);
151 broadcastConnectionStateChanged(
152 ConnectionStateListener::Resubscribed);
156 catch (
const AMPSException& subEx)
159 _disconnected =
true;
160 _serverChooser.reportFailure(subEx, getConnectionInfo());
161 ClientImpl::setDisconnected();
173 virtual void connect(
const std::string& )
178 virtual std::string logon(
long , Authenticator& ,
183 throw DisconnectedException(
"Attempt to call logon on a disconnected HAClient. Use connectAndLogon() instead.");
185 throw AlreadyConnectedException(
"Attempt to call logon on an HAClient. Use connectAndLogon() instead.");
188 static void HADoNothingDisconnectHandler(
amps_handle ,
194 class DisconnectHandlerDisabler
197 DisconnectHandlerDisabler()
198 : _pClient(NULL), _queueAckTimeout(0) { }
199 DisconnectHandlerDisabler(HAClientImpl* pClient_)
203 _queueAckTimeout = _pClient->getAckTimeout();
204 _pClient->setAckTimeout(0);
206 ~DisconnectHandlerDisabler()
215 _pClient->getHandle(),
216 (amps_handler)ClientImpl::ClientImplDisconnectHandler,
218 if (_queueAckTimeout)
220 _pClient->setAckTimeout(_queueAckTimeout);
221 _queueAckTimeout = 0;
226 void setClient(HAClientImpl* pClient_)
232 _queueAckTimeout = _pClient->getAckTimeout();
233 _pClient->setAckTimeout(0);
240 _pClient->getHandle(),
241 (amps_handler)HAClientImpl::HADoNothingDisconnectHandler,
245 HAClientImpl* _pClient;
246 int _queueAckTimeout;
249 void connectAndLogonInternal()
251 if (!_serverChooser.isValid())
253 throw ConnectionException(
"No server chooser registered with HAClient");
256 DisconnectHandlerDisabler disconnectDisabler;
257 while (!_disconnected)
259 std::string uri = _serverChooser.getCurrentURI();
262 throw ConnectionException(
"No AMPS instances available for connection. " + _serverChooser.getError());
264 Authenticator& auth = _serverChooser.getCurrentAuthenticator();
266 Lock<Mutex> l(_connectLock);
267 _sleepBeforeConnecting(uri);
271 if (_disconnected || _connected)
276 disconnectDisabler.setClient((HAClientImpl*)
this);
279 Lock<Mutex> clientLock(_lock);
280 ClientImpl::_connect(uri);
283 if (_logonOptions.empty())
285 ClientImpl::_logon(_timeout, auth);
289 ClientImpl::_logon(_timeout, auth, _logonOptions.c_str());
292 catch (
const AuthenticationException&)
294 ClientImpl::setDisconnected();
297 catch (
const NotEntitledException&)
299 ClientImpl::setDisconnected();
302 catch (
const DuplicateLogonException&)
304 ClientImpl::setDisconnected();
307 catch (
const NameInUseException&)
309 ClientImpl::setDisconnected();
312 catch (
const TimedOutException&)
314 ClientImpl::setDisconnected();
318 disconnectDisabler.clear();
321 _serverChooser.reportSuccess(getConnectionInfo());
322 _reconnectDelayStrategy.reset();
324 catch (
const AMPSException&)
326 ClientImpl::disconnect();
331 catch (
const AMPSException& ex)
333 Unlock<Mutex> u(_connectLock);
334 ConnectionInfo ci = getConnectionInfo();
336 ci[
"client.uri"] = uri;
337 _serverChooser.reportFailure(ex, ci);
340 ClientImpl::setDisconnected();
342 catch (
const std::exception& e)
346 _exceptionListener->exceptionThrown(e);
354 _exceptionListener->exceptionThrown(UnknownException(
"Unknown exception calling setDisconnected"));
364 ConnectionInfo gatherConnectionInfo()
const 366 return getConnectionInfo();
369 ConnectionInfo getConnectionInfo()
const 371 ConnectionInfo info = ClientImpl::getConnectionInfo();
372 std::ostringstream writer;
374 writer << getReconnectDelay();
375 info[
"haClient.reconnectDelay"] = writer.str();
376 writer.clear(); writer.str(
"");
378 info[
"haClient.timeout"] = writer.str();
383 bool disconnected()
const 385 return _disconnected;
392 Lock<Mutex> l(_connectLock);
393 _disconnected =
true;
395 ClientImpl::disconnect();
397 void _millisleep(
unsigned int millis_)
403 double waitTime = (double)millis_;
404 Timer timer(waitTime);
406 while (!timer.checkAndGetRemaining(&waitTime))
408 if (waitTime - 1000.0 > 0.0)
410 AMPS_USLEEP(1000000);
414 AMPS_USLEEP(1000UL * (
unsigned int)waitTime);
416 amps_invoke_waiting_function();
419 void _sleepBeforeConnecting(
const std::string& uri_)
424 _reconnectDelayStrategy.getConnectWaitDuration(uri_));
426 catch (
const ConnectionException&)
430 catch (
const std::exception& ex_)
432 _exceptionListener->exceptionThrown(ex_);
433 throw ConnectionException(ex_.what());
437 throw ConnectionException(
"Unknown exception thrown by " 438 "the HAClient's delay strategy.");
443 Mutex _connectAndLogonLock;
445 unsigned int _reconnectDelay;
446 ReconnectDelayStrategy _reconnectDelayStrategy;
447 ServerChooser _serverChooser;
448 #if __cplusplus >= 201103L || _MSC_VER >= 1900 449 std::atomic<bool> _disconnected;
451 volatile bool _disconnected;
453 std::string _logonOptions;
459 #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: ampsplusplus.hpp:102