Avoid unnecessary string copies

fixes #12509
This commit is contained in:
Gunnar Beutner 2016-08-20 23:46:44 +02:00 committed by Michael Friedrich
parent 43a4acd5a2
commit 218e780a44
13 changed files with 79 additions and 61 deletions

View File

@ -110,8 +110,19 @@ StreamReadStatus NetString::ReadStringFromStream(const Stream::Ptr& stream, Stri
void NetString::WriteStringToStream(const Stream::Ptr& stream, const String& str) void NetString::WriteStringToStream(const Stream::Ptr& stream, const String& str)
{ {
std::ostringstream msgbuf; std::ostringstream msgbuf;
msgbuf << str.GetLength() << ":" << str << ","; WriteStringToStream(msgbuf, str);
String msg = msgbuf.str(); String msg = msgbuf.str();
stream->Write(msg.CStr(), msg.GetLength()); stream->Write(msg.CStr(), msg.GetLength());
} }
/**
* Writes data into a stream using the netstring format.
*
* @param stream The stream.
* @param str The String that is to be written.
*/
void NetString::WriteStringToStream(std::ostream& stream, const String& str)
{
stream << str.GetLength() << ":" << str << ",";
}

View File

@ -40,6 +40,7 @@ class I2_BASE_API NetString
public: public:
static StreamReadStatus ReadStringFromStream(const Stream::Ptr& stream, String *message, StreamReadContext& context, bool may_wait = false); static StreamReadStatus ReadStringFromStream(const Stream::Ptr& stream, String *message, StreamReadContext& context, bool may_wait = false);
static void WriteStringToStream(const Stream::Ptr& stream, const String& message); static void WriteStringToStream(const Stream::Ptr& stream, const String& message);
static void WriteStringToStream(std::ostream& stream, const String& message);
private: private:
NetString(void); NetString(void);

View File

@ -327,7 +327,7 @@ private:
inline std::ostream& operator<<(std::ostream& stream, const String& str) inline std::ostream& operator<<(std::ostream& stream, const String& str)
{ {
stream << static_cast<std::string>(str); stream << str.GetData();
return stream; return stream;
} }
@ -341,102 +341,102 @@ inline std::istream& operator>>(std::istream& stream, String& str)
inline String operator+(const String& lhs, const String& rhs) inline String operator+(const String& lhs, const String& rhs)
{ {
return static_cast<std::string>(lhs)+static_cast<std::string>(rhs); return lhs.GetData() + rhs.GetData();
} }
inline String operator+(const String& lhs, const char *rhs) inline String operator+(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs)+rhs; return lhs.GetData() + rhs;
} }
inline String operator+(const char *lhs, const String& rhs) inline String operator+(const char *lhs, const String& rhs)
{ {
return lhs + static_cast<std::string>(rhs); return lhs + rhs.GetData();
} }
inline bool operator==(const String& lhs, const String& rhs) inline bool operator==(const String& lhs, const String& rhs)
{ {
return static_cast<std::string>(lhs) == static_cast<std::string>(rhs); return lhs.GetData() == rhs.GetData();
} }
inline bool operator==(const String& lhs, const char *rhs) inline bool operator==(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs) == rhs; return lhs.GetData() == rhs;
} }
inline bool operator==(const char *lhs, const String& rhs) inline bool operator==(const char *lhs, const String& rhs)
{ {
return lhs == static_cast<std::string>(rhs); return lhs == rhs.GetData();
} }
inline bool operator<(const String& lhs, const char *rhs) inline bool operator<(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs) < rhs; return lhs.GetData() < rhs;
} }
inline bool operator<(const char *lhs, const String& rhs) inline bool operator<(const char *lhs, const String& rhs)
{ {
return lhs < static_cast<std::string>(rhs); return lhs < rhs.GetData();
} }
inline bool operator>(const String& lhs, const String& rhs) inline bool operator>(const String& lhs, const String& rhs)
{ {
return static_cast<std::string>(lhs) > static_cast<std::string>(rhs); return lhs.GetData() > rhs.GetData();
} }
inline bool operator>(const String& lhs, const char *rhs) inline bool operator>(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs) > rhs; return lhs.GetData() > rhs;
} }
inline bool operator>(const char *lhs, const String& rhs) inline bool operator>(const char *lhs, const String& rhs)
{ {
return lhs > static_cast<std::string>(rhs); return lhs > rhs.GetData();
} }
inline bool operator<=(const String& lhs, const String& rhs) inline bool operator<=(const String& lhs, const String& rhs)
{ {
return static_cast<std::string>(lhs) <= static_cast<std::string>(rhs); return lhs.GetData() <= rhs.GetData();
} }
inline bool operator<=(const String& lhs, const char *rhs) inline bool operator<=(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs) <= rhs; return lhs.GetData() <= rhs;
} }
inline bool operator<=(const char *lhs, const String& rhs) inline bool operator<=(const char *lhs, const String& rhs)
{ {
return lhs <= static_cast<std::string>(rhs); return lhs <= rhs.GetData();
} }
inline bool operator>=(const String& lhs, const String& rhs) inline bool operator>=(const String& lhs, const String& rhs)
{ {
return static_cast<std::string>(lhs) >= static_cast<std::string>(rhs); return lhs.GetData() >= rhs.GetData();
} }
inline bool operator>=(const String& lhs, const char *rhs) inline bool operator>=(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs) >= rhs; return lhs.GetData() >= rhs;
} }
inline bool operator>=(const char *lhs, const String& rhs) inline bool operator>=(const char *lhs, const String& rhs)
{ {
return lhs >= static_cast<std::string>(rhs); return lhs >= rhs.GetData();
} }
inline bool operator!=(const String& lhs, const String& rhs) inline bool operator!=(const String& lhs, const String& rhs)
{ {
return static_cast<std::string>(lhs) != static_cast<std::string>(rhs); return lhs.GetData() != rhs.GetData();
} }
inline bool operator!=(const String& lhs, const char *rhs) inline bool operator!=(const String& lhs, const char *rhs)
{ {
return static_cast<std::string>(lhs) != rhs; return lhs.GetData() != rhs;
} }
inline bool operator!=(const char *lhs, const String& rhs) inline bool operator!=(const char *lhs, const String& rhs)
{ {
return lhs != static_cast<std::string>(rhs); return lhs != rhs.GetData();
} }
inline String::Iterator range_begin(String& x) inline String::Iterator range_begin(String& x)

View File

@ -23,7 +23,6 @@
#include "base/netstring.hpp" #include "base/netstring.hpp"
#include "base/exception.hpp" #include "base/exception.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <fstream>
using namespace icinga; using namespace icinga;
@ -32,6 +31,10 @@ ConfigCompilerContext *ConfigCompilerContext::GetInstance(void)
return Singleton<ConfigCompilerContext>::GetInstance(); return Singleton<ConfigCompilerContext>::GetInstance();
} }
ConfigCompilerContext::ConfigCompilerContext(void)
: m_ObjectsFP(NULL)
{ }
void ConfigCompilerContext::OpenObjectsFile(const String& filename) void ConfigCompilerContext::OpenObjectsFile(const String& filename)
{ {
m_ObjectsPath = filename; m_ObjectsPath = filename;
@ -42,7 +45,7 @@ void ConfigCompilerContext::OpenObjectsFile(const String& filename)
if (!*fp) if (!*fp)
BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + m_ObjectsTempFile + "' file")); BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + m_ObjectsTempFile + "' file"));
m_ObjectsFP = new StdioStream(fp, true); m_ObjectsFP = fp;
} }
void ConfigCompilerContext::WriteObject(const Dictionary::Ptr& object) void ConfigCompilerContext::WriteObject(const Dictionary::Ptr& object)
@ -54,14 +57,14 @@ void ConfigCompilerContext::WriteObject(const Dictionary::Ptr& object)
{ {
boost::mutex::scoped_lock lock(m_Mutex); boost::mutex::scoped_lock lock(m_Mutex);
NetString::WriteStringToStream(m_ObjectsFP, json); NetString::WriteStringToStream(*m_ObjectsFP, json);
} }
} }
void ConfigCompilerContext::CancelObjectsFile(void) void ConfigCompilerContext::CancelObjectsFile(void)
{ {
m_ObjectsFP->Close(); delete m_ObjectsFP;
m_ObjectsFP.reset(); m_ObjectsFP = NULL;
#ifdef _WIN32 #ifdef _WIN32
_unlink(m_ObjectsTempFile.CStr()); _unlink(m_ObjectsTempFile.CStr());
@ -72,8 +75,8 @@ void ConfigCompilerContext::CancelObjectsFile(void)
void ConfigCompilerContext::FinishObjectsFile(void) void ConfigCompilerContext::FinishObjectsFile(void)
{ {
m_ObjectsFP->Close(); delete m_ObjectsFP;
m_ObjectsFP.reset(); m_ObjectsFP = NULL;
#ifdef _WIN32 #ifdef _WIN32
_unlink(m_ObjectsPath.CStr()); _unlink(m_ObjectsPath.CStr());

View File

@ -21,9 +21,9 @@
#define CONFIGCOMPILERCONTEXT_H #define CONFIGCOMPILERCONTEXT_H
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "base/stdiostream.hpp"
#include "base/dictionary.hpp" #include "base/dictionary.hpp"
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <fstream>
namespace icinga namespace icinga
{ {
@ -34,6 +34,8 @@ namespace icinga
class I2_CONFIG_API ConfigCompilerContext class I2_CONFIG_API ConfigCompilerContext
{ {
public: public:
ConfigCompilerContext(void);
void OpenObjectsFile(const String& filename); void OpenObjectsFile(const String& filename);
void WriteObject(const Dictionary::Ptr& object); void WriteObject(const Dictionary::Ptr& object);
void CancelObjectsFile(void); void CancelObjectsFile(void);
@ -44,7 +46,7 @@ public:
private: private:
String m_ObjectsPath; String m_ObjectsPath;
String m_ObjectsTempFile; String m_ObjectsTempFile;
StdioStream::Ptr m_ObjectsFP; std::fstream *m_ObjectsFP;
mutable boost::mutex m_Mutex; mutable boost::mutex m_Mutex;
}; };

View File

@ -48,8 +48,10 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
DebugInfo di = rule.GetDebugInfo(); DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "Dependency") Log(LogDebug, "Dependency")
<< "Applying dependency '" << name << "' to object '" << checkable->GetName() << "' for rule " << di; << "Applying dependency '" << name << "' to object '" << checkable->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
builder->SetType("Dependency"); builder->SetType("Dependency");
@ -123,10 +125,9 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
Array::Ptr arrclone = arr->ShallowClone();
ObjectLock olock(arrclone); ObjectLock olock(arr);
BOOST_FOREACH(const Value& instance, arrclone) { BOOST_FOREACH(const Value& instance, arr) {
String name = rule.GetName(); String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) { if (!rule.GetFKVar().IsEmpty()) {

View File

@ -87,16 +87,11 @@ void Dependency::OnAllConfigLoaded(void)
Host::Ptr childHost = Host::GetByName(GetChildHostName()); Host::Ptr childHost = Host::GetByName(GetChildHostName());
if (childHost) { if (childHost) {
if (GetChildServiceName().IsEmpty()) { if (GetChildServiceName().IsEmpty())
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' child host '" << GetChildHostName() << ".";
m_Child = childHost; m_Child = childHost;
} else { else
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' child host '" << GetChildHostName() << "' service '" << GetChildServiceName() << "' .";
m_Child = childHost->GetServiceByShortName(GetChildServiceName()); m_Child = childHost->GetServiceByShortName(GetChildServiceName());
} }
}
if (!m_Child) if (!m_Child)
BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a child host/service which doesn't exist.", GetDebugInfo())); BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a child host/service which doesn't exist.", GetDebugInfo()));
@ -106,16 +101,11 @@ void Dependency::OnAllConfigLoaded(void)
Host::Ptr parentHost = Host::GetByName(GetParentHostName()); Host::Ptr parentHost = Host::GetByName(GetParentHostName());
if (parentHost) { if (parentHost) {
if (GetParentServiceName().IsEmpty()) { if (GetParentServiceName().IsEmpty())
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' parent host '" << GetParentHostName() << ".";
m_Parent = parentHost; m_Parent = parentHost;
} else { else
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' parent host '" << GetParentHostName() << "' service '" << GetParentServiceName() << "' .";
m_Parent = parentHost->GetServiceByShortName(GetParentServiceName()); m_Parent = parentHost->GetServiceByShortName(GetParentServiceName());
} }
}
if (!m_Parent) if (!m_Parent)
BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a parent host/service which doesn't exist.", GetDebugInfo())); BOOST_THROW_EXCEPTION(ScriptError("Dependency '" + GetName() + "' references a parent host/service which doesn't exist.", GetDebugInfo()));

View File

@ -67,16 +67,16 @@ void Host::OnAllConfigLoaded(void)
void Host::CreateChildObjects(const Type::Ptr& childType) void Host::CreateChildObjects(const Type::Ptr& childType)
{ {
if (childType->GetName() == "ScheduledDowntime") if (childType == ScheduledDowntime::TypeInstance)
ScheduledDowntime::EvaluateApplyRules(this); ScheduledDowntime::EvaluateApplyRules(this);
if (childType->GetName() == "Notification") if (childType == Notification::TypeInstance)
Notification::EvaluateApplyRules(this); Notification::EvaluateApplyRules(this);
if (childType->GetName() == "Dependency") if (childType == Dependency::TypeInstance)
Dependency::EvaluateApplyRules(this); Dependency::EvaluateApplyRules(this);
if (childType->GetName() == "Service") if (childType == Service::TypeInstance)
Service::EvaluateApplyRules(this); Service::EvaluateApplyRules(this);
} }

View File

@ -48,8 +48,10 @@ bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
DebugInfo di = rule.GetDebugInfo(); DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "Notification") Log(LogDebug, "Notification")
<< "Applying notification '" << name << "' to object '" << checkable->GetName() << "' for rule " << di; << "Applying notification '" << name << "' to object '" << checkable->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
builder->SetType("Notification"); builder->SetType("Notification");

View File

@ -47,8 +47,10 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
DebugInfo di = rule.GetDebugInfo(); DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "ScheduledDowntime") Log(LogDebug, "ScheduledDowntime")
<< "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di; << "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
builder->SetType("ScheduledDowntime"); builder->SetType("ScheduledDowntime");
@ -121,10 +123,9 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
Array::Ptr arrclone = arr->ShallowClone();
ObjectLock olock(arrclone); ObjectLock olock(arr);
BOOST_FOREACH(const Value& instance, arrclone) { BOOST_FOREACH(const Value& instance, arr) {
String name = rule.GetName(); String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) { if (!rule.GetFKVar().IsEmpty()) {

View File

@ -46,8 +46,10 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
DebugInfo di = rule.GetDebugInfo(); DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "Service") Log(LogDebug, "Service")
<< "Applying service '" << name << "' to host '" << host->GetName() << "' for rule " << di; << "Applying service '" << name << "' to host '" << host->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di); ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
builder->SetType("Service"); builder->SetType("Service");
@ -109,10 +111,9 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
Array::Ptr arrclone = arr->ShallowClone();
ObjectLock olock(arrclone); ObjectLock olock(arr);
BOOST_FOREACH(const Value& instance, arrclone) { BOOST_FOREACH(const Value& instance, arr) {
String name = rule.GetName(); String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) { if (!rule.GetFKVar().IsEmpty()) {

View File

@ -97,13 +97,13 @@ void Service::OnAllConfigLoaded(void)
void Service::CreateChildObjects(const Type::Ptr& childType) void Service::CreateChildObjects(const Type::Ptr& childType)
{ {
if (childType->GetName() == "ScheduledDowntime") if (childType == ScheduledDowntime::TypeInstance)
ScheduledDowntime::EvaluateApplyRules(this); ScheduledDowntime::EvaluateApplyRules(this);
if (childType->GetName() == "Notification") if (childType == Notification::TypeInstance)
Notification::EvaluateApplyRules(this); Notification::EvaluateApplyRules(this);
if (childType->GetName() == "Dependency") if (childType == Dependency::TypeInstance)
Dependency::EvaluateApplyRules(this); Dependency::EvaluateApplyRules(this);
} }

View File

@ -51,7 +51,9 @@ void TimePeriod::Start(bool runtimeCreated)
/* Pre-fill the time period for the next 24 hours. */ /* Pre-fill the time period for the next 24 hours. */
double now = Utility::GetTime(); double now = Utility::GetTime();
UpdateRegion(now, now + 24 * 3600, true); UpdateRegion(now, now + 24 * 3600, true);
#ifdef _DEBUG
Dump(); Dump();
#endif /* _DEBUG */
} }
void TimePeriod::AddSegment(double begin, double end) void TimePeriod::AddSegment(double begin, double end)
@ -176,7 +178,9 @@ void TimePeriod::RemoveSegment(double begin, double end)
SetSegments(newSegments); SetSegments(newSegments);
#ifdef _DEBUG
Dump(); Dump();
#endif /* _DEBUG */
} }
void TimePeriod::RemoveSegment(const Dictionary::Ptr& segment) void TimePeriod::RemoveSegment(const Dictionary::Ptr& segment)
@ -351,7 +355,9 @@ void TimePeriod::UpdateTimerHandler(void)
} }
tp->UpdateRegion(valid_end, now + 24 * 3600, false); tp->UpdateRegion(valid_end, now + 24 * 3600, false);
#ifdef _DEBUG
tp->Dump(); tp->Dump();
#endif /* _DEBUG */
} }
} }