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)
{ }
ConfigType::Ptr ConfigObject::GetType(void) const
{
return ConfigType::GetByName(GetReflectionType()->GetName());
}
bool ConfigObject::IsActive(void) const
{
return GetActive();
@ -103,7 +98,8 @@ class ModAttrValidationUtils : public ValidationUtils
public:
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)
return false;
@ -361,16 +357,16 @@ void ConfigObject::Register(void)
{
ASSERT(!OwnsLock());
ConfigType::Ptr dtype = GetType();
dtype->RegisterObject(this);
TypeImpl<ConfigObject>::Ptr type = static_pointer_cast<TypeImpl<ConfigObject> >(GetReflectionType());
type->RegisterObject(this);
}
void ConfigObject::Unregister(void)
{
ASSERT(!OwnsLock());
ConfigType::Ptr dtype = GetType();
dtype->UnregisterObject(this);
TypeImpl<ConfigObject>::Ptr type = static_pointer_cast<TypeImpl<ConfigObject> >(GetReflectionType());
type->UnregisterObject(this);
}
void ConfigObject::Start(bool runtimeCreated)
@ -440,7 +436,17 @@ void ConfigObject::OnConfigLoaded(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)
@ -494,8 +500,13 @@ void ConfigObject::DumpObjects(const String& filename, int attributeTypes)
StdioStream::Ptr sfp = new StdioStream(&fp, false);
BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) {
BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
Dictionary::Ptr persistentObject = new Dictionary();
persistentObject->Set("type", type->GetName());
@ -535,15 +546,9 @@ void ConfigObject::RestoreObject(const String& message, int attributeTypes)
Dictionary::Ptr persistentObject = JsonDecode(message);
String type = persistentObject->Get("type");
ConfigType::Ptr dt = ConfigType::GetByName(type);
if (!dt)
return;
String name = persistentObject->Get("name");
ConfigObject::Ptr object = dt->GetObject(name);
ConfigObject::Ptr object = GetObject(type, name);
if (!object)
return;
@ -597,8 +602,13 @@ void ConfigObject::RestoreObjects(const String& filename, int attributeTypes)
unsigned long no_state = 0;
BOOST_FOREACH(const ConfigType::Ptr& type, ConfigType::GetTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, type->GetObjects()) {
BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
if (!object->GetStateLoaded()) {
object->OnStateLoaded();
object->SetStateLoaded(true);
@ -614,8 +624,13 @@ void ConfigObject::RestoreObjects(const String& filename, int attributeTypes)
void ConfigObject::StopObjects(void)
{
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) {
BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
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)
{
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) {
BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
Dictionary::Ptr originalAttributes = object->GetOriginalAttributes();
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)
{
ConfigType::Ptr dtype = ConfigType::GetByName(type);
if (!dtype)
Type::Ptr ptype = Type::GetByName(type);
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!ctype)
return ConfigObject::Ptr();
return dtype->GetObject(name);
return ctype->GetObject(name);
}
ConfigObject::Ptr ConfigObject::GetZone(void) const

View File

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

View File

@ -17,75 +17,25 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#include "base/configtype.hpp"
#include "base/serializer.hpp"
#include "base/debug.hpp"
#include "base/objectlock.hpp"
#include "base/configobject.hpp"
#include "base/convert.hpp"
#include "base/exception.hpp"
using namespace icinga;
ConfigType::ConfigType(const String& name)
: m_Name(name)
ConfigType::~ConfigType(void)
{ }
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()) {
Type::Ptr type = Type::GetByName(name);
if (nt == m_ObjectMap.end())
return ConfigObject::Ptr();
if (!type || !ConfigObject::TypeInstance->IsAssignableFrom(type)
|| 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;
return nt->second;
}
void ConfigType::RegisterObject(const ConfigObject::Ptr& object)
@ -93,7 +43,7 @@ void ConfigType::RegisterObject(const ConfigObject::Ptr& object)
String name = object->GetName();
{
ObjectLock olock(this);
boost::mutex::scoped_lock lock(m_Mutex);
ObjectMap::iterator it = m_ObjectMap.find(name);
@ -101,7 +51,9 @@ void ConfigType::RegisterObject(const ConfigObject::Ptr& object)
if (it->second == object)
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()),
object->GetDebugInfo()));
}
@ -116,28 +68,19 @@ void ConfigType::UnregisterObject(const ConfigObject::Ptr& object)
String name = object->GetName();
{
ObjectLock olock(this);
boost::mutex::scoped_lock lock(m_Mutex);
m_ObjectMap.erase(name);
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);
if (nt == m_ObjectMap.end())
return ConfigObject::Ptr();
return nt->second;
return std::make_pair(
ConfigTypeIterator<ConfigObject>(type, 0),
ConfigTypeIterator<ConfigObject>(type, UINT_MAX)
);
}
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. *
******************************************************************************/
#ifndef DYNAMICTYPE_H
#define DYNAMICTYPE_H
#ifndef CONFIGTYPE_H
#define CONFIGTYPE_H
#include "base/i2-base.hpp"
#include "base/configobject.hpp"
#include "base/objectlock.hpp"
#include <map>
# include <boost/iterator/iterator_facade.hpp>
#include "base/object.hpp"
#include "base/type.hpp"
#include "base/dictionary.hpp"
namespace icinga
{
class ConfigObject;
template<typename T>
class ConfigTypeIterator;
class I2_BASE_API ConfigType : public Object
class I2_BASE_API ConfigType
{
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);
template<typename T>
static std::pair<ConfigTypeIterator<T>, ConfigTypeIterator<T> > GetObjectsByType(void)
{
ConfigType::Ptr type = GetByName(T::GetTypeName());
Type::Ptr type = T::TypeInstance;
return std::make_pair(
ConfigTypeIterator<T>(type, 0),
ConfigTypeIterator<T>(type, UINT_MAX)
@ -64,34 +58,29 @@ public:
private:
template<typename T> friend class ConfigTypeIterator;
String m_Name;
typedef std::map<String, ConfigObject::Ptr> ObjectMap;
typedef std::vector<ConfigObject::Ptr> ObjectVector;
typedef std::map<String, intrusive_ptr<ConfigObject> > ObjectMap;
typedef std::vector<intrusive_ptr<ConfigObject> > ObjectVector;
mutable boost::mutex m_Mutex;
ObjectMap m_ObjectMap;
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>
class ConfigTypeIterator : public boost::iterator_facade<ConfigTypeIterator<T>, const intrusive_ptr<T>, boost::forward_traversal_tag>
{
public:
ConfigTypeIterator(const ConfigType::Ptr& type, int index)
: m_Type(type), m_Index(index)
{ }
ConfigTypeIterator(const Type::Ptr& type, int index)
: m_Type(type), m_ConfigType(dynamic_cast<ConfigType *>(type.get())), m_Index(index)
{
ASSERT(m_ConfigType);
}
private:
friend class boost::iterator_core_access;
ConfigType::Ptr m_Type;
Type::Ptr m_Type;
ConfigType *m_ConfigType;
ConfigType::ObjectVector::size_type m_Index;
mutable intrusive_ptr<T> m_Current;
@ -115,10 +104,10 @@ private:
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()) &&
(m_Index == UINT_MAX || m_Index >= 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_ConfigType->m_ObjectVector.size()))
return true;
}
@ -127,12 +116,11 @@ private:
const intrusive_ptr<T>& dereference(void) const
{
ObjectLock olock(m_Type);
m_Current = static_pointer_cast<T>(*(m_Type->m_ObjectVector.begin() + m_Index));
boost::mutex::scoped_lock lock(m_ConfigType->m_Mutex);
m_Current = static_pointer_cast<T>(*(m_ConfigType->m_ObjectVector.begin() + m_Index));
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)
{
String typeName;
Type::Ptr ptype;
if (vtype.IsObjectType<Type>())
typeName = static_cast<Type::Ptr>(vtype)->GetName();
ptype = vtype;
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 dtype->GetObject(name);
return ctype->GetObject(name);
}
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)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type name"));
ConfigType *ctype = dynamic_cast<ConfigType *>(type.get());
if (!ctype)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type: Type must inherit from 'ConfigObject'"));
Array::Ptr result = new Array();
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects())
BOOST_FOREACH(const ConfigObject::Ptr& object, ctype->GetObjects())
result->Add(object);
return result;

View File

@ -577,7 +577,7 @@ bool ConfigItem::ActivateItems(WorkQueue& upq, const std::vector<ConfigItem::Ptr
#ifdef I2_DEBUG
Log(LogDebug, "ConfigItem")
<< "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'";
<< "Activating object '" << object->GetName() << "' of type '" << object->GetReflectionType()->GetName() << "'";
#endif /* I2_DEBUG */
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));
}
if (!ConfigType::GetByName(m_Type)) {
Type::Ptr ptype = Type::GetByName(m_Type);
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (!ctype) {
std::ostringstream msgbuf;
msgbuf << "The type '" + m_Type + "' is unknown";
BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), m_DebugInfo));

View File

@ -54,7 +54,7 @@ void DbConnection::OnConfigLoaded(void)
SetCategoryFilter(categories);
Log(LogWarning, "DbConnection")
<< "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.";
} else
SetCategoryFilter(FilterArrayToInt(categories, DbQuery::GetCategoryFilterMap(), DbCatEverything));
@ -466,9 +466,13 @@ void DbConnection::UpdateObject(const ConfigObject::Ptr& object)
void DbConnection::UpdateAllObjects(void)
{
ConfigType::Ptr type;
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) {
BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
ConfigType *dtype = dynamic_cast<ConfigType *>(type.get());
if (!dtype)
continue;
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
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("object_id", checkable);
if (checkable->GetType() == ConfigType::GetByName("Host")) {
if (checkable->GetReflectionType() == Host::TypeInstance) {
fields1->Set("comment_type", 2);
/* requires idoutils 1.10 schema fix */
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("internal_comment_id", comment->GetLegacyId());
} else {
@ -472,11 +472,11 @@ void DbEvents::AddDowntimeInternal(std::vector<DbQuery>& queries, const Downtime
fields1->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
fields1->Set("object_id", checkable);
if (checkable->GetType() == ConfigType::GetByName("Host")) {
if (checkable->GetReflectionType() == Host::TypeInstance) {
fields1->Set("downtime_type", 2);
/* requires idoutils 1.10 schema fix */
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("internal_downtime_id", downtime->GetLegacyId());
} else {

View File

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

View File

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

View File

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

View File

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

View File

@ -99,15 +99,16 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
/* update the object */
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")
<< "Config type '" << objType << "' does not exist.";
return Empty;
}
ConfigObject::Ptr object = dtype->GetObject(objName);
ConfigObject::Ptr object = ctype->GetObject(objName);
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 */
Array::Ptr errors = new Array();
if (!ConfigObjectUtility::CreateObject(Type::GetByName(objType),
if (!ConfigObjectUtility::CreateObject(ptype,
objName, config, errors)) {
Log(LogCritical, "ApiListener")
<< "Could not create object '" << objName << "':";
@ -128,7 +129,7 @@ Value ApiListener::ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin
return Empty;
}
object = dtype->GetObject(objName);
object = ctype->GetObject(objName);
if (!object)
return Empty;
@ -230,15 +231,16 @@ Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin
}
/* 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")
<< "Config type '" << params->Get("type") << "' does not exist.";
return Empty;
}
ConfigObject::Ptr object = dtype->GetObject(params->Get("name"));
ConfigObject::Ptr object = ctype->GetObject(params->Get("name"));
if (!object) {
Log(LogNotice, "ApiListener")
@ -397,8 +399,13 @@ void ApiListener::SendRuntimeConfigObjects(const JsonRpcConnection::Ptr& aclient
Log(LogInformation, "ApiListener")
<< "Syncing runtime objects to endpoint '" << endpoint->GetName() << "'.";
BOOST_FOREACH(const ConfigType::Ptr& dt, ConfigType::GetTypes()) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dt->GetObjects()) {
BOOST_FOREACH(const Type::Ptr& type, Type::GetAllTypes()) {
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 */
if (object->GetVersion() < endpoint->GetLocalLogPosition())
continue;

View File

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

View File

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

View File

@ -95,9 +95,8 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
return true;
}
ConfigType::Ptr dtype = ConfigType::GetByName(type->GetName());
ConfigObject::Ptr obj = dtype->GetObject(name);
ConfigType *ctype = dynamic_cast<ConfigType *>(type.get());
ConfigObject::Ptr obj = ctype->GetObject(name);
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
{
ConfigType::Ptr dtype = ConfigType::GetByName(type);
Type::Ptr ptype = Type::GetByName(type);
ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());
if (dtype) {
BOOST_FOREACH(const ConfigObject::Ptr& object, dtype->GetObjects()) {
if (ctype) {
BOOST_FOREACH(const ConfigObject::Ptr& object, ctype->GetObjects()) {
addTarget(object);
}
}

View File

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

View File

@ -242,12 +242,16 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
<< "class " << apiMacro << "TypeImpl<" << klass.Name << ">"
<< " : public Type";
if (!klass.Parent.empty())
m_Header << "Impl<" << klass.Parent << ">";
if (!klass.TypeBase.empty())
m_Header << ", public " + klass.TypeBase;
m_Header << 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;
@ -525,7 +529,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
m_Impl << "\t" << "if (avalue.IsObjectType<Function>()) {" << std::endl
<< "\t\t" << "Function::Ptr func = avalue;" << 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;
std::string ftype = FieldTypeToIcingaName(field, true);
@ -855,24 +859,58 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
if (!it->TrackAccessor.empty())
m_Impl << "\t" << it->TrackAccessor << std::endl;
if (it->Type.TypeName != "String") {
if (it->Type.ArrayRank > 0) {
m_Impl << "\t" << "if (oldValue) {" << std::endl
<< "\t\t" << "ObjectLock olock(oldValue);" << std::endl
<< "\t\t" << "BOOST_FOREACH(const String& ref, oldValue) {" << std::endl
<< "\t\t\t" << "DependencyGraph::RemoveDependency(this, ConfigObject::GetObject(\"" << it->Type.TypeName << "\", ref).get());" << std::endl
<< "\t\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 << "ref).get());" << std::endl
<< "\t\t" << "}" << std::endl
<< "\t" << "}" << std::endl
<< "\t" << "if (newValue) {" << 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(\"" << it->Type.TypeName << "\", ref).get());" << 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(\"" << it->Type.TypeName << "\", oldValue).get());" << 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(\"" << it->Type.TypeName << "\", newValue).get());" << 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;