26 #ifndef _HACLIENTIMPL_H_ 27 #define _HACLIENTIMPL_H_ 38 class HAClientImpl :
public ClientImpl
41 HAClientImpl(
const std::string& name_)
42 : ClientImpl(name_), _timeout(AMPS_HACLIENT_TIMEOUT_DEFAULT)
43 , _reconnectDelay(AMPS_HACLIENT_RECONNECT_DEFAULT)
44 , _reconnectDelayStrategy(new ExponentialDelayStrategy(_reconnectDelay))
45 , _disconnected(false)
47 #ifdef AMPS_USE_FUNCTIONAL 48 setDisconnectHandler(HADisconnectHandler());
52 setSubscriptionManager(
new MemorySubscriptionManager());
61 void setTimeout(
int timeout_)
66 int getTimeout()
const 71 unsigned int getReconnectDelay(
void)
const 73 return _reconnectDelay;
76 void setReconnectDelay(
unsigned int reconnectDelay_)
78 _reconnectDelay = reconnectDelay_;
79 setReconnectDelayStrategy(
new FixedDelayStrategy(
80 (
unsigned int)reconnectDelay_));
83 void setReconnectDelayStrategy(
const ReconnectDelayStrategy& strategy_)
85 _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 #ifdef AMPS_USE_FUNCTIONAL 124 void operator()(Client& client)
126 invoke(client, NULL);
130 void connectAndLogon()
132 Lock<Mutex> l(_connectAndLogonLock);
134 _reconnectDelayStrategy.reset();
139 _disconnected =
false;
140 connectAndLogonInternal();
144 if(_subscriptionManager)
147 _subscriptionManager->resubscribe(c);
148 broadcastConnectionStateChanged(
149 ConnectionStateListener::Resubscribed);
153 catch(
const AMPSException& subEx)
156 _disconnected =
true;
157 _serverChooser.reportFailure(subEx, getConnectionInfo());
158 ClientImpl::setDisconnected();
170 virtual void connect(
const std::string& )
175 virtual std::string logon(
long , Authenticator& ,
178 if (_disconnected)
throw DisconnectedException(
"Attempt to call logon on a disconnected HAClient. Use connectAndLogon() instead.");
179 throw AlreadyConnectedException(
"Attempt to call logon on an HAClient. Use connectAndLogon() instead.");
182 static void HADoNothingDisconnectHandler(
amps_handle ,
188 class DisconnectHandlerDisabler
191 DisconnectHandlerDisabler()
192 : _pClient(NULL), _queueAckTimeout(0) { }
193 DisconnectHandlerDisabler(HAClientImpl* pClient_)
197 _queueAckTimeout = _pClient->getAckTimeout();
198 _pClient->setAckTimeout(0);
200 ~DisconnectHandlerDisabler() { clear(); }
206 _pClient->getHandle(),
207 (amps_handler)ClientImpl::ClientImplDisconnectHandler,
209 if (_queueAckTimeout)
211 _pClient->setAckTimeout(_queueAckTimeout);
212 _queueAckTimeout = 0;
217 void setClient(HAClientImpl* pClient_)
223 _queueAckTimeout = _pClient->getAckTimeout();
224 _pClient->setAckTimeout(0);
231 _pClient->getHandle(),
232 (amps_handler)HAClientImpl::HADoNothingDisconnectHandler,
236 HAClientImpl* _pClient;
237 int _queueAckTimeout;
240 void connectAndLogonInternal()
242 if(!_serverChooser.isValid())
244 throw ConnectionException(
"No server chooser registered with HAClient");
247 DisconnectHandlerDisabler disconnectDisabler;
248 while(!_disconnected)
250 std::string uri = _serverChooser.getCurrentURI();
253 throw ConnectionException(
"No AMPS instances available for connection. " + _serverChooser.getError());
255 Authenticator& auth = _serverChooser.getCurrentAuthenticator();
257 Lock<Mutex> l(_connectLock);
258 _sleepBeforeConnecting(uri);
262 if(_disconnected || _connected)
267 disconnectDisabler.setClient((HAClientImpl*)
this);
270 Lock<Mutex> clientLock(_lock);
271 ClientImpl::_connect(uri);
272 if (_logonOptions.empty())
274 ClientImpl::_logon(_timeout, auth);
278 ClientImpl::_logon(_timeout, auth, _logonOptions.c_str());
281 disconnectDisabler.clear();
284 _serverChooser.reportSuccess(getConnectionInfo());
285 _reconnectDelayStrategy.reset();
287 catch(
const AMPSException& e)
289 ClientImpl::disconnect();
290 throw AMPSException(e);
294 catch(
const AMPSException& ex)
296 Unlock<Mutex> u(_connectLock);
297 ConnectionInfo ci = getConnectionInfo();
299 ci[
"client.uri"] = uri;
300 _serverChooser.reportFailure(ex,ci);
303 ClientImpl::setDisconnected();
305 catch (
const std::exception& e)
309 _exceptionListener->exceptionThrown(e);
316 _exceptionListener->exceptionThrown(UnknownException(
"Unknown exception calling setDisconnected"));
325 ConnectionInfo gatherConnectionInfo()
const 327 return getConnectionInfo();
330 ConnectionInfo getConnectionInfo()
const 332 ConnectionInfo info = ClientImpl::getConnectionInfo();
333 std::ostringstream writer;
335 writer << getReconnectDelay();
336 info[
"haClient.reconnectDelay"] = writer.str();
337 writer.clear(); writer.str(
"");
339 info[
"haClient.timeout"] = writer.str();
344 bool disconnected()
const 346 return _disconnected;
353 Lock<Mutex> l(_connectLock);
354 _disconnected =
true;
356 ClientImpl::disconnect();
358 void _millisleep(
unsigned int millis_)
364 ts.tv_sec = millis_ / 1000;
365 ts.tv_nsec = millis_ % 1000 * 1000000;
366 nanosleep(&ts, NULL);
369 void _sleepBeforeConnecting(
const std::string& uri_)
374 _reconnectDelayStrategy.getConnectWaitDuration(uri_));
376 catch(
const ConnectionException&)
380 catch(
const std::exception& ex_)
382 _exceptionListener->exceptionThrown(ex_);
383 throw ConnectionException(ex_.what());
387 throw ConnectionException(
"Unknown exception thrown by " 388 "the HAClient's delay strategy.");
393 Mutex _connectAndLogonLock;
395 unsigned int _reconnectDelay;
396 ReconnectDelayStrategy _reconnectDelayStrategy;
397 ServerChooser _serverChooser;
398 volatile bool _disconnected;
399 std::string _logonOptions;
405 #endif //_HACLIENTIMPL_H_ void AMPSDLL 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:179
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...
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.
Provides AMPS::ServerChooser, the abstract base class that defines the interface that an AMPS::HAClie...
Definition: ampsplusplus.hpp:103