Make sure we don't block on write() while holding locks.

This commit is contained in:
Gunnar Beutner 2013-02-24 12:47:24 +01:00
parent d011f09f32
commit 0a0bb967a4
9 changed files with 77 additions and 43 deletions

View File

@ -175,7 +175,7 @@ void CompatComponent::ProcessCommand(const String& command)
}
#endif /* _WIN32 */
void CompatComponent::DumpComments(ofstream& fp, const Service::Ptr& owner, CompatObjectType type)
void CompatComponent::DumpComments(ostream& fp, const Service::Ptr& owner, CompatObjectType type)
{
ObjectLock olock(owner);
@ -212,7 +212,7 @@ void CompatComponent::DumpComments(ofstream& fp, const Service::Ptr& owner, Comp
}
}
void CompatComponent::DumpDowntimes(ofstream& fp, const Service::Ptr& owner, CompatObjectType type)
void CompatComponent::DumpDowntimes(ostream& fp, const Service::Ptr& owner, CompatObjectType type)
{
ObjectLock olock(owner);
@ -255,7 +255,7 @@ void CompatComponent::DumpDowntimes(ofstream& fp, const Service::Ptr& owner, Com
}
}
void CompatComponent::DumpHostStatus(ofstream& fp, const Host::Ptr& host)
void CompatComponent::DumpHostStatus(ostream& fp, const Host::Ptr& host)
{
Service::Ptr hc;
@ -294,7 +294,7 @@ void CompatComponent::DumpHostStatus(ofstream& fp, const Host::Ptr& host)
}
}
void CompatComponent::DumpHostObject(ofstream& fp, const Host::Ptr& host)
void CompatComponent::DumpHostObject(ostream& fp, const Host::Ptr& host)
{
ObjectLock olock(host);
@ -319,7 +319,7 @@ void CompatComponent::DumpHostObject(ofstream& fp, const Host::Ptr& host)
<< "\n";
}
void CompatComponent::DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& service, CompatObjectType type)
void CompatComponent::DumpServiceStatusAttrs(ostream& fp, const Service::Ptr& service, CompatObjectType type)
{
String output;
String perfdata;
@ -388,7 +388,7 @@ void CompatComponent::DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& s
}
}
void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& service)
void CompatComponent::DumpServiceStatus(ostream& fp, const Service::Ptr& service)
{
String host_name, short_name;
Host::Ptr host;
@ -417,7 +417,7 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, const Service::Ptr& servic
DumpComments(fp, service, CompatTypeService);
}
void CompatComponent::DumpServiceObject(ofstream& fp, const Service::Ptr& service)
void CompatComponent::DumpServiceObject(ostream& fp, const Service::Ptr& service)
{
set<Service::Ptr> parentServices;
Host::Ptr host;
@ -534,48 +534,64 @@ void CompatComponent::StatusTimerHandler(void)
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) {
Host::Ptr host = static_pointer_cast<Host>(object);
DumpHostStatus(statusfp, host);
DumpHostObject(objectfp, host);
stringstream tempstatusfp, tempobjectfp;
DumpHostStatus(tempstatusfp, host);
DumpHostObject(tempobjectfp, host);
statusfp << tempstatusfp.str();
objectfp << tempobjectfp.str();
}
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("HostGroup")) {
HostGroup::Ptr hg = static_pointer_cast<HostGroup>(object);
stringstream tempobjectfp;
{
ObjectLock olock(hg);
objectfp << "define hostgroup {" << "\n"
tempobjectfp << "define hostgroup {" << "\n"
<< "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n"
<< "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n"
<< "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n";
}
objectfp << "\t" << "members" << "\t";
DumpNameList(objectfp, HostGroup::GetMembers(hg));
objectfp << "\n"
tempobjectfp << "\t" << "members" << "\t";
DumpNameList(tempobjectfp, HostGroup::GetMembers(hg));
tempobjectfp << "\n"
<< "}" << "\n";
objectfp << tempobjectfp.str();
}
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
Service::Ptr service = static_pointer_cast<Service>(object);
stringstream tempstatusfp, tempobjectfp;
DumpServiceStatus(statusfp, service);
DumpServiceObject(objectfp, service);
statusfp << tempstatusfp.str();
objectfp << tempobjectfp.str();
}
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("ServiceGroup")) {
ServiceGroup::Ptr sg = static_pointer_cast<ServiceGroup>(object);
stringstream tempobjectfp;
{
ObjectLock olock(sg);
objectfp << "define servicegroup {" << "\n"
tempobjectfp << "define servicegroup {" << "\n"
<< "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n"
<< "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n"
<< "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n";
}
objectfp << "\t" << "members" << "\t";
tempobjectfp << "\t" << "members" << "\t";
vector<String> sglist;
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
@ -597,10 +613,12 @@ void CompatComponent::StatusTimerHandler(void)
sglist.push_back(short_name);
}
DumpStringList(objectfp, sglist);
DumpStringList(tempobjectfp, sglist);
objectfp << "\n"
tempobjectfp << "\n"
<< "}" << "\n";
objectfp << tempobjectfp.str();
}
statusfp.close();

View File

@ -53,15 +53,15 @@ private:
String GetLogPath(void) const;
String GetCommandPath(void) const;
void DumpDowntimes(ofstream& fp, const Service::Ptr& owner, CompatObjectType type);
void DumpComments(ofstream& fp, const Service::Ptr& owner, CompatObjectType type);
void DumpHostStatus(ofstream& fp, const Host::Ptr& host);
void DumpHostObject(ofstream& fp, const Host::Ptr& host);
void DumpDowntimes(ostream& fp, const Service::Ptr& owner, CompatObjectType type);
void DumpComments(ostream& fp, const Service::Ptr& owner, CompatObjectType type);
void DumpHostStatus(ostream& fp, const Host::Ptr& host);
void DumpHostObject(ostream& fp, const Host::Ptr& host);
void DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& service, CompatObjectType type);
void DumpServiceStatusAttrs(ostream& fp, const Service::Ptr& service, CompatObjectType type);
template<typename T>
void DumpNameList(ofstream& fp, const T& list)
void DumpNameList(ostream& fp, const T& list)
{
typename T::const_iterator it;
bool first = true;
@ -77,7 +77,7 @@ private:
}
template<typename T>
void DumpStringList(ofstream& fp, const T& list)
void DumpStringList(ostream& fp, const T& list)
{
typename T::const_iterator it;
bool first = true;
@ -91,8 +91,8 @@ private:
}
}
void DumpServiceStatus(ofstream& fp, const Service::Ptr& service);
void DumpServiceObject(ofstream& fp, const Service::Ptr& service);
void DumpServiceStatus(ostream& fp, const Service::Ptr& service);
void DumpServiceObject(ostream& fp, const Service::Ptr& service);
void StatusTimerHandler(void);
};

View File

@ -306,8 +306,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const vector<String
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
Logger::Write(LogInformation, "icinga", "Setting acknowledgement for service '" + service->GetName() + "'");
service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
service->SetAcknowledgementExpiry(0);
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal);
}
void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const vector<String>& arguments)
@ -324,8 +323,7 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const vector<
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
Logger::Write(LogInformation, "icinga", "Setting timed acknowledgement for service '" + service->GetName() + "'");
service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
service->SetAcknowledgementExpiry(timestamp);
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal, timestamp);
}
void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const vector<String>& arguments)
@ -336,8 +334,7 @@ void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const vector<Str
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Removing acknowledgement for service '" + service->GetName() + "'");
service->SetAcknowledgement(AcknowledgementNone);
service->SetAcknowledgementExpiry(0);
service->ClearAcknowledgement();
}
void ExternalCommandProcessor::AcknowledgeHostProblem(double, const vector<String>& arguments)
@ -355,8 +352,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const vector<Strin
if (service->GetState() == StateOK)
BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
service->SetAcknowledgementExpiry(0);
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal);
}
}
@ -376,8 +372,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const vector
if (service->GetState() == StateOK)
BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
service->SetAcknowledgement(sticky ? AcknowledgementSticky : AcknowledgementNormal);
service->SetAcknowledgementExpiry(timestamp);
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal, timestamp);
}
}
@ -391,8 +386,7 @@ void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const vector<St
Logger::Write(LogInformation, "icinga", "Removing acknowledgement for host '" + host->GetName() + "'");
Service::Ptr service = host->GetHostCheckService();
if (service) {
service->SetAcknowledgement(AcknowledgementNone);
service->SetAcknowledgementExpiry(0);
service->ClearAcknowledgement();
}
}

View File

@ -96,7 +96,9 @@ String Notification::NotificationTypeToString(NotificationType type)
case NotificationDowntimeRemoved:
return "DOWNTIMECANCELLED";
case NotificationCustom:
return "DOWNTIMECUSTOM";
return "CUSTOM";
case NotificationAcknowledgement:
return "ACKNOWLEDGEMENT";
case NotificationProblem:
return "PROBLEM";
case NotificationRecovery:

View File

@ -34,6 +34,7 @@ enum NotificationType
NotificationDowntimeEnd,
NotificationDowntimeRemoved,
NotificationCustom,
NotificationAcknowledgement,
NotificationProblem,
NotificationRecovery
};

View File

@ -23,8 +23,8 @@ using namespace icinga;
REGISTER_SCRIPTFUNCTION("PluginCheck", &PluginCheckTask::ScriptFunc);
PluginCheckTask::PluginCheckTask(const ScriptTask::Ptr& task, const Process::Ptr& process)
: m_Task(task), m_Process(process)
PluginCheckTask::PluginCheckTask(const ScriptTask::Ptr& task, const Process::Ptr& process, const Value& command)
: m_Task(task), m_Process(process), m_Command(command)
{ }
void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments)
@ -49,7 +49,7 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
PluginCheckTask ct(task, process);
PluginCheckTask ct(task, process, command);
process->Start(boost::bind(&PluginCheckTask::ProcessFinishedHandler, ct));
}
@ -71,6 +71,7 @@ void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
String output = pr.Output;
output.Trim();
Dictionary::Ptr result = ParseCheckOutput(output);
result->Set("command", ct.m_Command);
result->Set("state", ExitStatusToState(pr.ExitStatus));
result->Set("execution_start", pr.ExecutionStart);
result->Set("execution_end", pr.ExecutionEnd);

View File

@ -39,10 +39,11 @@ public:
private:
static void ProcessFinishedHandler(PluginCheckTask ct);
PluginCheckTask(const ScriptTask::Ptr& task, const Process::Ptr& process);
PluginCheckTask(const ScriptTask::Ptr& task, const Process::Ptr& process, const Value& command);
ScriptTask::Ptr m_Task;
Process::Ptr m_Process;
Value m_Command;
};
}

View File

@ -258,6 +258,20 @@ void Service::SetAcknowledgementExpiry(double timestamp)
Set("acknowledgement_expiry", timestamp);
}
void Service::AcknowledgeProblem(AcknowledgementType type, double expiry)
{
SetAcknowledgement(type);
SetAcknowledgementExpiry(expiry);
RequestNotifications(NotificationAcknowledgement);
}
void Service::ClearAcknowledgement(void)
{
SetAcknowledgement(AcknowledgementNone);
SetAcknowledgementExpiry(0);
}
void Service::OnAttributeChanged(const String& name, const Value& oldValue)
{
if (name == "checker")

View File

@ -171,6 +171,9 @@ public:
void ApplyCheckResult(const Dictionary::Ptr& cr);
static void UpdateStatistics(const Dictionary::Ptr& cr);
void AcknowledgeProblem(AcknowledgementType type, double expiry = 0);
void ClearAcknowledgement(void);
static void BeginExecuteCheck(const Service::Ptr& self, const function<void (void)>& callback);
void ProcessCheckResult(const Dictionary::Ptr& cr);