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)
{
std::ostringstream msgbuf;
msgbuf << str.GetLength() << ":" << str << ",";
WriteStringToStream(msgbuf, str);
String msg = msgbuf.str();
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:
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(std::ostream& stream, const String& message);
private:
NetString(void);

View File

@ -327,7 +327,7 @@ private:
inline std::ostream& operator<<(std::ostream& stream, const String& str)
{
stream << static_cast<std::string>(str);
stream << str.GetData();
return stream;
}
@ -341,102 +341,102 @@ inline std::istream& operator>>(std::istream& stream, String& str)
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)
{
return static_cast<std::string>(lhs)+rhs;
return lhs.GetData() + 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)
{
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)
{
return static_cast<std::string>(lhs) == rhs;
return lhs.GetData() == 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)
{
return static_cast<std::string>(lhs) < rhs;
return lhs.GetData() < 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)
{
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)
{
return static_cast<std::string>(lhs) > rhs;
return lhs.GetData() > 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)
{
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)
{
return static_cast<std::string>(lhs) <= rhs;
return lhs.GetData() <= 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)
{
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)
{
return static_cast<std::string>(lhs) >= rhs;
return lhs.GetData() >= 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)
{
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)
{
return static_cast<std::string>(lhs) != rhs;
return lhs.GetData() != 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)

View File

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

View File

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

View File

@ -48,8 +48,10 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "Dependency")
<< "Applying dependency '" << name << "' to object '" << checkable->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
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));
Array::Ptr arr = vinstances;
Array::Ptr arrclone = arr->ShallowClone();
ObjectLock olock(arrclone);
BOOST_FOREACH(const Value& instance, arrclone) {
ObjectLock olock(arr);
BOOST_FOREACH(const Value& instance, arr) {
String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) {

View File

@ -87,15 +87,10 @@ void Dependency::OnAllConfigLoaded(void)
Host::Ptr childHost = Host::GetByName(GetChildHostName());
if (childHost) {
if (GetChildServiceName().IsEmpty()) {
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' child host '" << GetChildHostName() << ".";
if (GetChildServiceName().IsEmpty())
m_Child = childHost;
} else {
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' child host '" << GetChildHostName() << "' service '" << GetChildServiceName() << "' .";
else
m_Child = childHost->GetServiceByShortName(GetChildServiceName());
}
}
if (!m_Child)
@ -106,15 +101,10 @@ void Dependency::OnAllConfigLoaded(void)
Host::Ptr parentHost = Host::GetByName(GetParentHostName());
if (parentHost) {
if (GetParentServiceName().IsEmpty()) {
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' parent host '" << GetParentHostName() << ".";
if (GetParentServiceName().IsEmpty())
m_Parent = parentHost;
} else {
Log(LogDebug, "Dependency")
<< "Dependency '" << GetName() << "' parent host '" << GetParentHostName() << "' service '" << GetParentServiceName() << "' .";
else
m_Parent = parentHost->GetServiceByShortName(GetParentServiceName());
}
}
if (!m_Parent)

View File

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

View File

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

View File

@ -47,8 +47,10 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "ScheduledDowntime")
<< "Applying scheduled downtime '" << rule.GetName() << "' to object '" << checkable->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
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));
Array::Ptr arr = vinstances;
Array::Ptr arrclone = arr->ShallowClone();
ObjectLock olock(arrclone);
BOOST_FOREACH(const Value& instance, arrclone) {
ObjectLock olock(arr);
BOOST_FOREACH(const Value& instance, arr) {
String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) {

View File

@ -46,8 +46,10 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
DebugInfo di = rule.GetDebugInfo();
#ifdef _DEBUG
Log(LogDebug, "Service")
<< "Applying service '" << name << "' to host '" << host->GetName() << "' for rule " << di;
#endif /* _DEBUG */
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
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));
Array::Ptr arr = vinstances;
Array::Ptr arrclone = arr->ShallowClone();
ObjectLock olock(arrclone);
BOOST_FOREACH(const Value& instance, arrclone) {
ObjectLock olock(arr);
BOOST_FOREACH(const Value& instance, arr) {
String name = rule.GetName();
if (!rule.GetFKVar().IsEmpty()) {

View File

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

View File

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