]> granicus.if.org Git - icinga2/commitdiff
Implemented DynamicType support.
authorGunnar Beutner <gunnar@beutner.name>
Tue, 4 Dec 2012 07:42:24 +0000 (08:42 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Tue, 4 Dec 2012 07:42:24 +0000 (08:42 +0100)
Fixes #3477

29 files changed:
components/compat/compatcomponent.cpp
components/compatido/compatidocomponent.cpp
components/delegation/delegationcomponent.cpp
components/replication/replicationcomponent.cpp
lib/base/Makefile.am
lib/base/application.cpp
lib/base/base.vcxproj
lib/base/base.vcxproj.filters
lib/base/component.cpp
lib/base/dynamicobject.cpp
lib/base/dynamicobject.h
lib/base/dynamictype.cpp [new file with mode: 0644]
lib/base/dynamictype.h [new file with mode: 0644]
lib/base/i2-base.h
lib/base/logger.cpp
lib/base/object.cpp
lib/base/object.h
lib/base/socket.cpp
lib/base/tlsstream.cpp
lib/config/configitem.cpp
lib/icinga/host.cpp
lib/icinga/hostgroup.cpp
lib/icinga/icingaapplication.cpp
lib/icinga/icingaapplication.h
lib/icinga/service.cpp
lib/icinga/servicegroup.cpp
lib/remoting/endpoint.cpp
lib/remoting/endpointmanager.cpp
lib/remoting/endpointmanager.h

index 45bd28f64308adf42d8a2542ebbbe4e94f7ebd03..2faa003d856e5459b7d90d6d105c42b66b20a974 100644 (file)
@@ -248,7 +248,7 @@ void CompatComponent::StatusTimerHandler(void)
        map<String, vector<String> > hostgroups;
 
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
                const Host::Ptr& host = static_pointer_cast<Host>(object);
 
                Dictionary::Ptr dict;
@@ -290,7 +290,7 @@ void CompatComponent::StatusTimerHandler(void)
 
        map<String, vector<Service::Ptr> > servicegroups;
 
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
                Service::Ptr service = static_pointer_cast<Service>(object);
 
                Dictionary::Ptr dict;
index c680ba1b81d3204c4a15c9962f6ce0537b04ef09..a1113bd0bb134271e6e4d0f069c8af0677e5bf30 100644 (file)
@@ -740,7 +740,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
        map<String, vector<String> > hostgroups;
 
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
                const Host::Ptr& host = static_pointer_cast<Host>(object);
 
                Dictionary::Ptr dict;
@@ -785,7 +785,7 @@ void CompatIdoComponent::DumpConfigObjects(void)
        /* services and servicegroups */
        map<String, vector<Service::Ptr> > servicegroups;
 
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
                Service::Ptr service = static_pointer_cast<Service>(object);
 
                Dictionary::Ptr dict;
@@ -854,7 +854,7 @@ void CompatIdoComponent::DumpStatusData(void)
 {
        /* hosts */
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Host")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Host")->GetObjects()) {
                const Host::Ptr& host = static_pointer_cast<Host>(object);
 
                DumpHostStatus(host);
@@ -862,7 +862,7 @@ void CompatIdoComponent::DumpStatusData(void)
 
 
        /* services */
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
                Service::Ptr service = static_pointer_cast<Service>(object);
 
                DumpServiceStatus(service);
index 9e8e85a03e8eec64151daaabf4ee3eed58c5b055..7dff383d29553aa1838c914e0caf71bdd6b8ba90 100644 (file)
@@ -41,7 +41,7 @@ vector<Endpoint::Ptr> DelegationComponent::GetCheckerCandidates(const Service::P
        vector<Endpoint::Ptr> candidates;
 
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
                Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
 
                String myIdentity = EndpointManager::GetInstance()->GetIdentity();
@@ -73,7 +73,7 @@ void DelegationComponent::DelegationTimerHandler(void)
        map<Endpoint::Ptr, int> histogram;
 
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
                Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
 
                histogram[endpoint] = 0;
@@ -82,7 +82,7 @@ void DelegationComponent::DelegationTimerHandler(void)
        vector<Service::Ptr> services;
 
        /* build "checker -> service count" histogram */
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Service")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Service")->GetObjects()) {
                Service::Ptr service = dynamic_pointer_cast<Service>(object);
 
                if (!service)
index 06ca0c8a1d0b48321dea1af4821f94bd776a3363..f8ee5c68c7c589715e79790fa0d62009a1c80e40 100644 (file)
@@ -85,11 +85,10 @@ void ReplicationComponent::EndpointConnectedHandler(const Endpoint::Ptr& endpoin
        endpoint->RegisterSubscription("config::ObjectUpdate");
        endpoint->RegisterSubscription("config::ObjectRemoved");
 
-       pair<DynamicObject::TypeMap::iterator, DynamicObject::TypeMap::iterator> trange = DynamicObject::GetTypes();
-       DynamicObject::TypeMap::iterator tt;
-       for (tt = trange.first; tt != trange.second; tt++) {
+       DynamicType::Ptr type;
+       BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) {
                DynamicObject::Ptr object;
-               BOOST_FOREACH(tie(tuples::ignore, object), tt->second) {
+               BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) {
                        if (!ShouldReplicateObject(object))
                                continue;
 
@@ -186,12 +185,13 @@ void ReplicationComponent::RemoteObjectUpdateHandler(const Endpoint::Ptr& sender
        if (!params.Get("update", &update))
                return;
 
-       DynamicObject::Ptr object = DynamicObject::GetObject(type, name);
+       DynamicType::Ptr dtype = DynamicType::GetByName(type);
+       DynamicObject::Ptr object = dtype->GetObject(name);
 
        // TODO: sanitize update, disallow __local
 
        if (!object) {
-               object = DynamicObject::Create(type, update);
+               object = dtype->CreateObject(update);
 
                if (source == EndpointManager::GetInstance()->GetIdentity()) {
                        /* the peer sent us an object that was originally created by us - 
index 5df39cb42b86094ea9c438603c8a3d253584521f..575a83546aa4a12174b29729838946b0aaa0ddf2 100644 (file)
@@ -16,6 +16,8 @@ libbase_la_SOURCES =  \
        dictionary.h \
        dynamicobject.cpp \
        dynamicobject.h \
+       dynamictype.cpp \
+       dynamictype.h \
        event.cpp \
        event.h \
        exception.cpp \
index 42b72a42128e7882e78034891c7750fe8357c9d6..23dac5ed9e96ae4286f423a27a4940cfe3f67320 100644 (file)
@@ -122,7 +122,7 @@ void Application::RunEventLoop(void)
 #ifdef _DEBUG
                if (nextProfile < Utility::GetTime()) {
                        stringstream msgbuf;
-                       msgbuf << "Active objects: " << Object::GetAliveObjects();
+                       msgbuf << "Active objects: " << Object::GetAliveObjectsCount();
                        Logger::Write(LogInformation, "base", msgbuf.str());
 
                        Object::PrintMemoryProfile();
index 233c6bfeb38f25982bcf83d5f555a0d1c9865d34..47253afa4c960cf89e134cab00af29abbfc41a5e 100644 (file)
@@ -24,6 +24,7 @@
     <ClCompile Include="connection.cpp" />
     <ClCompile Include="dynamicobject.cpp" />
     <ClCompile Include="dictionary.cpp" />
+    <ClCompile Include="dynamictype.cpp" />
     <ClCompile Include="event.cpp" />
     <ClCompile Include="exception.cpp" />
     <ClCompile Include="fifo.cpp" />
@@ -61,6 +62,7 @@
     <ClInclude Include="connection.h" />
     <ClInclude Include="dynamicobject.h" />
     <ClInclude Include="dictionary.h" />
+    <ClInclude Include="dynamictype.h" />
     <ClInclude Include="event.h" />
     <ClInclude Include="fifo.h" />
     <ClInclude Include="stdiostream.h" />
index 912b4fe92e7f5b2e9a40427a9a682f684bedd218..af7b4337a7765ea74e027d2da9cac9d6b5336e96 100644 (file)
@@ -88,6 +88,9 @@
     <ClCompile Include="stdiostream.cpp">
       <Filter>Quelldateien</Filter>
     </ClCompile>
+    <ClCompile Include="dynamictype.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="application.h">
     <ClInclude Include="stdiostream.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="dynamictype.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Quelldateien">
index bc66042c69134be17acffd85d91b44034ec9f07a..cf8413e7b01b8eca4514e666b2bfa498917c0035 100644 (file)
@@ -24,7 +24,7 @@
 
 using namespace icinga;
 
-REGISTER_CLASS(Component);
+REGISTER_TYPE(Component, NULL);
 
 /**
  * Constructor for the component class.
index 7be1d424f826015159b933a5e3721457de0e886f..9b50c42cf1c53baec812007d6f02c0db8c94a584 100644 (file)
@@ -219,9 +219,10 @@ void DynamicObject::ClearAttributesByType(DynamicAttributeType type)
        }
 }
 
-String DynamicObject::GetType(void) const
+DynamicType::Ptr DynamicObject::GetType(void) const
 {
-       return Get("__type");
+       String name = Get("__type");
+       return DynamicType::GetByName(name);
 }
 
 String DynamicObject::GetName(void) const
@@ -263,13 +264,11 @@ void DynamicObject::Register(void)
 {
        assert(Application::IsMainThread());
 
-       DynamicObject::Ptr dobj = GetObject(GetType(), GetName());
+       DynamicObject::Ptr dobj = GetType()->GetObject(GetName());
        DynamicObject::Ptr self = GetSelf();
        assert(!dobj || dobj == self);
 
-       pair<DynamicObject::TypeMap::iterator, bool> ti;
-       ti = GetAllObjects().insert(make_pair(GetType(), DynamicObject::NameMap()));
-       ti.first->second.insert(make_pair(GetName(), GetSelf()));
+       GetType()->RegisterObject(self);
 
        OnRegistered(GetSelf());
 
@@ -285,51 +284,14 @@ void DynamicObject::Unregister(void)
 {
        assert(Application::IsMainThread());
 
-       DynamicObject::TypeMap::iterator tt;
-       tt = GetAllObjects().find(GetType());
-
-       if (tt == GetAllObjects().end())
-               return;
-
-       DynamicObject::NameMap::iterator nt = tt->second.find(GetName());
-
-       if (nt == tt->second.end())
+       if (GetType()->GetObject(GetName()))
                return;
 
-       tt->second.erase(nt);
+       GetType()->UnregisterObject(GetSelf());
 
        OnUnregistered(GetSelf());
 }
 
-DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& name)
-{
-       DynamicObject::TypeMap::iterator tt;
-       tt = GetAllObjects().find(type);
-
-       if (tt == GetAllObjects().end())
-               return DynamicObject::Ptr();
-
-       DynamicObject::NameMap::iterator nt = tt->second.find(name);              
-
-       if (nt == tt->second.end())
-               return DynamicObject::Ptr();
-
-       return nt->second;
-}
-
-pair<DynamicObject::TypeMap::iterator, DynamicObject::TypeMap::iterator> DynamicObject::GetTypes(void)
-{
-       return make_pair(GetAllObjects().begin(), GetAllObjects().end());
-}
-
-pair<DynamicObject::NameMap::iterator, DynamicObject::NameMap::iterator> DynamicObject::GetObjects(const String& type)
-{
-       pair<DynamicObject::TypeMap::iterator, bool> ti;
-       ti = GetAllObjects().insert(make_pair(type, DynamicObject::NameMap()));
-
-       return make_pair(ti.first->second.begin(), ti.first->second.end());
-}
-
 ScriptTask::Ptr DynamicObject::InvokeMethod(const String& method,
     const vector<Value>& arguments, ScriptTask::CompletionCallback callback)
 {
@@ -370,12 +332,10 @@ void DynamicObject::DumpObjects(const String& filename)
        StdioStream::Ptr sfp = boost::make_shared<StdioStream>(&fp, false);
        sfp->Start();
 
-       DynamicObject::TypeMap::iterator tt;
-       for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
-               DynamicObject::NameMap::iterator nt;
-               for (nt = tt->second.begin(); nt != tt->second.end(); nt++) {
-                       DynamicObject::Ptr object = nt->second;
-
+       DynamicType::Ptr type;
+       BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) {
+               DynamicObject::Ptr object;
+               BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) {
                        if (object->IsLocal())
                                continue;
 
@@ -449,10 +409,15 @@ void DynamicObject::RestoreObjects(const String& filename)
 
                bool hasConfig = update->Contains("configTx");
 
-               DynamicObject::Ptr object = GetObject(type, name);
+               DynamicType::Ptr dt = DynamicType::GetByName(type);
+
+               if (!dt)
+                       throw_exception(invalid_argument("Invalid type: " + type));
+
+               DynamicObject::Ptr object = dt->GetObject(name);
 
                if (hasConfig && !object) {
-                       object = Create(type, update);
+                       object = dt->CreateObject(update);
                        object->Register();
                } else if (object) {
                        object->ApplyUpdate(update, Attribute_All);
@@ -464,11 +429,11 @@ void DynamicObject::RestoreObjects(const String& filename)
 
 void DynamicObject::DeactivateObjects(void)
 {
-       DynamicObject::TypeMap::iterator tt;
-       for (tt = GetAllObjects().begin(); tt != GetAllObjects().end(); tt++) {
-               DynamicObject::NameMap::iterator nt;
+       DynamicType::TypeMap::iterator tt;
+       for (tt = DynamicType::GetTypes().begin(); tt != DynamicType::GetTypes().end(); tt++) {
+               DynamicType::NameMap::iterator nt;
 
-               while ((nt = tt->second.begin()) != tt->second.end()) {
+               while ((nt = tt->second->GetObjects().begin()) != tt->second->GetObjects().end()) {
                        DynamicObject::Ptr object = nt->second;
 
                        object->Unregister();
@@ -476,52 +441,6 @@ void DynamicObject::DeactivateObjects(void)
        }
 }
 
-DynamicObject::TypeMap& DynamicObject::GetAllObjects(void)
-{
-       static TypeMap objects;
-       return objects;
-}
-
-DynamicObject::ClassMap& DynamicObject::GetClasses(void)
-{
-       static ClassMap classes;
-       return classes;
-}
-
-bool DynamicObject::ClassExists(const String& name)
-{
-       return (GetClasses().find(name) != GetClasses().end());
-}
-
-void DynamicObject::RegisterClass(const String& type, DynamicObject::Factory factory)
-{
-       if (GetObjects(type).first != GetObjects(type).second)
-               throw_exception(runtime_error("Cannot register class for type '" +
-                   type + "': Objects of this type already exist."));
-
-       GetClasses()[type] = factory;
-}
-
-DynamicObject::Ptr DynamicObject::Create(const String& type, const Dictionary::Ptr& serializedUpdate)
-{
-       DynamicObject::ClassMap::iterator ct;
-       ct = GetClasses().find(type);
-
-       DynamicObject::Ptr obj;
-       if (ct != GetClasses().end()) {
-               obj = ct->second(serializedUpdate);
-       } else {
-               obj = boost::make_shared<DynamicObject>(serializedUpdate);
-
-               Logger::Write(LogCritical, "base", "Creating generic DynamicObject for type '" + type + "'");
-       }
-
-       /* apply the object's non-config attributes */
-       obj->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
-
-       return obj;
-}
-
 double DynamicObject::GetCurrentTx(void)
 {
        assert(m_CurrentTx != 0);
@@ -545,3 +464,8 @@ void DynamicObject::FinishTx(void)
 void DynamicObject::OnAttributeChanged(const String&, const Value&)
 { }
 
+DynamicObject::Ptr DynamicObject::GetObject(const String& type, const String& name)
+{
+       DynamicType::Ptr dtype = DynamicType::GetByName(type);
+       return dtype->GetObject(name);
+}
index e7f4814db50c376525a7d7e259d7723772f4831e..828622da99bdd394bc40be3739d873a3d4713f15 100644 (file)
@@ -60,6 +60,8 @@ struct DynamicAttribute
        double Tx; /**< The timestamp of the last value change. */
 };
 
+class DynamicType;
+
 /**
  * A dynamic object that can be instantiated from the configuration file
  * and that supports attribute replication to remote application instances.
@@ -72,12 +74,6 @@ public:
        typedef shared_ptr<DynamicObject> Ptr;
        typedef weak_ptr<DynamicObject> WeakPtr;
 
-       typedef function<DynamicObject::Ptr (const Dictionary::Ptr&)> Factory;
-
-       typedef map<String, Factory, string_iless> ClassMap;
-       typedef map<String, DynamicObject::Ptr, string_iless> NameMap;
-       typedef map<String, NameMap, string_iless> TypeMap;
-
        typedef map<String, DynamicAttribute, string_iless> AttributeMap;
        typedef AttributeMap::iterator AttributeIterator;
        typedef AttributeMap::const_iterator AttributeConstIterator;
@@ -104,7 +100,7 @@ public:
        ScriptTask::Ptr InvokeMethod(const String& method,
            const vector<Value>& arguments, ScriptTask::CompletionCallback callback);
 
-       String GetType(void) const;
+       shared_ptr<DynamicType> GetType(void) const;
        String GetName(void) const;
 
        bool IsLocal(void) const;
@@ -122,17 +118,11 @@ public:
        virtual void Start(void);
 
        static DynamicObject::Ptr GetObject(const String& type, const String& name);
-       static pair<TypeMap::iterator, TypeMap::iterator> GetTypes(void);
-       static pair<NameMap::iterator, NameMap::iterator> GetObjects(const String& type);
 
        static void DumpObjects(const String& filename);
        static void RestoreObjects(const String& filename);
        static void DeactivateObjects(void);
 
-       static void RegisterClass(const String& type, Factory factory);
-       static bool ClassExists(const String& type);
-       static DynamicObject::Ptr Create(const String& type, const Dictionary::Ptr& serializedUpdate);
-
        static double GetCurrentTx(void);
        static void BeginTx(void);
        static void FinishTx(void);
@@ -144,9 +134,6 @@ private:
        void InternalSetAttribute(const String& name, const Value& data, double tx, bool suppressEvent = false);
        Value InternalGetAttribute(const String& name) const;
 
-       static ClassMap& GetClasses(void);
-       static TypeMap& GetAllObjects(void);
-
        AttributeMap m_Attributes;
        double m_ConfigTx;
 
@@ -157,38 +144,6 @@ private:
        void InternalApplyUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes, bool suppressEvents);
 };
 
-/**
- * Helper class for registering DynamicObject implementation classes.
- *
- * @ingroup base
- */
-class RegisterClassHelper
-{
-public:
-       RegisterClassHelper(const String& name, DynamicObject::Factory factory)
-       {
-               if (!DynamicObject::ClassExists(name))
-                       DynamicObject::RegisterClass(name, factory);
-       }
-};
-
-/**
- * Factory function for DynamicObject-based classes.
- *
- * @ingroup base
- */
-template<typename T>
-shared_ptr<T> DynamicObjectFactory(const Dictionary::Ptr& serializedUpdate)
-{
-       return boost::make_shared<T>(serializedUpdate);
-}
-
-#define REGISTER_CLASS_ALIAS(klass, alias) \
-       static RegisterClassHelper g_Register ## klass(alias, DynamicObjectFactory<klass>)
-
-#define REGISTER_CLASS(klass) \
-       REGISTER_CLASS_ALIAS(klass, #klass)
-
 }
 
 #endif /* DYNAMICOBJECT_H */
diff --git a/lib/base/dynamictype.cpp b/lib/base/dynamictype.cpp
new file mode 100644 (file)
index 0000000..9313a6d
--- /dev/null
@@ -0,0 +1,118 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "i2-base.h"
+
+using namespace icinga;
+
+DynamicType::DynamicType(const String& name, const DynamicType::ObjectFactory& factory)
+       : m_Name(name), m_ObjectFactory(factory)
+{ }
+
+DynamicType::Ptr DynamicType::GetByName(const String& name)
+{
+       DynamicType::TypeMap::const_iterator tt = GetTypes().find(name);
+
+       if (tt == GetTypes().end())
+               return DynamicType::Ptr();
+
+       return tt->second;
+}
+
+DynamicType::TypeMap& DynamicType::GetTypes(void)
+{
+       static DynamicType::TypeMap types;
+       return types;
+}
+
+DynamicType::NameMap& DynamicType::GetObjects(void)
+{
+       return m_Objects;
+}
+
+String DynamicType::GetName(void) const
+{
+       return m_Name;
+}
+
+void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
+{
+       m_Objects[object->GetName()] = object;
+}
+
+void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
+{
+       m_Objects.erase(object->GetName());
+}
+
+DynamicObject::Ptr DynamicType::GetObject(const String& name) const
+{
+       DynamicType::NameMap::const_iterator nt = m_Objects.find(name);
+
+       if (nt == m_Objects.end())
+               return DynamicObject::Ptr();
+
+       return nt->second;
+}
+
+void DynamicType::RegisterType(const DynamicType::Ptr& type)
+{
+       if (GetByName(type->GetName()))
+               throw_exception(runtime_error("Cannot register class for type '" +
+                   type->GetName() + "': Objects of this type already exist."));
+
+       GetTypes()[type->GetName()] = type;
+}
+
+DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUpdate) const
+{
+       DynamicObject::Ptr obj = m_ObjectFactory(serializedUpdate);
+
+       /* register attributes */
+       String name;
+       DynamicAttributeType type;
+       BOOST_FOREACH(tuples::tie(name, type), m_Attributes)
+               obj->RegisterAttribute(name, type);
+
+       /* apply the object's non-config attributes */
+       obj->ApplyUpdate(serializedUpdate, Attribute_All & ~Attribute_Config);
+
+       return obj;
+}
+
+bool DynamicType::TypeExists(const String& name)
+{
+       return (GetByName(name));
+}
+
+void DynamicType::AddAttribute(const String& name, DynamicAttributeType type)
+{
+       m_Attributes[name] = type;
+}
+
+void DynamicType::RemoveAttribute(const String& name)
+{
+       m_Attributes.erase(name);
+}
+
+void DynamicType::AddAttributes(const AttributeDescription *attributes, int attributeCount)
+{
+       for (int i = 0; i < attributeCount; i++)
+               AddAttribute(attributes[i].Name, attributes[i].Type);
+}
\ No newline at end of file
diff --git a/lib/base/dynamictype.h b/lib/base/dynamictype.h
new file mode 100644 (file)
index 0000000..7b47c75
--- /dev/null
@@ -0,0 +1,110 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program is free software; you can redistribute it and/or              *
+ * modify it under the terms of the GNU General Public License                *
+ * as published by the Free Software Foundation; either version 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program is distributed in the hope that it will be useful,            *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+ * GNU General Public License for more details.                               *
+ *                                                                            *
+ * You should have received a copy of the GNU General Public License          *
+ * along with this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef DYNAMICTYPE_H
+#define DYNAMICTYPE_H
+
+namespace icinga
+{
+
+struct AttributeDescription
+{
+       String Name;
+       DynamicAttributeType Type;
+};
+
+class I2_BASE_API DynamicType : public Object
+{
+public:
+       typedef shared_ptr<DynamicType> Ptr;
+       typedef weak_ptr<DynamicType> WeakPtr;
+
+       typedef function<DynamicObject::Ptr (const Dictionary::Ptr&)> ObjectFactory;
+       typedef map<String, DynamicType::Ptr, string_iless> TypeMap;
+       typedef map<String, DynamicObject::Ptr, string_iless> NameMap;
+
+       DynamicType(const String& name, const ObjectFactory& factory);
+
+       String GetName(void) const;
+
+       static DynamicType::Ptr GetByName(const String& name);
+
+       static void RegisterType(const DynamicType::Ptr& type);
+       static bool TypeExists(const String& name);
+       
+       DynamicObject::Ptr CreateObject(const Dictionary::Ptr& serializedUpdate) const;
+       DynamicObject::Ptr GetObject(const String& name) const;
+
+       void RegisterObject(const DynamicObject::Ptr& object);
+       void UnregisterObject(const DynamicObject::Ptr& object);
+
+       static TypeMap& GetTypes(void);
+       NameMap& GetObjects(void);
+
+       void AddAttribute(const String& name, DynamicAttributeType type);
+       void RemoveAttribute(const String& name);
+
+       void AddAttributes(const AttributeDescription *attributes, int attributeCount);
+
+private:
+       String m_Name;
+       ObjectFactory m_ObjectFactory;
+       map<String, DynamicAttributeType> m_Attributes;
+
+       NameMap m_Objects;
+};
+
+/**
+ * Helper class for registering DynamicObject implementation classes.
+ *
+ * @ingroup base
+ */
+class RegisterTypeHelper
+{
+public:
+       RegisterTypeHelper(const String& name, const DynamicType::ObjectFactory& factory, const AttributeDescription* attributes, int attributeCount)
+       {
+               if (!DynamicType::TypeExists(name)) {
+                       DynamicType::Ptr type = boost::make_shared<DynamicType>(name, factory);
+                       type->AddAttributes(attributes, attributeCount);
+                       DynamicType::RegisterType(type);
+               }
+       }
+};
+
+/**
+ * Factory function for DynamicObject-based classes.
+ *
+ * @ingroup base
+ */
+template<typename T>
+shared_ptr<T> DynamicObjectFactory(const Dictionary::Ptr& serializedUpdate)
+{
+       return boost::make_shared<T>(serializedUpdate);
+}
+
+#define REGISTER_TYPE_ALIAS(type, alias, attributeDesc) \
+       static RegisterTypeHelper g_Register ## type(alias, DynamicObjectFactory<type>, attributeDesc, (attributeDesc == NULL) ? 0 : sizeof(attributeDesc) / sizeof((static_cast<AttributeDescription *>(attributeDesc))[0]))
+
+#define REGISTER_TYPE(type, attributeDesc) \
+       REGISTER_TYPE_ALIAS(type, #type, attributeDesc)
+
+}
+
+#endif /* DYNAMICTYPE_H */
index c529d2850bc3d3d54a37e76cb42786db2ceeddd8..0ec12ad5b78d303057dcf0fc4e0596b0c96f76c3 100644 (file)
@@ -192,6 +192,7 @@ namespace tuples = boost::tuples;
 #include "scriptfunction.h"
 #include "scripttask.h"
 #include "dynamicobject.h"
+#include "dynamictype.h"
 #include "logger.h"
 #include "application.h"
 #include "component.h"
index 3ed277df1a8ae311a3afc1d111480ee446671380..c9c9e7e13a0e45c59a19b1d7da64bba7dbdef4a5 100644 (file)
 
 using namespace icinga;
 
-REGISTER_CLASS(Logger);
+static AttributeDescription loggerAttributes[] = {
+       { "type", Attribute_Config },
+       { "path", Attribute_Config },
+       { "severity", Attribute_Config }
+};
+
+REGISTER_TYPE(Logger, loggerAttributes);
 
 /**
  * Constructor for the Logger class.
@@ -31,10 +37,6 @@ REGISTER_CLASS(Logger);
 Logger::Logger(const Dictionary::Ptr& properties)
        : DynamicObject(properties)
 {
-       RegisterAttribute("type", Attribute_Config);
-       RegisterAttribute("path", Attribute_Config);
-       RegisterAttribute("severity", Attribute_Config);
-
        if (!IsLocal())
                throw_exception(runtime_error("Logger objects must be local."));
 
@@ -111,8 +113,10 @@ void Logger::ForwardLogEntry(const LogEntry& entry)
 {
        bool processed = false;
 
+       DynamicType::Ptr dt = DynamicType::GetByName("Logger");
+
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Logger")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), dt->GetObjects()) {
                Logger::Ptr logger = dynamic_pointer_cast<Logger>(object);
 
                if (entry.Severity >= logger->GetMinSeverity())
index a0f7d03d2ed3e5c9578f0549ab9ee7f90a9be555..5e7486b49a20f8458c08da365d41b440f5e86495 100644 (file)
 
 using namespace icinga;
 
-boost::mutex Object::m_Mutex;
-vector<Object::Ptr> Object::m_HeldObjects;
-#ifdef _DEBUG
-set<Object *> Object::m_AliveObjects;
-#endif /* _DEBUG */
-
 /**
  * Default constructor for the Object class.
  */
 Object::Object(void)
 {
 #ifdef _DEBUG
-       boost::mutex::scoped_lock lock(m_Mutex);
-       m_AliveObjects.insert(this);
+       boost::mutex::scoped_lock lock(GetMutex());
+       GetAliveObjects().insert(this);
 #endif /* _DEBUG */
 }
 
@@ -44,8 +38,8 @@ Object::Object(void)
 Object::~Object(void)
 {
 #ifdef _DEBUG
-       boost::mutex::scoped_lock lock(m_Mutex);
-       m_AliveObjects.erase(this);
+       boost::mutex::scoped_lock lock(GetMutex());
+       GetAliveObjects().erase(this);
 #endif /* _DEBUG */
 }
 
@@ -56,8 +50,8 @@ Object::~Object(void)
  */
 void Object::Hold(void)
 {
-       boost::mutex::scoped_lock lock(m_Mutex);
-       m_HeldObjects.push_back(GetSelf());
+       boost::mutex::scoped_lock lock(GetMutex());
+       GetHeldObjects().push_back(GetSelf());
 }
 
 /**
@@ -65,8 +59,8 @@ void Object::Hold(void)
  */
 void Object::ClearHeldObjects(void)
 {
-       boost::mutex::scoped_lock lock(m_Mutex);
-       m_HeldObjects.clear();
+       boost::mutex::scoped_lock lock(GetMutex());
+       GetHeldObjects().clear();
 }
 
 /**
@@ -85,10 +79,10 @@ Object::SharedPtrHolder Object::GetSelf(void)
  *
  * @returns The number of alive objects.
  */
-int Object::GetAliveObjects(void)
+int Object::GetAliveObjectsCount(void)
 {
-       boost::mutex::scoped_lock lock(m_Mutex);
-       return m_AliveObjects.size();
+       boost::mutex::scoped_lock lock(GetMutex());
+       return GetAliveObjects().size();
 }
 
 /**
@@ -101,9 +95,9 @@ void Object::PrintMemoryProfile(void)
        ofstream dictfp("dictionaries.dump.tmp");
 
        {
-               boost::mutex::scoped_lock lock(m_Mutex);
+               boost::mutex::scoped_lock lock(GetMutex());
                set<Object *>::iterator it;
-               BOOST_FOREACH(Object *obj, m_AliveObjects) {
+               BOOST_FOREACH(Object *obj, GetAliveObjects()) {
                        pair<map<String, int>::iterator, bool> tt;
                        tt = types.insert(make_pair(Utility::GetTypeName(typeid(*obj)), 1));
                        if (!tt.second)
@@ -130,4 +124,40 @@ void Object::PrintMemoryProfile(void)
                std::cerr << type << ": " << count << std::endl;
        }
 }
+
+/**
+ * Returns currently active objects.
+ *
+ * @returns currently active objects
+ */
+set<Object *>& Object::GetAliveObjects(void)
+{
+       static set<Object *> aliveObjects;
+       return aliveObjects;
+}
 #endif /* _DEBUG */
+
+/**
+ * Returns the mutex used for accessing static members.
+ *
+ * @returns a mutex
+ */
+boost::mutex& Object::GetMutex(void)
+{
+       static boost::mutex mutex;
+       return mutex;
+}
+
+/**
+ * Returns currently held objects. The caller must be
+ * holding the mutex returned by GetMutex().
+ *
+ * @returns currently held objects
+ */
+vector<Object::Ptr>& Object::GetHeldObjects(void)
+{
+       static vector<Object::Ptr> heldObjects;
+       return heldObjects;
+}
+
+
index 038819ac7a2a173c2d2e4c442453f0431715afd9..940f4837fcb993867bcf732799896984cc665847 100644 (file)
@@ -97,7 +97,7 @@ public:
        SharedPtrHolder GetSelf(void);
 
 #ifdef _DEBUG
-       static int GetAliveObjects(void);
+       static int GetAliveObjectsCount(void);
        static void PrintMemoryProfile(void);
 #endif /* _DEBUG */
 
@@ -109,14 +109,9 @@ private:
        Object(const Object& other);
        Object& operator=(const Object& rhs);
 
-       static boost::mutex m_Mutex; /**< Mutex which protects static members
-                                         of the Object class. */
-       static vector<Object::Ptr> m_HeldObjects; /**< Currently held
-                                                      objects. */
-#ifdef _DEBUG
-       static set<Object *> m_AliveObjects; /**< Currently alive objects -
-                                                 for debugging purposes. */
-#endif /* _DEBUG */
+       static boost::mutex& GetMutex(void);
+       static set<Object *>& GetAliveObjects(void);
+       static vector<Object::Ptr>& GetHeldObjects(void);
 };
 
 /**
index 3f5973eda01196aee4079000fb6109adb1222c00..33f0891821ea44df404de4f0313c77e235345a94 100644 (file)
@@ -37,6 +37,9 @@ Socket::Socket(void)
  */
 Socket::~Socket(void)
 {
+       m_SendQueue->Close();
+       m_RecvQueue->Close();
+
        Close();
 }
 
index 947ed9194cdcf75721d114d1940043ab5d4058cd..ae803a9f362c931f9260f52828038b5890cf96db 100644 (file)
@@ -215,6 +215,9 @@ void TlsStream::Close(void)
        if (m_SSL)
                SSL_shutdown(m_SSL.get());
 
+       m_SendQueue->Close();
+       m_RecvQueue->Close();
+
        Stream::Close();
 }
 
index 927ef341dff6eb6a2c3804b0514837fb9101cfc4..8690162f518cbc6db894e32b31ed0bae83fc3d88 100644 (file)
@@ -148,11 +148,13 @@ DynamicObject::Ptr ConfigItem::Commit(void)
        update->Set("attrs", attrs);
        update->Set("configTx", DynamicObject::GetCurrentTx());
 
+       DynamicType::Ptr dtype = DynamicType::GetByName(GetType());
+
        if (!dobj)
-               dobj = DynamicObject::GetObject(GetType(), GetName());
+               dobj = dtype->GetObject(GetName());
 
        if (!dobj)
-               dobj = DynamicObject::Create(GetType(), update);
+               dobj = dtype->CreateObject(update);
        else
                dobj->ApplyUpdate(update, Attribute_Config);
 
index b402780f0731e5ec3555d4720e0760dc165ccdaf..7fafd78958270076ed418c0b5a9ab31ebe55ad5b 100644 (file)
 
 using namespace icinga;
 
-REGISTER_CLASS(Host);
+static AttributeDescription hostAttributes[] = {
+       { "alias", Attribute_Config },
+       { "hostgroups", Attribute_Config }
+};
+
+REGISTER_TYPE(Host, hostAttributes);
 
 bool Host::m_InitializerDone = false;
 
@@ -34,9 +39,6 @@ Host::Host(const Dictionary::Ptr& properties)
 
                m_InitializerDone = true;
        }
-
-       RegisterAttribute("alias", Attribute_Config);
-       RegisterAttribute("hostgroups", Attribute_Config);
 }
 
 String Host::GetAlias(void) const
index 1d9cc7b04cf6f4cd1102e8e16c6cebc284e96a6b..0838ef764e22c60e46a28069d2b24ec1806eb8d5 100644 (file)
 
 using namespace icinga;
 
-REGISTER_CLASS(HostGroup);
+static AttributeDescription hostGroupAttributes[] = {
+       { "alias", Attribute_Config },
+       { "notes_url", Attribute_Config },
+       { "action_url", Attribute_Config }
+};
+
+REGISTER_TYPE(HostGroup, hostGroupAttributes);
 
 String HostGroup::GetAlias(void) const
 {
index a6500b4b9d6e0c9450d1a6199f43c0a95873bfca..68b716f474cbaeda7ef89d1ee1267074523a3ee1 100644 (file)
 #include <iostream>
 #include "i2-icinga.h"
 
+using namespace icinga;
+
+static AttributeDescription icingaApplicationAttributes[] = {
+       { "cert_path", Attribute_Config },
+       { "ca_path", Attribute_Config },
+       { "node", Attribute_Config },
+       { "service", Attribute_Config },
+       { "pid_path", Attribute_Config },
+       { "state_path", Attribute_Config },
+       { "macros", Attribute_Config }
+};
+
+REGISTER_TYPE(IcingaApplication, icingaApplicationAttributes);
+
 #ifndef _WIN32
 #      include "icinga-version.h"
 #      define ICINGA_VERSION GIT_MESSAGE
 #endif /* _WIN32 */
 
-using namespace icinga;
-
 const String IcingaApplication::DefaultPidPath = "icinga2.pid";
 const String IcingaApplication::DefaultStatePath = "icinga2.state";
 
index e238fa6ae3fbf2e8dde2ffa8ee4b1ba290c13d37..01c1a920bfe0ef813e9280e1063a2c6bf49a9773 100644 (file)
@@ -64,8 +64,6 @@ private:
        void DumpProgramState(void);
 };
 
-REGISTER_CLASS(IcingaApplication);
-
 }
 
 #endif /* ICINGAAPPLICATION_H */
index 4b1b249847e97b0ae8d7e5e99e357a6457472b19..c01b7640ebef7cf72c81db718110bdb2d103c590 100644 (file)
 
 using namespace icinga;
 
-REGISTER_CLASS(Service);
+static AttributeDescription serviceAttributes[] = {
+       { "alias", Attribute_Config },
+       { "host_name", Attribute_Config },
+       { "macros", Attribute_Config },
+       { "check_command", Attribute_Config },
+       { "max_check_attempts", Attribute_Config },
+       { "check_interval", Attribute_Config },
+       { "retry_interval", Attribute_Config },
+       { "dependencies", Attribute_Config },
+       { "servicegroups", Attribute_Config },
+       { "checkers", Attribute_Config },
+
+       { "scheduling_offset", Attribute_Transient },
+       { "next_check", Attribute_Replicated },
+       { "checker", Attribute_Replicated },
+       { "check_attempt", Attribute_Replicated },
+       { "state", Attribute_Replicated },
+       { "state_type", Attribute_Replicated },
+       { "last_result", Attribute_Replicated },
+       { "last_state_change", Attribute_Replicated },
+       { "last_hard_state_change", Attribute_Replicated }
+};
+
+REGISTER_TYPE(Service, serviceAttributes);
 
 const int Service::DefaultMaxCheckAttempts = 3;
 const int Service::DefaultCheckInterval = 5 * 60;
@@ -33,28 +56,7 @@ boost::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChang
 
 Service::Service(const Dictionary::Ptr& serializedObject)
        : DynamicObject(serializedObject)
-{
-       RegisterAttribute("alias", Attribute_Config);
-       RegisterAttribute("host_name", Attribute_Config);
-       RegisterAttribute("macros", Attribute_Config);
-       RegisterAttribute("check_command", Attribute_Config);
-       RegisterAttribute("max_check_attempts", Attribute_Config);
-       RegisterAttribute("check_interval", Attribute_Config);
-       RegisterAttribute("retry_interval", Attribute_Config);
-       RegisterAttribute("dependencies", Attribute_Config);
-       RegisterAttribute("servicegroups", Attribute_Config);
-       RegisterAttribute("checkers", Attribute_Config);
-
-       RegisterAttribute("scheduling_offset", Attribute_Transient);
-       RegisterAttribute("next_check", Attribute_Replicated);
-       RegisterAttribute("checker", Attribute_Replicated);
-       RegisterAttribute("check_attempt", Attribute_Replicated);
-       RegisterAttribute("state", Attribute_Replicated);
-       RegisterAttribute("state_type", Attribute_Replicated);
-       RegisterAttribute("last_result", Attribute_Replicated);
-       RegisterAttribute("last_state_change", Attribute_Replicated);
-       RegisterAttribute("last_hard_state_change", Attribute_Replicated);
-}
+{ }
 
 String Service::GetAlias(void) const
 {
index d5f5bc1b62cc2d8b1afe84a9bbbd109b52a1e1f6..31b413fc43ab22701d69611d857ec58d3f0d27d1 100644 (file)
 
 using namespace icinga;
 
-REGISTER_CLASS(ServiceGroup);
+static AttributeDescription serviceGroupAttributes[] = {
+       { "alias", Attribute_Config },
+       { "notes_url", Attribute_Config },
+       { "action_url",  Attribute_Config }
+};
+
+REGISTER_TYPE(ServiceGroup, serviceGroupAttributes);
 
 String ServiceGroup::GetAlias(void) const
 {
index 1746189e750ad93a0b09885e5cf409a86da1bb0b..99d26848e0566fc31f22d2b09b88515c8d8400d9 100644 (file)
 
 using namespace icinga;
 
-REGISTER_CLASS(Endpoint);
+static AttributeDescription endpointAttributes[] = {
+       { "node", Attribute_Replicated },
+       { "service", Attribute_Replicated },
+       { "local", Attribute_Config },
+       { "subscriptions", Attribute_Replicated },
+       { "client", Attribute_Transient }
+};
+
+REGISTER_TYPE(Endpoint, endpointAttributes);
 
 boost::signal<void (const Endpoint::Ptr&)> Endpoint::OnConnected;
 boost::signal<void (const Endpoint::Ptr&)> Endpoint::OnDisconnected;
@@ -35,13 +43,7 @@ boost::signal<void (const Endpoint::Ptr&, const String& topic)> Endpoint::OnSubs
  */
 Endpoint::Endpoint(const Dictionary::Ptr& serializedUpdate)
        : DynamicObject(serializedUpdate)
-{
-       RegisterAttribute("node", Attribute_Replicated);
-       RegisterAttribute("service", Attribute_Replicated);
-       RegisterAttribute("local", Attribute_Config);
-       RegisterAttribute("subscriptions", Attribute_Replicated);
-       RegisterAttribute("client", Attribute_Transient);
-}
+{ }
 
 /**
  * Checks whether an endpoint with the specified name exists.
index c25801addb0624672207712047abdd7df88f4df8..299e24ab5400670e75ee139c3095a8b1f0985b13 100644 (file)
@@ -151,6 +151,7 @@ void EndpointManager::NewClientHandler(const Socket::Ptr& client, TlsRole role)
 
        m_PendingClients.insert(tlsStream);
        tlsStream->OnConnected.connect(boost::bind(&EndpointManager::ClientConnectedHandler, this, _1, peerAddress));
+       tlsStream->OnClosed.connect(boost::bind(&EndpointManager::ClientClosedHandler, this, _1));
 
        client->Start();
 }
@@ -177,6 +178,12 @@ void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const St
        endpoint->SetClient(jclient);
 }
 
+void EndpointManager::ClientClosedHandler(const Stream::Ptr& client)
+{
+       TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
+       m_PendingClients.erase(tlsStream);
+}
+
 /**
  * Sends a unicast message to the specified recipient.
  *
@@ -213,7 +220,7 @@ void EndpointManager::SendAnycastMessage(const Endpoint::Ptr& sender,
 
        vector<Endpoint::Ptr> candidates;
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
                Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
                /* don't forward messages between non-local endpoints */
                if (!sender->IsLocal() && !endpoint->IsLocal())
@@ -249,7 +256,7 @@ void EndpointManager::SendMulticastMessage(const Endpoint::Ptr& sender,
                throw_exception(invalid_argument("Message is missing the 'method' property."));
 
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
                Endpoint::Ptr recipient = dynamic_pointer_cast<Endpoint>(object);
 
                /* don't forward messages back to the sender */
@@ -297,7 +304,7 @@ void EndpointManager::SubscriptionTimerHandler(void)
        Dictionary::Ptr subscriptions = boost::make_shared<Dictionary>();
 
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
                Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
 
                if (!endpoint->IsLocalEndpoint())
@@ -316,7 +323,7 @@ void EndpointManager::SubscriptionTimerHandler(void)
 void EndpointManager::ReconnectTimerHandler(void)
 {
        DynamicObject::Ptr object;
-       BOOST_FOREACH(tie(tuples::ignore, object), DynamicObject::GetObjects("Endpoint")) {
+       BOOST_FOREACH(tie(tuples::ignore, object), DynamicType::GetByName("Endpoint")->GetObjects()) {
                Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
 
                if (endpoint->IsConnected() || endpoint == m_Endpoint)
index 9ae73ce439dbea777c636393ba8f3c77ed43ec80..b491846a10ef5b8d73728dcb2c82c34cb2430bbe 100644 (file)
@@ -103,6 +103,7 @@ private:
 
        void NewClientHandler(const Socket::Ptr& client, TlsRole rol);
        void ClientConnectedHandler(const Stream::Ptr& client, const String& peerAddress);
+       void ClientClosedHandler(const Stream::Ptr& client);
 };
 
 }