Improve performance for type lookups

fixes #12448
This commit is contained in:
Gunnar Beutner 2016-08-16 11:02:10 +02:00
parent a34e01d0bb
commit b7a1b58069
21 changed files with 233 additions and 221 deletions

View File

@ -51,11 +51,6 @@ boost::signals2::signal<void (const ConfigObject::Ptr&)> ConfigObject::OnStateCh
ConfigObject::ConfigObject(void) ConfigObject::ConfigObject(void)
{ } { }
ConfigType::Ptr ConfigObject::GetType(void) const
{
return ConfigType::GetByName(GetReflectionType()->GetName());
}
bool ConfigObject::IsActive(void) const bool ConfigObject::IsActive(void) const
{ {
return GetActive(); return GetActive();
@ -103,7 +98,8 @@ class ModAttrValidationUtils : public ValidationUtils
public: public:
virtual bool ValidateName(const String& type, const String& name) const override virtual bool ValidateName(const String& type, const String& name) const override
{ {
ConfigType::Ptr dtype = ConfigType::GetByName(type); Type::Ptr ptype = Type::GetByName(type);
ConfigType *dtype = dynamic_cast<ConfigType *>(ptype.get());
if (!dtype) if (!dtype)
return false; return false;
@ -361,16 +357,16 @@ void ConfigObject::Register(void)
{ {
ASSERT(!OwnsLock()); ASSERT(!OwnsLock());
ConfigType::Ptr dtype = GetType(); TypeImpl<ConfigObject>::Ptr type = static_pointer_cast<TypeImpl<ConfigObject> >(GetReflectionType());
dtype->RegisterObject(this); type->RegisterObject(this);
} }
void ConfigObject::Unregister(void) void ConfigObject::Unregister(void)
{ {
ASSERT(!OwnsLock()); ASSERT(!OwnsLock());
ConfigType::Ptr dtype = GetType(); TypeImpl<ConfigObject>::Ptr type = static_pointer_cast<TypeImpl<ConfigObject> >(GetReflectionType());
dtype->UnregisterObject(this); type->UnregisterObject(this);
} }
void ConfigObject::Start(bool runtimeCreated) void ConfigObject::Start(bool runtimeCreated)
@ -440,7 +436,17 @@ void ConfigObject::OnConfigLoaded(void)
void ConfigObject::OnAllConfigLoaded(void) void ConfigObject::OnAllConfigLoaded(void)
{ {
m_Zone = GetObject("Zone", GetZoneName()); static ConfigType *ctype;
if (!ctype) {
Type::Ptr type = Type::GetByName("Zone");
ctype = dynamic_cast<ConfigType *>(type.get());
}
String zoneName = GetZoneName();
if (!zoneName.IsEmpty())
m_Zone = ctype->GetObject(zoneName);
} }
void ConfigObject::CreateChildObjects(const Type::Ptr& childType) void ConfigObject::CreateChildObjects(const Type::Ptr& childType)
@ -494,8 +500,13 @@ void ConfigObject::DumpObjects(const String& filename, int attributeTypes)
StdioStream::Ptr sfp = new StdioStream(&fp, false); StdioStream::Ptr sfp = new StdioStream(&fp, false);
BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) { BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
Dictionary::Ptr persistentObject = new Dictionary(); Dictionary::Ptr persistentObject = new Dictionary();
persistentObject->Set("type", type->GetName()); persistentObject->Set("type", type->GetName());
@ -535,15 +546,9 @@ void ConfigObject::RestoreObject(const String& message, int attributeTypes)
Dictionary::Ptr persistentObject = JsonDecode(message); Dictionary::Ptr persistentObject = JsonDecode(message);
String type = persistentObject->Get("type"); String type = persistentObject->Get("type");
ConfigType::Ptr dt = ConfigType::GetByName(type);
if (!dt)
return;
String name = persistentObject->Get("name"); String name = persistentObject->Get("name");
ConfigObject::Ptr object = dt->GetObject(name); ConfigObject::Ptr object = GetObject(type, name);
if (!object) if (!object)
return; return;
@ -597,8 +602,13 @@ void ConfigObject::RestoreObjects(const String& filename, int attributeTypes)
unsigned long no_state = 0; unsigned long no_state = 0;
BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) { BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
if (!object->GetStateLoaded()) { if (!object->GetStateLoaded()) {
object->OnStateLoaded(); object->OnStateLoaded();
object->SetStateLoaded(true); object->SetStateLoaded(true);
@ -614,8 +624,13 @@ void ConfigObject::RestoreObjects(const String& filename, int attributeTypes)
void ConfigObject::StopObjects(void) void ConfigObject::StopObjects(void)
{ {
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) { BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
object->Deactivate(); object->Deactivate();
} }
} }
@ -623,8 +638,13 @@ void ConfigObject::StopObjects(void)
void ConfigObject::DumpModifiedAttributes(const boost::function<void(const ConfigObject::Ptr&, const String&, const Value&)>& callback) void ConfigObject::DumpModifiedAttributes(const boost::function<void(const ConfigObject::Ptr&, const String&, const Value&)>& callback)
{ {
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) { BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
Dictionary::Ptr originalAttributes = object->GetOriginalAttributes(); Dictionary::Ptr originalAttributes = object->GetOriginalAttributes();
if (!originalAttributes) if (!originalAttributes)
@ -680,10 +700,13 @@ void ConfigObject::DumpModifiedAttributes(const boost::function<void(const Confi
ConfigObject::Ptr ConfigObject::GetObject(const String& type, const String& name) ConfigObject::Ptr ConfigObject::GetObject(const String& type, const String& name)
{ {
ConfigType::Ptr dtype = ConfigType::GetByName(type); Type::Ptr ptype = Type::GetByName(type);
if (!dtype) ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!ctype)
return ConfigObject::Ptr(); return ConfigObject::Ptr();
return dtype->GetObject(name);
return ctype->GetObject(name);
} }
ConfigObject::Ptr ConfigObject::GetZone(void) const ConfigObject::Ptr ConfigObject::GetZone(void) const

View File

@ -17,8 +17,8 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
#ifndef DYNAMICOBJECT_H #ifndef CONFIGOBJECT_H
#define DYNAMICOBJECT_H #define CONFIGOBJECT_H
#include "base/i2-base.hpp" #include "base/i2-base.hpp"
#include "base/configobject.thpp" #include "base/configobject.thpp"
@ -44,8 +44,6 @@ public:
static boost::signals2::signal<void (const ConfigObject::Ptr&)> OnStateChanged; static boost::signals2::signal<void (const ConfigObject::Ptr&)> OnStateChanged;
intrusive_ptr<ConfigType> GetType(void) const;
bool IsActive(void) const; bool IsActive(void) const;
bool IsPaused(void) const; bool IsPaused(void) const;
@ -80,9 +78,9 @@ public:
template<typename T> template<typename T>
static intrusive_ptr<T> GetObject(const String& name) static intrusive_ptr<T> GetObject(const String& name)
{ {
ConfigObject::Ptr object = GetObject(T::GetTypeName(), name); typedef TypeImpl<T> ObjType;
ObjType *ptype = static_cast<ObjType *>(T::TypeInstance.get());
return static_pointer_cast<T>(object); return static_pointer_cast<T>(ptype->GetObject(name));
} }
static ConfigObject::Ptr GetObject(const String& type, const String& name); static ConfigObject::Ptr GetObject(const String& type, const String& name);
@ -117,4 +115,4 @@ private:
} }
#endif /* DYNAMICOBJECT_H */ #endif /* CONFIGOBJECT_H */

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include "base/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/configtype.hpp"
library base; library base;
@ -67,9 +68,10 @@ public:
private: private:
DebugInfo m_DebugInfo; DebugInfo m_DebugInfo;
}; };
}}} }}}
abstract class ConfigObject : ConfigObjectBase abstract class ConfigObject : ConfigObjectBase < ConfigType
{ {
[config, no_user_modify] String __name (Name); [config, no_user_modify] String __name (Name);
[config, no_user_modify] String "name" (ShortName) { [config, no_user_modify] String "name" (ShortName) {

View File

@ -17,75 +17,25 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
#include "base/configtype.hpp" #include "base/configobject.hpp"
#include "base/serializer.hpp"
#include "base/debug.hpp"
#include "base/objectlock.hpp"
#include "base/convert.hpp" #include "base/convert.hpp"
#include "base/exception.hpp" #include "base/exception.hpp"
using namespace icinga; using namespace icinga;
ConfigType::ConfigType(const String& name) ConfigType::~ConfigType(void)
: m_Name(name)
{ } { }
ConfigType::Ptr ConfigType::GetByName(const String& name) ConfigObject::Ptr ConfigType::GetObject(const String& name) const
{ {
boost::mutex::scoped_lock lock(GetStaticMutex()); boost::mutex::scoped_lock lock(m_Mutex);
ConfigType::TypeMap::const_iterator tt = InternalGetTypeMap().find(name); ConfigType::ObjectMap::const_iterator nt = m_ObjectMap.find(name);
if (tt == InternalGetTypeMap().end()) { if (nt == m_ObjectMap.end())
Type::Ptr type = Type::GetByName(name); return ConfigObject::Ptr();
if (!type || !ConfigObject::TypeInstance->IsAssignableFrom(type) return nt->second;
|| type->IsAbstract())
return ConfigType::Ptr();
ConfigType::Ptr dtype = new ConfigType(name);
InternalGetTypeMap()[type->GetName()] = dtype;
InternalGetTypeVector().push_back(dtype);
return dtype;
}
return tt->second;
}
/**
* Note: Caller must hold ConfigType::GetStaticMutex() while using the map.
*/
ConfigType::TypeMap& ConfigType::InternalGetTypeMap(void)
{
static ConfigType::TypeMap typemap;
return typemap;
}
ConfigType::TypeVector& ConfigType::InternalGetTypeVector(void)
{
static ConfigType::TypeVector typevector;
return typevector;
}
ConfigType::TypeVector ConfigType::GetTypes(void)
{
boost::mutex::scoped_lock lock(GetStaticMutex());
return InternalGetTypeVector(); /* Making a copy of the vector here. */
}
std::pair<ConfigTypeIterator<ConfigObject>, ConfigTypeIterator<ConfigObject> > ConfigType::GetObjects(void)
{
return std::make_pair(
ConfigTypeIterator<ConfigObject>(this, 0),
ConfigTypeIterator<ConfigObject>(this, -1)
);
}
String ConfigType::GetName(void) const
{
return m_Name;
} }
void ConfigType::RegisterObject(const ConfigObject::Ptr& object) void ConfigType::RegisterObject(const ConfigObject::Ptr& object)
@ -93,7 +43,7 @@ void ConfigType::RegisterObject(const ConfigObject::Ptr& object)
String name = object->GetName(); String name = object->GetName();
{ {
ObjectLock olock(this); boost::mutex::scoped_lock lock(m_Mutex);
ObjectMap::iterator it = m_ObjectMap.find(name); ObjectMap::iterator it = m_ObjectMap.find(name);
@ -101,7 +51,9 @@ void ConfigType::RegisterObject(const ConfigObject::Ptr& object)
if (it->second == object) if (it->second == object)
return; return;
BOOST_THROW_EXCEPTION(ScriptError("An object with type '" + m_Name + "' and name '" + name + "' already exists (" + Type *type = dynamic_cast<Type *>(this);
BOOST_THROW_EXCEPTION(ScriptError("An object with type '" + type->GetName() + "' and name '" + name + "' already exists (" +
Convert::ToString(it->second->GetDebugInfo()) + "), new declaration: " + Convert::ToString(object->GetDebugInfo()), Convert::ToString(it->second->GetDebugInfo()) + "), new declaration: " + Convert::ToString(object->GetDebugInfo()),
object->GetDebugInfo())); object->GetDebugInfo()));
} }
@ -116,28 +68,19 @@ void ConfigType::UnregisterObject(const ConfigObject::Ptr& object)
String name = object->GetName(); String name = object->GetName();
{ {
ObjectLock olock(this); boost::mutex::scoped_lock lock(m_Mutex);
m_ObjectMap.erase(name); m_ObjectMap.erase(name);
m_ObjectVector.erase(std::remove(m_ObjectVector.begin(), m_ObjectVector.end(), object), m_ObjectVector.end()); m_ObjectVector.erase(std::remove(m_ObjectVector.begin(), m_ObjectVector.end(), object), m_ObjectVector.end());
} }
} }
ConfigObject::Ptr ConfigType::GetObject(const String& name) const std::pair<ConfigTypeIterator<ConfigObject>, ConfigTypeIterator<ConfigObject> > ConfigType::GetObjects(void)
{ {
ObjectLock olock(this); Type::Ptr type = dynamic_cast<Type *>(this);
ConfigType::ObjectMap::const_iterator nt = m_ObjectMap.find(name); return std::make_pair(
ConfigTypeIterator<ConfigObject>(type, 0),
if (nt == m_ObjectMap.end()) ConfigTypeIterator<ConfigObject>(type, UINT_MAX)
return ConfigObject::Ptr(); );
return nt->second;
} }
boost::mutex& ConfigType::GetStaticMutex(void)
{
static boost::mutex mutex;
return mutex;
}

View File

@ -17,44 +17,38 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/ ******************************************************************************/
#ifndef DYNAMICTYPE_H #ifndef CONFIGTYPE_H
#define DYNAMICTYPE_H #define CONFIGTYPE_H
#include "base/i2-base.hpp" #include "base/i2-base.hpp"
#include "base/configobject.hpp" #include "base/object.hpp"
#include "base/objectlock.hpp" #include "base/type.hpp"
#include <map> #include "base/dictionary.hpp"
# include <boost/iterator/iterator_facade.hpp>
namespace icinga namespace icinga
{ {
class ConfigObject;
template<typename T> template<typename T>
class ConfigTypeIterator; class ConfigTypeIterator;
class I2_BASE_API ConfigType : public Object class I2_BASE_API ConfigType
{ {
public: public:
DECLARE_PTR_TYPEDEFS(ConfigType); virtual ~ConfigType(void);
ConfigType(const String& name); intrusive_ptr<ConfigObject> GetObject(const String& name) const;
String GetName(void) const; void RegisterObject(const intrusive_ptr<ConfigObject>& object);
void UnregisterObject(const intrusive_ptr<ConfigObject>& object);
static ConfigType::Ptr GetByName(const String& name);
ConfigObject::Ptr GetObject(const String& name) const;
void RegisterObject(const ConfigObject::Ptr& object);
void UnregisterObject(const ConfigObject::Ptr& object);
static std::vector<ConfigType::Ptr> GetTypes(void);
std::pair<ConfigTypeIterator<ConfigObject>, ConfigTypeIterator<ConfigObject> > GetObjects(void); std::pair<ConfigTypeIterator<ConfigObject>, ConfigTypeIterator<ConfigObject> > GetObjects(void);
template<typename T> template<typename T>
static std::pair<ConfigTypeIterator<T>, ConfigTypeIterator<T> > GetObjectsByType(void) static std::pair<ConfigTypeIterator<T>, ConfigTypeIterator<T> > GetObjectsByType(void)
{ {
ConfigType::Ptr type = GetByName(T::GetTypeName()); Type::Ptr type = T::TypeInstance;
return std::make_pair( return std::make_pair(
ConfigTypeIterator<T>(type, 0), ConfigTypeIterator<T>(type, 0),
ConfigTypeIterator<T>(type, UINT_MAX) ConfigTypeIterator<T>(type, UINT_MAX)
@ -64,34 +58,29 @@ public:
private: private:
template<typename T> friend class ConfigTypeIterator; template<typename T> friend class ConfigTypeIterator;
String m_Name; typedef std::map<String, intrusive_ptr<ConfigObject> > ObjectMap;
typedef std::vector<intrusive_ptr<ConfigObject> > ObjectVector;
typedef std::map<String, ConfigObject::Ptr> ObjectMap;
typedef std::vector<ConfigObject::Ptr> ObjectVector;
mutable boost::mutex m_Mutex;
ObjectMap m_ObjectMap; ObjectMap m_ObjectMap;
ObjectVector m_ObjectVector; ObjectVector m_ObjectVector;
typedef std::map<String, ConfigType::Ptr> TypeMap;
typedef std::vector<ConfigType::Ptr> TypeVector;
static TypeMap& InternalGetTypeMap(void);
static TypeVector& InternalGetTypeVector(void);
static boost::mutex& GetStaticMutex(void);
}; };
template<typename T> template<typename T>
class ConfigTypeIterator : public boost::iterator_facade<ConfigTypeIterator<T>, const intrusive_ptr<T>, boost::forward_traversal_tag> class ConfigTypeIterator : public boost::iterator_facade<ConfigTypeIterator<T>, const intrusive_ptr<T>, boost::forward_traversal_tag>
{ {
public: public:
ConfigTypeIterator(const ConfigType::Ptr& type, int index) ConfigTypeIterator(const Type::Ptr& type, int index)
: m_Type(type), m_Index(index) : m_Type(type), m_ConfigType(dynamic_cast<ConfigType *>(type.get())), m_Index(index)
{ } {
ASSERT(m_ConfigType);
}
private: private:
friend class boost::iterator_core_access; friend class boost::iterator_core_access;
ConfigType::Ptr m_Type; Type::Ptr m_Type;
ConfigType *m_ConfigType;
ConfigType::ObjectVector::size_type m_Index; ConfigType::ObjectVector::size_type m_Index;
mutable intrusive_ptr<T> m_Current; mutable intrusive_ptr<T> m_Current;
@ -115,10 +104,10 @@ private:
ASSERT(other.m_Type == m_Type); ASSERT(other.m_Type == m_Type);
{ {
ObjectLock olock(m_Type); boost::mutex::scoped_lock lock(m_ConfigType->m_Mutex);
if ((other.m_Index == UINT_MAX || other.m_Index >= other.m_Type->m_ObjectVector.size()) && if ((other.m_Index == UINT_MAX || other.m_Index >= other.m_ConfigType->m_ObjectVector.size()) &&
(m_Index == UINT_MAX || m_Index >= m_Type->m_ObjectVector.size())) (m_Index == UINT_MAX || m_Index >= m_ConfigType->m_ObjectVector.size()))
return true; return true;
} }
@ -127,12 +116,11 @@ private:
const intrusive_ptr<T>& dereference(void) const const intrusive_ptr<T>& dereference(void) const
{ {
ObjectLock olock(m_Type); boost::mutex::scoped_lock lock(m_ConfigType->m_Mutex);
m_Current = static_pointer_cast<T>(*(m_Type->m_ObjectVector.begin() + m_Index)); m_Current = static_pointer_cast<T>(*(m_ConfigType->m_ObjectVector.begin() + m_Index));
return m_Current; return m_Current;
} }
}; };
} }
#endif /* DYNAMICTYPE_H */ #endif /* CONFIGTYPE_H */

View File

@ -262,31 +262,34 @@ Array::Ptr ScriptUtils::Keys(const Dictionary::Ptr& dict)
ConfigObject::Ptr ScriptUtils::GetObject(const Value& vtype, const String& name) ConfigObject::Ptr ScriptUtils::GetObject(const Value& vtype, const String& name)
{ {
String typeName; Type::Ptr ptype;
if (vtype.IsObjectType<Type>()) if (vtype.IsObjectType<Type>())
typeName = static_cast<Type::Ptr>(vtype)->GetName(); ptype = vtype;
else else
typeName = vtype; ptype = Type::GetByName(vtype);
ConfigType::Ptr dtype = ConfigType::GetByName(typeName); ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!dtype) if (!ctype)
return ConfigObject::Ptr(); return ConfigObject::Ptr();
return dtype->GetObject(name); return ctype->GetObject(name);
} }
Array::Ptr ScriptUtils::GetObjects(const Type::Ptr& type) Array::Ptr ScriptUtils::GetObjects(const Type::Ptr& type)
{ {
ConfigType::Ptr dtype = ConfigType::GetByName(type->GetName()); if (!type)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type: Must not be null"));
if (!dtype) ConfigType *ctype = dynamic_cast<ConfigType *>(type.get());
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type name"));
if (!ctype)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type: Type must inherit from 'ConfigObject'"));
Array::Ptr result = new Array(); Array::Ptr result = new Array();
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) BOOST_FOREACH(const ConfigObject::Ptr& object, ctype->GetObjects())
result->Add(object); result->Add(object);
return result; return result;

View File

@ -577,7 +577,7 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr
#ifdef I2_DEBUG #ifdef I2_DEBUG
Log(LogDebug, "ConfigItem") Log(LogDebug, "ConfigItem")
<< "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'"; << "Activating object '" << object->GetName() << "' of type '" << object->GetReflectionType()->GetName() << "'";
#endif /* I2_DEBUG */ #endif /* I2_DEBUG */
upq.Enqueue(boost::bind(&ConfigObject::Activate, object, runtimeCreated)); upq.Enqueue(boost::bind(&ConfigObject::Activate, object, runtimeCreated));
} }

View File

@ -93,7 +93,10 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), m_DebugInfo));
} }
if (!ConfigType::GetByName(m_Type)) { Type::Ptr ptype = Type::GetByName(m_Type);
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!ctype) {
std::ostringstream msgbuf; std::ostringstream msgbuf;
msgbuf << "The type '" + m_Type + "' is unknown"; msgbuf << "The type '" + m_Type + "' is unknown";
BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), m_DebugInfo));

View File

@ -54,7 +54,7 @@ void DbConnection::OnConfigLoaded(void)
SetCategoryFilter(categories); SetCategoryFilter(categories);
Log(LogWarning, "DbConnection") Log(LogWarning, "DbConnection")
<< "Specifying flags using '|' for 'categories' for object '" << GetName() << "Specifying flags using '|' for 'categories' for object '" << GetName()
<< "' of type '" << GetType()->GetName() << "'" << "' of type '" << GetReflectionType()->GetName() << "'"
<< " is deprecated. This functionality will be removed in 2.6.0. Please use an array."; << " is deprecated. This functionality will be removed in 2.6.0. Please use an array.";
} else } else
SetCategoryFilter(FilterArrayToInt(categories, DbQuery::GetCategoryFilterMap(), DbCatEverything)); SetCategoryFilter(FilterArrayToInt(categories, DbQuery::GetCategoryFilterMap(), DbCatEverything));
@ -466,9 +466,13 @@ void DbConnection::UpdateObject(const ConfigObject::Ptr& object)
void DbConnection::UpdateAllObjects(void) void DbConnection::UpdateAllObjects(void)
{ {
ConfigType::Ptr type; BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) {
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
UpdateObject(object); UpdateObject(object);
} }
} }

View File

@ -339,11 +339,11 @@ void DbEvents::AddCommentInternal(std::vector<DbQuery>& queries, const Comment::
fields1->Set("entry_type", comment->GetEntryType()); fields1->Set("entry_type", comment->GetEntryType());
fields1->Set("object_id", checkable); fields1->Set("object_id", checkable);
if (checkable->GetType() == ConfigType::GetByName("Host")) { if (checkable->GetReflectionType() == Host::TypeInstance) {
fields1->Set("comment_type", 2); fields1->Set("comment_type", 2);
/* requires idoutils 1.10 schema fix */ /* requires idoutils 1.10 schema fix */
fields1->Set("internal_comment_id", comment->GetLegacyId()); fields1->Set("internal_comment_id", comment->GetLegacyId());
} else if (checkable->GetType() == ConfigType::GetByName("Service")) { } else if (checkable->GetReflectionType() == Service::TypeInstance) {
fields1->Set("comment_type", 1); fields1->Set("comment_type", 1);
fields1->Set("internal_comment_id", comment->GetLegacyId()); fields1->Set("internal_comment_id", comment->GetLegacyId());
} else { } else {
@ -472,11 +472,11 @@ void DbEvents::AddDowntimeInternal(std::vector<DbQuery>& queries, const Downtime
fields1->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime())); fields1->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
fields1->Set("object_id", checkable); fields1->Set("object_id", checkable);
if (checkable->GetType() == ConfigType::GetByName("Host")) { if (checkable->GetReflectionType() == Host::TypeInstance) {
fields1->Set("downtime_type", 2); fields1->Set("downtime_type", 2);
/* requires idoutils 1.10 schema fix */ /* requires idoutils 1.10 schema fix */
fields1->Set("internal_downtime_id", downtime->GetLegacyId()); fields1->Set("internal_downtime_id", downtime->GetLegacyId());
} else if (checkable->GetType() == ConfigType::GetByName("Service")) { } else if (checkable->GetReflectionType() == Service::TypeInstance) {
fields1->Set("downtime_type", 1); fields1->Set("downtime_type", 1);
fields1->Set("internal_downtime_id", downtime->GetLegacyId()); fields1->Set("internal_downtime_id", downtime->GetLegacyId());
} else { } else {

View File

@ -84,7 +84,7 @@ void IdoCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult
return; return;
} }
ConfigType::Ptr dtype = ConfigType::GetByName(idoType); ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
VERIFY(dtype); VERIFY(dtype);
DbConnection::Ptr conn = static_pointer_cast<DbConnection>(dtype->GetObject(idoName)); DbConnection::Ptr conn = static_pointer_cast<DbConnection>(dtype->GetObject(idoName));

View File

@ -19,6 +19,7 @@
#include "icinga/checkable.hpp" #include "icinga/checkable.hpp"
#include "icinga/customvarobject.hpp" #include "icinga/customvarobject.hpp"
#impl_include "icinga/hostgroup.hpp"
library icinga; library icinga;

View File

@ -21,6 +21,7 @@
#include "icinga/host.hpp" #include "icinga/host.hpp"
#include "icinga/icingaapplication.hpp" #include "icinga/icingaapplication.hpp"
#include "icinga/customvarobject.hpp" #include "icinga/customvarobject.hpp"
#impl_include "icinga/servicegroup.hpp"
library icinga; library icinga;

View File

@ -19,6 +19,7 @@
#include "icinga/customvarobject.hpp" #include "icinga/customvarobject.hpp"
#include "base/array.hpp" #include "base/array.hpp"
#impl_include "icinga/usergroup.hpp"
library icinga; library icinga;

View File

@ -99,15 +99,16 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
/* update the object */ /* update the object */
double objVersion = params->Get("version"); double objVersion = params->Get("version");
ConfigType::Ptr dtype = ConfigType::GetByName(objType); Type::Ptr ptype = Type::GetByName(objType);
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!dtype) { if (!ctype) {
Log(LogCritical, "ApiListener") Log(LogCritical, "ApiListener")
<< "Config type '" << objType << "' does not exist."; << "Config type '" << objType << "' does not exist.";
return Empty; return Empty;
} }
ConfigObject::Ptr object = dtype->GetObject(objName); ConfigObject::Ptr object = ctype->GetObject(objName);
String config = params->Get("config"); String config = params->Get("config");
@ -115,7 +116,7 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
/* object does not exist, create it through the API */ /* object does not exist, create it through the API */
Array::Ptr errors = new Array(); Array::Ptr errors = new Array();
if (!ConfigObjectUtility::CreateObject(Type::GetByName(objType), if (!ConfigObjectUtility::CreateObject(ptype,
objName, config, errors)) { objName, config, errors)) {
Log(LogCritical, "ApiListener") Log(LogCritical, "ApiListener")
<< "Could not create object '" << objName << "':"; << "Could not create object '" << objName << "':";
@ -128,7 +129,7 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
return Empty; return Empty;
} }
object = dtype->GetObject(objName); object = ctype->GetObject(objName);
if (!object) if (!object)
return Empty; return Empty;
@ -230,15 +231,16 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
} }
/* delete the object */ /* delete the object */
ConfigType::Ptr dtype = ConfigType::GetByName(params->Get("type")); Type::Ptr ptype = Type::GetByName(params->Get("type"));
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!dtype) { if (!ctype) {
Log(LogCritical, "ApiListener") Log(LogCritical, "ApiListener")
<< "Config type '" << params->Get("type") << "' does not exist."; << "Config type '" << params->Get("type") << "' does not exist.";
return Empty; return Empty;
} }
ConfigObject::Ptr object = dtype->GetObject(params->Get("name")); ConfigObject::Ptr object = ctype->GetObject(params->Get("name"));
if (!object) { if (!object) {
Log(LogNotice, "ApiListener") Log(LogNotice, "ApiListener")
@ -397,8 +399,13 @@ void ApiListener::SendRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient
Log(LogInformation, "ApiListener") Log(LogInformation, "ApiListener")
<< "Syncing runtime objects to endpoint '" << endpoint->GetName() << "'."; << "Syncing runtime objects to endpoint '" << endpoint->GetName() << "'.";
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) { BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
/* don't sync objects with an older version time than the endpoint's log position */ /* don't sync objects with an older version time than the endpoint's log position */
if (object->GetVersion() < endpoint->GetLocalLogPosition()) if (object->GetVersion() < endpoint->GetLocalLogPosition())
continue; continue;

View File

@ -955,12 +955,7 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
Dictionary::Ptr secname = pmessage->Get("secobj"); Dictionary::Ptr secname = pmessage->Get("secobj");
if (secname) { if (secname) {
ConfigType::Ptr dtype = ConfigType::GetByName(secname->Get("type")); ConfigObject::Ptr secobj = ConfigObject::GetObject(secname->Get("type"), secname->Get("name"));
if (!dtype)
continue;
ConfigObject::Ptr secobj = dtype->GetObject(secname->Get("name"));
if (!secobj) if (!secobj)
continue; continue;

View File

@ -63,8 +63,13 @@ void ApiListener::UpdateObjectAuthority(void)
std::sort(endpoints.begin(), endpoints.end(), ObjectNameLessComparer); std::sort(endpoints.begin(), endpoints.end(), ObjectNameLessComparer);
} }
BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) { BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) { ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
if (object->GetHAMode() != HARunOnce) if (object->GetHAMode() != HARunOnce)
continue; continue;

View File

@ -95,9 +95,8 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
return true; return true;
} }
ConfigType::Ptr dtype = ConfigType::GetByName(type->GetName()); ConfigType *ctype = dynamic_cast<ConfigType *>(type.get());
ConfigObject::Ptr obj = ctype->GetObject(name);
ConfigObject::Ptr obj = dtype->GetObject(name);
result1->Set("code", 200); result1->Set("code", 200);

View File

@ -47,10 +47,11 @@ Type::Ptr FilterUtility::TypeFromPluralName(const String& pluralName)
void ConfigObjectTargetProvider::FindTargets(const String& type, const boost::function<void (const Value&)>& addTarget) const void ConfigObjectTargetProvider::FindTargets(const String& type, const boost::function<void (const Value&)>& addTarget) const
{ {
ConfigType::Ptr dtype = ConfigType::GetByName(type); Type::Ptr ptype = Type::GetByName(type);
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (dtype) { if (ctype) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) { BOOST_FOREACH(const ConfigObject::Ptr& object, ctype->GetObjects()) {
addTarget(object); addTarget(object);
} }
} }

View File

@ -197,7 +197,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re
continue; continue;
Dictionary::Ptr refInfo = new Dictionary(); Dictionary::Ptr refInfo = new Dictionary();
refInfo->Set("type", configObj->GetType()->GetName()); refInfo->Set("type", configObj->GetReflectionType()->GetName());
refInfo->Set("name", configObj->GetName()); refInfo->Set("name", configObj->GetName());
used_by->Add(refInfo); used_by->Add(refInfo);
} }

View File

@ -242,12 +242,16 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
<< "class " << apiMacro << "TypeImpl<" << klass.Name << ">" << "class " << apiMacro << "TypeImpl<" << klass.Name << ">"
<< " : public Type"; << " : public Type";
if (!klass.Parent.empty())
m_Header << "Impl<" << klass.Parent << ">";
if (!klass.TypeBase.empty()) if (!klass.TypeBase.empty())
m_Header << ", public " + klass.TypeBase; m_Header << ", public " + klass.TypeBase;
m_Header << std::endl m_Header << std::endl
<< "{" << std::endl << "{" << std::endl
<< "public:" << std::endl; << "public:" << std::endl
<< "\t" << "DECLARE_PTR_TYPEDEFS(TypeImpl<" << klass.Name << ">);" << std::endl << std::endl;
m_Impl << "template class TypeImpl<" << klass.Name << ">;" << std::endl << std::endl; m_Impl << "template class TypeImpl<" << klass.Name << ">;" << std::endl << std::endl;
@ -525,7 +529,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
m_Impl << "\t" << "if (avalue.IsObjectType<Function>()) {" << std::endl m_Impl << "\t" << "if (avalue.IsObjectType<Function>()) {" << std::endl
<< "\t\t" << "Function::Ptr func = avalue;" << std::endl << "\t\t" << "Function::Ptr func = avalue;" << std::endl
<< "\t\t" << "if (func->IsDeprecated())" << std::endl << "\t\t" << "if (func->IsDeprecated())" << std::endl
<< "\t\t\t" << "Log(LogWarning, \"" << klass.Name << "\") << \"Attribute '" << field.Name << "' for object '\" << dynamic_cast<ConfigObject *>(this)->GetName() << \"' of type '\" << dynamic_cast<ConfigObject *>(this)->GetType()->GetName() << \"' is set to a deprecated function: \" << func->GetName();" << std::endl << "\t\t\t" << "Log(LogWarning, \"" << klass.Name << "\") << \"Attribute '" << field.Name << "' for object '\" << dynamic_cast<ConfigObject *>(this)->GetName() << \"' of type '\" << dynamic_cast<ConfigObject *>(this)->GetReflectionType()->GetName() << \"' is set to a deprecated function: \" << func->GetName();" << std::endl
<< "\t" << "}" << std::endl << std::endl; << "\t" << "}" << std::endl << std::endl;
std::string ftype = FieldTypeToIcingaName(field, true); std::string ftype = FieldTypeToIcingaName(field, true);
@ -855,24 +859,58 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
if (!it->TrackAccessor.empty()) if (!it->TrackAccessor.empty())
m_Impl << "\t" << it->TrackAccessor << std::endl; m_Impl << "\t" << it->TrackAccessor << std::endl;
if (it->Type.ArrayRank > 0) { if (it->Type.TypeName != "String") {
m_Impl << "\t" << "if (oldValue) {" << std::endl if (it->Type.ArrayRank > 0) {
<< "\t\t" << "ObjectLock olock(oldValue);" << std::endl m_Impl << "\t" << "if (oldValue) {" << std::endl
<< "\t\t" << "BOOST_FOREACH(const String& ref, oldValue) {" << std::endl << "\t\t" << "ObjectLock olock(oldValue);" << std::endl
<< "\t\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", ref).get());" << std::endl << "\t\t" << "BOOST_FOREACH(const String& ref, oldValue) {" << std::endl
<< "\t\t" << "}" << std::endl << "\t\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject";
<< "\t" << "}" << std::endl
<< "\t" << "if (newValue) {" << std::endl /* Ew */
<< "\t\t" << "ObjectLock olock(newValue);" << std::endl if (it->Type.TypeName == "Zone" && m_Library == "base")
<< "\t\t" << "BOOST_FOREACH(const String& ref, newValue) {" << std::endl m_Impl << "(\"Zone\", ";
<< "\t\t\t" << "DependencyGraph::AddDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", ref).get());" << std::endl else
<< "\t\t" << "}" << std::endl m_Impl << "<" << it->Type.TypeName << ">(";
<< "\t" << "}" << std::endl;
} else { m_Impl << "ref).get());" << std::endl
m_Impl << "\t" << "if (!oldValue.IsEmpty())" << std::endl << "\t\t" << "}" << std::endl
<< "\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", oldValue).get());" << std::endl << "\t" << "}" << std::endl
<< "\t" << "if (!newValue.IsEmpty())" << std::endl << "\t" << "if (newValue) {" << std::endl
<< "\t\t" << "DependencyGraph::AddDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", newValue).get());" << std::endl; << "\t\t" << "ObjectLock olock(newValue);" << std::endl
<< "\t\t" << "BOOST_FOREACH(const String& ref, newValue) {" << std::endl
<< "\t\t\t" << "DependencyGraph::AddDependency(this, ConfigObject::GetObject";
/* Ew */
if (it->Type.TypeName == "Zone" && m_Library == "base")
m_Impl << "(\"Zone\", ";
else
m_Impl << "<" << it->Type.TypeName << ">(";
m_Impl << "ref).get());" << std::endl
<< "\t\t" << "}" << std::endl
<< "\t" << "}" << std::endl;
} else {
m_Impl << "\t" << "if (!oldValue.IsEmpty())" << std::endl
<< "\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject";
/* Ew */
if (it->Type.TypeName == "Zone" && m_Library == "base")
m_Impl << "(\"Zone\", ";
else
m_Impl << "<" << it->Type.TypeName << ">(";
m_Impl << "oldValue).get());" << std::endl
<< "\t" << "if (!newValue.IsEmpty())" << std::endl
<< "\t\t" << "DependencyGraph::AddDependency(this, ConfigObject::GetObject";
/* Ew */
if (it->Type.TypeName == "Zone" && m_Library == "base")
m_Impl << "(\"Zone\", ";
else
m_Impl << "<" << it->Type.TypeName << ">(";
m_Impl << "newValue).get());" << std::endl;
}
} }
m_Impl << "}" << std::endl << std::endl; m_Impl << "}" << std::endl << std::endl;