Improve performance for Livestatus queries

refs #10428
This commit is contained in:
Gunnar Beutner 2015-10-22 08:28:40 +02:00
parent b4d592dc16
commit fd5d6de52e
5 changed files with 67 additions and 40 deletions

View File

@ -91,14 +91,15 @@ void Host::Stop(void)
// TODO: unregister slave services/notifications?
}
std::set<Service::Ptr> Host::GetServices(void) const
std::vector<Service::Ptr> Host::GetServices(void) const
{
boost::mutex::scoped_lock lock(m_ServicesMutex);
std::set<Service::Ptr> services;
std::vector<Service::Ptr> services;
services.reserve(m_Services.size());
typedef std::pair<String, Service::Ptr> ServicePair;
BOOST_FOREACH(const ServicePair& kv, m_Services) {
services.insert(kv.second);
services.push_back(kv.second);
}
return services;

View File

@ -43,7 +43,7 @@ public:
intrusive_ptr<Service> GetServiceByShortName(const Value& name);
std::set<intrusive_ptr<Service> > GetServices(void) const;
std::vector<intrusive_ptr<Service> > GetServices(void) const;
void AddService(const intrusive_ptr<Service>& service);
void RemoveService(const intrusive_ptr<Service>& service);

View File

@ -1478,9 +1478,12 @@ Value HostsTable::ServicesAccessor(const Value& row)
if (!host)
return Empty;
Array::Ptr services = new Array();
std::vector<Service::Ptr> rservices = host->GetServices();
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Array::Ptr services = new Array();
services->Reserve(rservices.size());
BOOST_FOREACH(const Service::Ptr& service, rservices) {
services->Add(service->GetShortName());
}
@ -1494,9 +1497,12 @@ Value HostsTable::ServicesWithStateAccessor(const Value& row)
if (!host)
return Empty;
Array::Ptr services = new Array();
std::vector<Service::Ptr> rservices = host->GetServices();
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Array::Ptr services = new Array();
services->Reserve(rservices.size());
BOOST_FOREACH(const Service::Ptr& service, rservices) {
Array::Ptr svc_add = new Array();
svc_add->Add(service->GetShortName());
@ -1515,9 +1521,12 @@ Value HostsTable::ServicesWithInfoAccessor(const Value& row)
if (!host)
return Empty;
Array::Ptr services = new Array();
std::vector<Service::Ptr> rservices = host->GetServices();
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Array::Ptr services = new Array();
services->Reserve(rservices.size());
BOOST_FOREACH(const Service::Ptr& service, rservices) {
Array::Ptr svc_add = new Array();
svc_add->Add(service->GetShortName());

View File

@ -403,34 +403,50 @@ Filter::Ptr LivestatusQuery::ParseFilter(const String& params, unsigned long& fr
return filter;
}
void LivestatusQuery::PrintResultSet(std::ostream& fp, const Array::Ptr& rs) const
void LivestatusQuery::BeginResultSet(std::ostream& fp) const
{
if (m_OutputFormat == "json" || m_OutputFormat == "python")
fp << "[";
}
void LivestatusQuery::EndResultSet(std::ostream& fp) const
{
if (m_OutputFormat == "json" || m_OutputFormat == "python")
fp << "]";
}
void LivestatusQuery::AppendResultRow(std::ostream& fp, const Array::Ptr& row, bool& first_row) const
{
if (m_OutputFormat == "csv") {
ObjectLock olock(rs);
bool first = true;
BOOST_FOREACH(const Array::Ptr& row, rs) {
bool first = true;
ObjectLock rlock(row);
BOOST_FOREACH(const Value& value, row) {
if (first)
first = false;
else
fp << m_Separators[1];
ObjectLock rlock(row);
BOOST_FOREACH(const Value& value, row) {
if (first)
first = false;
else
fp << m_Separators[1];
if (value.IsObjectType<Array>())
PrintCsvArray(fp, value, 0);
else
fp << value;
}
fp << m_Separators[0];
if (value.IsObjectType<Array>())
PrintCsvArray(fp, value, 0);
else
fp << value;
}
fp << m_Separators[0];
} else if (m_OutputFormat == "json") {
fp << JsonEncode(rs);
if (!first_row)
fp << ", ";
fp << JsonEncode(row);
} else if (m_OutputFormat == "python") {
PrintPythonArray(fp, rs);
if (!first_row)
fp << ", ";
PrintPythonArray(fp, row);
}
first_row = false;
}
void LivestatusQuery::PrintCsvArray(std::ostream& fp, const Array::Ptr& array, int level) const
@ -503,7 +519,9 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream)
else
columns = table->GetColumnNames();
Array::Ptr rs = new Array();
std::ostringstream result;
bool first_row = true;
BeginResultSet(result);
if (m_Aggregators.empty()) {
Array::Ptr header = new Array();
@ -516,8 +534,6 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream)
BOOST_FOREACH(const String& columnName, columns)
column_objs.push_back(std::make_pair(columnName, table->GetColumn(columnName)));
rs->Reserve(1 + objects.size());
BOOST_FOREACH(const LivestatusRowValue& object, objects) {
Array::Ptr row = new Array();
@ -531,11 +547,11 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream)
}
if (m_ColumnHeaders) {
rs->Add(header);
AppendResultRow(result, header, first_row);
m_ColumnHeaders = false;
}
rs->Add(row);
AppendResultRow(result, row, first_row);
}
} else {
std::vector<double> stats(m_Aggregators.size(), 0);
@ -563,7 +579,7 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream)
header->Add("stats_" + Convert::ToString(i));
}
rs->Add(header);
AppendResultRow(result, header, first_row);
}
Array::Ptr row = new Array();
@ -587,11 +603,10 @@ void LivestatusQuery::ExecuteGetHelper(const Stream::Ptr& stream)
for (size_t i = 0; i < m_Aggregators.size(); i++)
row->Add(stats[i]);
rs->Add(row);
AppendResultRow(result, row, first_row);
}
std::ostringstream result;
PrintResultSet(result, rs);
EndResultSet(result);
SendResponse(stream, LivestatusErrorOK, result.str());
}

View File

@ -97,7 +97,9 @@ private:
unsigned long m_LogTimeUntil;
String m_CompatLogPath;
void PrintResultSet(std::ostream& fp, const Array::Ptr& rs) const;
void BeginResultSet(std::ostream& fp) const;
void EndResultSet(std::ostream& fp) const;
void AppendResultRow(std::ostream& fp, const Array::Ptr& row, bool& first_row) const;
void PrintCsvArray(std::ostream& fp, const Array::Ptr& array, int level) const;
void PrintPythonArray(std::ostream& fp, const Array::Ptr& array) const;
static String QuoteStringPython(const String& str);