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& ,
180 throw DisconnectedException(
"Attempt to call logon on a disconnected HAClient. Use connectAndLogon() instead.");
182 throw AlreadyConnectedException(
"Attempt to call logon on an HAClient. Use connectAndLogon() instead.");
185 static void HADoNothingDisconnectHandler(
amps_handle ,
191 class DisconnectHandlerDisabler
194 DisconnectHandlerDisabler()
195 : _pClient(NULL), _queueAckTimeout(0) { }
196 DisconnectHandlerDisabler(HAClientImpl* pClient_)
200 _queueAckTimeout = _pClient->getAckTimeout();
201 _pClient->setAckTimeout(0);
203 ~DisconnectHandlerDisabler()
212 _pClient->getHandle(),
213 (amps_handler)ClientImpl::ClientImplDisconnectHandler,
215 if (_queueAckTimeout)
217 _pClient->setAckTimeout(_queueAckTimeout);
218 _queueAckTimeout = 0;
223 void setClient(HAClientImpl* pClient_)
229 _queueAckTimeout = _pClient->getAckTimeout();
230 _pClient->setAckTimeout(0);
237 _pClient->getHandle(),
238 (amps_handler)HAClientImpl::HADoNothingDisconnectHandler,
242 HAClientImpl* _pClient;
243 int _queueAckTimeout;
246 void connectAndLogonInternal()
248 if (!_serverChooser.isValid())
250 throw ConnectionException(
"No server chooser registered with HAClient");
253 DisconnectHandlerDisabler disconnectDisabler;
254 while (!_disconnected)
256 std::string uri = _serverChooser.getCurrentURI();
259 throw ConnectionException(
"No AMPS instances available for connection. " + _serverChooser.getError());
261 Authenticator& auth = _serverChooser.getCurrentAuthenticator();
263 Lock<Mutex> l(_connectLock);
264 _sleepBeforeConnecting(uri);
268 if (_disconnected || _connected)
273 disconnectDisabler.setClient((HAClientImpl*)
this);
276 Lock<Mutex> clientLock(_lock);
277 ClientImpl::_connect(uri);
278 if (_logonOptions.empty())
280 ClientImpl::_logon(_timeout, auth);
284 ClientImpl::_logon(_timeout, auth, _logonOptions.c_str());
287 disconnectDisabler.clear();
290 _serverChooser.reportSuccess(getConnectionInfo());
291 _reconnectDelayStrategy.reset();
293 catch (
const AMPSException& e)
295 ClientImpl::disconnect();
296 throw AMPSException(e);
300 catch (
const AMPSException& ex)
302 Unlock<Mutex> u(_connectLock);
303 ConnectionInfo ci = getConnectionInfo();
305 ci[
"client.uri"] = uri;
306 _serverChooser.reportFailure(ex, ci);
309 ClientImpl::setDisconnected();
311 catch (
const std::exception& e)
315 _exceptionListener->exceptionThrown(e);
323 _exceptionListener->exceptionThrown(UnknownException(
"Unknown exception calling setDisconnected"));
333 ConnectionInfo gatherConnectionInfo()
const 335 return getConnectionInfo();
338 ConnectionInfo getConnectionInfo()
const 340 ConnectionInfo info = ClientImpl::getConnectionInfo();
341 std::ostringstream writer;
343 writer << getReconnectDelay();
344 info[
"haClient.reconnectDelay"] = writer.str();
345 writer.clear(); writer.str(
"");
347 info[
"haClient.timeout"] = writer.str();
352 bool disconnected()
const 354 return _disconnected;
361 Lock<Mutex> l(_connectLock);
362 _disconnected =
true;
364 ClientImpl::disconnect();
366 void _millisleep(
unsigned int millis_)
372 double waitTime = (double)millis_;
373 Timer timer(waitTime);
375 while (!timer.checkAndGetRemaining(&waitTime))
377 if (waitTime - 1000.0 > 0.0)
379 AMPS_USLEEP(1000000);
383 AMPS_USLEEP(1000UL * (
unsigned int)waitTime);
385 amps_invoke_waiting_function();
388 void _sleepBeforeConnecting(
const std::string& uri_)
393 _reconnectDelayStrategy.getConnectWaitDuration(uri_));
395 catch (
const ConnectionException&)
399 catch (
const std::exception& ex_)
401 _exceptionListener->exceptionThrown(ex_);
402 throw ConnectionException(ex_.what());
406 throw ConnectionException(
"Unknown exception thrown by " 407 "the HAClient's delay strategy.");
412 Mutex _connectAndLogonLock;
414 unsigned int _reconnectDelay;
415 ReconnectDelayStrategy _reconnectDelayStrategy;
416 ServerChooser _serverChooser;
417 volatile bool _disconnected;
418 std::string _logonOptions;
424 #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:196
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:103