int result;
assert(!Application::m_Instance);
- Application::m_Instance = static_pointer_cast<Application>(shared_from_this());
+ Application::m_Instance = GetSelf();
#ifndef _WIN32
struct sigaction sa;
void ConfigObject::Commit(void)
{
ConfigObject::Ptr dobj = GetObject(GetType(), GetName());
- ConfigObject::Ptr self = static_pointer_cast<ConfigObject>(shared_from_this());
+ ConfigObject::Ptr self = GetSelf();
assert(!dobj || dobj == self);
m_Container->CheckObject(self);
}
void ConfigObject::Unregister(void)
{
- ConfigObject::Ptr self = static_pointer_cast<ConfigObject>(shared_from_this());
+ ConfigObject::Ptr self = GetSelf();
m_Container->RemoveObject(self);
}
*/
void Object::Hold(void)
{
- m_HeldObjects.push_back(shared_from_this());
+ m_HeldObjects.push_back(GetSelf());
}
/**
m_HeldObjects.clear();
}
+SharedPtrHolder Object::GetSelf(void)
+{
+ return SharedPtrHolder(shared_from_this());
+}
namespace icinga
{
+class SharedPtrHolder;
+
/**
* Base class for all heap-allocated objects. At least one of its methods
* has to be virtual for RTTI to work.
void Hold(void);
+ SharedPtrHolder GetSelf(void);
+
private:
Object(const Object& other);
Object operator=(const Object& rhs);
static vector<Object::Ptr> m_HeldObjects;
};
+/**
+ * Holds a shared pointer and provides support for implicit upcasts.
+ */
+class SharedPtrHolder
+{
+public:
+ explicit SharedPtrHolder(const shared_ptr<Object>& object)
+ : m_Object(object)
+ { }
+
+ template<typename T>
+ operator shared_ptr<T>(void) const
+ {
+#ifdef _DEBUG
+ shared_ptr<T> other = dynamic_pointer_cast<T>(m_Object);
+ assert(other);
+#else /* _DEBUG */
+ shared_ptr<T> other = static_pointer_cast<T>(m_Object);
+#endif /* _DEBUG */
+
+ return other;
+ }
+
+ template<typename T>
+ operator weak_ptr<T>(void) const
+ {
+ return static_cast<shared_ptr<T> >(*this);
+ }
+
+private:
+ shared_ptr<Object> m_Object;
+};
+
/**
* Compares a weak pointer with a raw pointer.
*/
Range range = GetRange(key);
for (Iterator it = range.first; it != range.second; it++) {
- callback(shared_from_this(), *it);
+ callback(GetSelf(), *it);
}
}
void AddObject(const TValue& object)
{
m_Objects.insert(object);
- OnObjectAdded(shared_from_this(), object);
+ OnObjectAdded(GetSelf(), object);
}
void RemoveObject(const TValue& object)
if (it != m_Objects.end()) {
m_Objects.erase(it);
- OnObjectRemoved(shared_from_this(), object);
+ OnObjectRemoved(GetSelf(), object);
}
}
if (!Contains(object)) {
AddObject(object);
} else {
- OnObjectCommitted(shared_from_this(), object);
+ OnObjectCommitted(GetSelf(), object);
}
}
}
- boost::signal<void (const Object::Ptr&, const TValue&)> OnObjectAdded;
- boost::signal<void (const Object::Ptr&, const TValue&)> OnObjectCommitted;
- boost::signal<void (const Object::Ptr&, const TValue&)> OnObjectRemoved;
+ boost::signal<void (const typename ObjectSet<TValue>::Ptr&, const TValue&)> OnObjectAdded;
+ boost::signal<void (const typename ObjectSet<TValue>::Ptr&, const TValue&)> OnObjectCommitted;
+ boost::signal<void (const typename ObjectSet<TValue>::Ptr&, const TValue&)> OnObjectRemoved;
Iterator Begin(void)
{
void ForeachObject(function<void (const typename Object::Ptr&, const TValue&)> callback)
{
for (Iterator it = Begin(); it != End(); it++) {
- callback(shared_from_this(), *it);
+ callback(GetSelf(), *it);
}
}
OnException.connect(boost::bind(&Socket::ExceptionEventHandler, this));
- Sockets.push_back(static_pointer_cast<Socket>(shared_from_this()));
+ Sockets.push_back(GetSelf());
}
/**
if (!from_dtor) {
Stop();
- OnClosed(shared_from_this());
+ OnClosed(GetSelf());
}
}
void Socket::HandleSocketError(const std::exception& ex)
{
if (!OnError.empty()) {
- OnError(shared_from_this(), ex);
+ OnError(GetSelf(), ex);
Close();
} else {
void SetFD(SOCKET fd);
SOCKET GetFD(void) const;
- boost::signal<void (const Object::Ptr&)> OnReadable;
- boost::signal<void (const Object::Ptr&)> OnWritable;
- boost::signal<void (const Object::Ptr&)> OnException;
+ boost::signal<void (const Socket::Ptr&)> OnReadable;
+ boost::signal<void (const Socket::Ptr&)> OnWritable;
+ boost::signal<void (const Socket::Ptr&)> OnException;
- boost::signal<void (const Object::Ptr&, const std::exception&)> OnError;
- boost::signal<void (const Object::Ptr&)> OnClosed;
+ boost::signal<void (const Socket::Ptr&, const std::exception&)> OnError;
+ boost::signal<void (const Socket::Ptr&)> OnClosed;
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
m_RecvQueue->Write(NULL, rc);
- OnDataAvailable(shared_from_this());
+ OnDataAvailable(GetSelf());
}
/**
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
- boost::signal<void (const Object::Ptr&)> OnDataAvailable;
+ boost::signal<void (const TcpClient::Ptr&)> OnDataAvailable;
private:
TcpClientRole m_Role;
client->SetFD(fd);
client->Start();
- OnNewClient(shared_from_this(), client);
+ OnNewClient(GetSelf(), client);
}
/**
void Listen(void);
- boost::signal<void (const Object::Ptr&, const TcpClient::Ptr&)> OnNewClient;
+ boost::signal<void (const TcpServer::Ptr&, const TcpClient::Ptr&)> OnNewClient;
virtual bool WantsToRead(void) const;
*/
void Timer::Call(void)
{
- OnTimerExpired(shared_from_this());
+ OnTimerExpired(GetSelf());
}
/**
{
Stop();
- Timers.push_back(static_pointer_cast<Timer>(shared_from_this()));
+ Timers.push_back(GetSelf());
Reschedule(time(NULL) + m_Interval);
}
void Reschedule(time_t next);
- boost::signal<void(const Object::Ptr&)> OnTimerExpired;
+ boost::signal<void(const Timer::Ptr&)> OnTimerExpired;
private:
time_t m_Interval; /**< The interval of the timer. */
GetRecvQueue()->Write(NULL, rc);
- OnDataAvailable(shared_from_this());
+ OnDataAvailable(GetSelf());
}
/**
bool valid = false;
shared_ptr<X509> x509Certificate = shared_ptr<X509>(x509Context->cert, &TlsClient::NullCertificateDeleter);
- client->OnVerifyCertificate(client->shared_from_this(), valid, x509Context, x509Certificate);
+ client->OnVerifyCertificate(client->GetSelf(), valid, x509Context, x509Certificate);
return valid ? 1 : 0;
}
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
- boost::signal<void (const Object::Ptr&, bool&, X509_STORE_CTX *, const shared_ptr<X509>&)> OnVerifyCertificate;
+ boost::signal<void (const TlsClient::Ptr&, bool&, X509_STORE_CTX *, const shared_ptr<X509>&)> OnVerifyCertificate;
protected:
void HandleSSLError(void);
endpoint->OnSessionEstablished.connect(boost::bind(&ConfigRpcComponent::SessionEstablishedHandler, this, _1));
}
-void ConfigRpcComponent::SessionEstablishedHandler(const Object::Ptr& source)
+void ConfigRpcComponent::SessionEstablishedHandler(const Endpoint::Ptr& endpoint)
{
RequestMessage request;
request.SetMethod("config::FetchObjects");
- Endpoint::Ptr endpoint = static_pointer_cast<Endpoint>(source);
GetEndpointManager()->SendUnicastMessage(m_ConfigRpcEndpoint, endpoint, request);
}
VirtualEndpoint::Ptr m_ConfigRpcEndpoint;
void NewEndpointHandler(const Endpoint::Ptr& endpoint);
- void SessionEstablishedHandler(const Object::Ptr& source);
+ void SessionEstablishedHandler(const Endpoint::Ptr& endpoint);
void LocalObjectCommittedHandler(const ConfigObject::Ptr& object);
void LocalObjectRemovedHandler(const ConfigObject::Ptr& object);
* @param ea Event arguments for the component.
* @returns 0
*/
-void DiscoveryComponent::NewIdentityHandler(const Object::Ptr& source)
+void DiscoveryComponent::NewIdentityHandler(const Endpoint::Ptr& endpoint)
{
- Endpoint::Ptr endpoint = static_pointer_cast<Endpoint>(source);
string identity = endpoint->GetIdentity();
if (identity == GetEndpointManager()->GetIdentity()) {
Timer::Ptr m_DiscoveryTimer;
void NewEndpointHandler(const Endpoint::Ptr& endpoint);
- void NewIdentityHandler(const Object::Ptr& source);
+ void NewIdentityHandler(const Endpoint::Ptr& endpoint);
void NewComponentMessageHandler(const RequestMessage& request);
void RegisterComponentMessageHandler(const Endpoint::Ptr& sender, const RequestMessage& request);
dobj->Commit();
ConfigItem::Ptr ci = GetObject(GetType(), GetName());
- ConfigItem::Ptr self = static_pointer_cast<ConfigItem>(shared_from_this());
+ ConfigItem::Ptr self = GetSelf();
if (ci && ci != self) {
ci->m_ConfigObject.reset();
GetAllObjects()->RemoveObject(ci);
{
// TODO: unregister associated ConfigObject
- ConfigItem::Ptr self = static_pointer_cast<ConfigItem>(shared_from_this());
- GetAllObjects()->RemoveObject(self);
+ GetAllObjects()->RemoveObject(GetSelf());
}
ConfigItem::Ptr ConfigItem::GetObject(const string& type, const string& name)
void Endpoint::SetIdentity(string identity)
{
m_Identity = identity;
- OnIdentityChanged(shared_from_this());
+ OnIdentityChanged(GetSelf());
}
/**
ConstTopicIterator BeginPublications(void) const;
ConstTopicIterator EndPublications(void) const;
- boost::signal<void (const Object::Ptr&)> OnIdentityChanged;
- boost::signal<void (const Object::Ptr&)> OnSessionEstablished;
+ boost::signal<void (const Endpoint::Ptr&)> OnIdentityChanged;
+ boost::signal<void (const Endpoint::Ptr&)> OnSessionEstablished;
private:
string m_Identity; /**< The identity of this endpoint. */
if (!endpoint->IsLocal() && endpoint->GetIdentity() != "")
throw invalid_argument("Identity must be empty.");
- endpoint->SetEndpointManager(static_pointer_cast<EndpointManager>(shared_from_this()));
+ endpoint->SetEndpointManager(GetSelf());
m_Endpoints.push_back(endpoint);
- OnNewEndpoint(shared_from_this(), endpoint);
+ OnNewEndpoint(GetSelf(), endpoint);
}
/**
*
* @param callback The callback function.
*/
-void EndpointManager::ForEachEndpoint(function<void (const Object::Ptr&, const Endpoint::Ptr&)> callback)
+void EndpointManager::ForEachEndpoint(function<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> callback)
{
vector<Endpoint::Ptr>::iterator prev, i;
for (i = m_Endpoints.begin(); i != m_Endpoints.end(); ) {
prev = i;
i++;
- callback(shared_from_this(), *prev);
+ callback(GetSelf(), *prev);
}
}
void EndpointManager::SendAPIMessage(Endpoint::Ptr sender,
RequestMessage& message,
- function<void(const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout)
+ function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout)
{
m_NextMessageID++;
map<string, PendingRequest>::iterator it;
for (it = m_Requests.begin(); it != m_Requests.end(); it++) {
if (it->second.HasTimedOut()) {
- it->second.Callback(shared_from_this(), Endpoint::Ptr(), it->second.Request, ResponseMessage(), true);
+ it->second.Callback(GetSelf(), Endpoint::Ptr(), it->second.Request, ResponseMessage(), true);
m_Requests.erase(it);
if (it == m_Requests.end())
return;
- it->second.Callback(shared_from_this(), sender, it->second.Request, message, false);
+ it->second.Callback(GetSelf(), sender, it->second.Request, message, false);
m_Requests.erase(it);
RescheduleRequestTimer();
namespace icinga
{
-/**
- * Information about a pending API request.
- *
- * @ingroup icinga
- */
-struct I2_ICINGA_API PendingRequest
-{
- time_t Timeout;
- RequestMessage Request;
- function<void(const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> Callback;
-
- bool HasTimedOut(void) const
- {
- return time(NULL) > Timeout;
- }
-};
-
/**
* Forwards messages between endpoints.
*
void SendMulticastMessage(Endpoint::Ptr sender, const RequestMessage& message);
void SendAPIMessage(Endpoint::Ptr sender, RequestMessage& message,
- function<void(const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout = 10);
+ function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout = 10);
void ProcessResponseMessage(const Endpoint::Ptr& sender, const ResponseMessage& message);
- void ForEachEndpoint(function<void (const Object::Ptr&, const Endpoint::Ptr&)> callback);
+ void ForEachEndpoint(function<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> callback);
Endpoint::Ptr GetEndpointByIdentity(string identity) const;
- boost::signal<void (const Object::Ptr&, const Endpoint::Ptr&)> OnNewEndpoint;
+ boost::signal<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> OnNewEndpoint;
private:
string m_Identity;
vector<JsonRpcServer::Ptr> m_Servers;
vector<Endpoint::Ptr> m_Endpoints;
+ /**
+ * Information about a pending API request.
+ *
+ * @ingroup icinga
+ */
+ struct I2_ICINGA_API PendingRequest
+ {
+ time_t Timeout;
+ RequestMessage Request;
+ function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> Callback;
+
+ bool HasTimedOut(void) const
+ {
+ return time(NULL) > Timeout;
+ }
+ };
+
long m_NextMessageID;
map<string, PendingRequest> m_Requests;
Timer::Ptr m_RequestTimer;
void JsonRpcEndpoint::NewMessageHandler(const MessagePart& message)
{
- Endpoint::Ptr sender = static_pointer_cast<Endpoint>(shared_from_this());
+ Endpoint::Ptr sender = GetSelf();
if (ResponseMessage::IsResponseMessage(message)) {
/* rather than routing the message to the right virtual
// remove the endpoint if there are no more subscriptions */
if (BeginSubscriptions() == EndSubscriptions()) {
Hold();
- GetEndpointManager()->UnregisterEndpoint(static_pointer_cast<Endpoint>(shared_from_this()));
+ GetEndpointManager()->UnregisterEndpoint(GetSelf());
}
m_Client.reset();
return true;
}
-void VirtualEndpoint::RegisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
+void VirtualEndpoint::RegisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
{
- map<string, shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
+ map<string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
it = m_TopicHandlers.find(topic);
- shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > sig;
+ shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > sig;
if (it == m_TopicHandlers.end()) {
- sig = boost::make_shared<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> >();
+ sig = boost::make_shared<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> >();
m_TopicHandlers.insert(make_pair(topic, sig));
} else {
sig = it->second;
RegisterSubscription(topic);
}
-void VirtualEndpoint::UnregisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
+void VirtualEndpoint::UnregisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
{
// TODO: implement
//m_TopicHandlers[method] -= callback;
if (!request.GetMethod(&method))
return;
- map<string, shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
+ map<string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
it = m_TopicHandlers.find(method);
if (it == m_TopicHandlers.end())
return;
- (*it->second)(shared_from_this(), sender, request);
+ (*it->second)(GetSelf(), sender, request);
}
void VirtualEndpoint::ProcessResponse(Endpoint::Ptr sender, const ResponseMessage& response)
typedef shared_ptr<VirtualEndpoint> Ptr;
typedef weak_ptr<VirtualEndpoint> WeakPtr;
- void RegisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
- void UnregisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
+ void RegisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
+ void UnregisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
virtual string GetAddress(void) const;
virtual void Stop(void);
private:
- map< string, shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > > m_TopicHandlers;
+ map< string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > > m_TopicHandlers;
};
}
return;
message = MessagePart(jsonString);
- OnNewMessage(shared_from_this(), message);
+ OnNewMessage(GetSelf(), message);
} catch (const Exception& ex) {
Application::Log(LogCritical, "jsonrpc", "Exception while processing message from JSON-RPC client: " + string(ex.GetMessage()));
Close();
void SendMessage(const MessagePart& message);
- boost::signal<void (const Object::Ptr&, const MessagePart&)> OnNewMessage;
+ boost::signal<void (const JsonRpcClient::Ptr&, const MessagePart&)> OnNewMessage;
private:
void DataAvailableHandler(void);
}
while (*m++);
};
- return mask;
+ return pattern;
}