Fine-grained locks (WIP, Part 4).

This commit is contained in:
Gunnar Beutner 2013-02-19 07:26:52 +01:00
parent 3dace35cf1
commit ecc95b3dc0
9 changed files with 41 additions and 37 deletions

View File

@ -353,8 +353,8 @@ void DynamicObject::Unregister(void)
OnUnregistered(GetSelf()); OnUnregistered(GetSelf());
} }
ScriptTask::Ptr DynamicObject::InvokeMethod(const String& method, ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method,
const vector<Value>& arguments, ScriptTask::CompletionCallback callback) const vector<Value>& arguments)
{ {
Value value = Get("methods"); Value value = Get("methods");
@ -377,10 +377,7 @@ ScriptTask::Ptr DynamicObject::InvokeMethod(const String& method,
if (!func) if (!func)
BOOST_THROW_EXCEPTION(invalid_argument("Function '" + funcName + "' does not exist.")); BOOST_THROW_EXCEPTION(invalid_argument("Function '" + funcName + "' does not exist."));
ScriptTask::Ptr task = boost::make_shared<ScriptTask>(func, arguments); return boost::make_shared<ScriptTask>(func, arguments);
task->Start(callback);
return task;
} }
/* /*

View File

@ -100,8 +100,8 @@ public:
static signals2::signal<void (const DynamicObject::Ptr&)> OnUnregistered; static signals2::signal<void (const DynamicObject::Ptr&)> OnUnregistered;
static signals2::signal<void (double, const set<DynamicObject *>&)> OnTransactionClosing; static signals2::signal<void (double, const set<DynamicObject *>&)> OnTransactionClosing;
ScriptTask::Ptr InvokeMethod(const String& method, ScriptTask::Ptr MakeMethodTask(const String& method,
const vector<Value>& arguments, ScriptTask::CompletionCallback callback); const vector<Value>& arguments);
shared_ptr<DynamicType> GetType(void) const; shared_ptr<DynamicType> GetType(void) const;
String GetName(void) const; String GetName(void) const;

View File

@ -29,6 +29,5 @@ ScriptTask::ScriptTask(const ScriptFunction::Ptr& function,
void ScriptTask::Run(void) void ScriptTask::Run(void)
{ {
ObjectLock olock(this);
m_Function->Invoke(GetSelf(), m_Arguments); m_Function->Invoke(GetSelf(), m_Arguments);
} }

View File

@ -35,5 +35,8 @@ void API::GetAnswerToEverything(const ScriptTask::Ptr& task, const vector<Value>
Logger::Write(LogInformation, "icinga", "Hello from the Icinga 2 API: " + text); Logger::Write(LogInformation, "icinga", "Hello from the Icinga 2 API: " + text);
task->FinishResult(42); {
ObjectLock olock(task);
task->FinishResult(42);
}
} }

View File

@ -75,8 +75,8 @@ void Notification::SendNotification(NotificationType type)
vector<Value> arguments; vector<Value> arguments;
arguments.push_back(static_cast<Notification::Ptr>(GetSelf())); arguments.push_back(static_cast<Notification::Ptr>(GetSelf()));
arguments.push_back(type); arguments.push_back(type);
ScriptTask::Ptr task;
task = InvokeMethod("notify", arguments, boost::bind(&Notification::NotificationCompletedHandler, this, _1)); ScriptTask::Ptr task = MakeMethodTask("notify", arguments);
if (!task) { if (!task) {
Logger::Write(LogWarning, "icinga", "Notification object '" + GetName() + "' doesn't have a 'notify' method."); Logger::Write(LogWarning, "icinga", "Notification object '" + GetName() + "' doesn't have a 'notify' method.");
@ -84,11 +84,10 @@ void Notification::SendNotification(NotificationType type)
return; return;
} }
if (!task->IsFinished()) { /* We need to keep the task object alive until the completion handler is called. */
/* We need to keep the task object alive until the completion handler is called. */ m_Tasks.insert(task);
m_Tasks.insert(task); task->Start(boost::bind(&Notification::NotificationCompletedHandler, this, _1));
}
} }
void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task) void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)

View File

@ -31,5 +31,8 @@ void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>&
Dictionary::Ptr cr = boost::make_shared<Dictionary>(); Dictionary::Ptr cr = boost::make_shared<Dictionary>();
cr->Set("state", StateUnknown); cr->Set("state", StateUnknown);
task->FinishResult(cr); {
ObjectLock olock(task);
task->FinishResult(cr);
}
} }

View File

@ -79,7 +79,11 @@ void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
try { try {
pr = ct.m_Process->GetResult(); pr = ct.m_Process->GetResult();
} catch (...) { } catch (...) {
ct.m_Task->FinishException(boost::current_exception()); {
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishException(boost::current_exception());
}
return; return;
} }
@ -90,7 +94,10 @@ void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
result->Set("execution_start", pr.ExecutionStart); result->Set("execution_start", pr.ExecutionStart);
result->Set("execution_end", pr.ExecutionEnd); result->Set("execution_end", pr.ExecutionEnd);
ct.m_Task->FinishResult(result); {
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishResult(result);
}
} }
ServiceState PluginCheckTask::ExitStatusToState(int exitStatus) ServiceState PluginCheckTask::ExitStatusToState(int exitStatus)

View File

@ -107,9 +107,16 @@ void PluginNotificationTask::ProcessFinishedHandler(PluginNotificationTask ct)
Logger::Write(LogWarning, "icinga", msgbuf.str()); Logger::Write(LogWarning, "icinga", msgbuf.str());
} }
ct.m_Task->FinishResult(Empty); {
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishResult(Empty);
}
} catch (...) { } catch (...) {
ct.m_Task->FinishException(boost::current_exception()); {
ObjectLock olock(ct.m_Task);
ct.m_Task->FinishException(boost::current_exception());
}
return; return;
} }
} }

View File

@ -435,24 +435,13 @@ void Service::BeginExecuteCheck(const function<void (void)>& callback)
scheduleInfo->Set("schedule_start", GetNextCheck()); scheduleInfo->Set("schedule_start", GetNextCheck());
scheduleInfo->Set("execution_start", Utility::GetTime()); scheduleInfo->Set("execution_start", Utility::GetTime());
try { vector<Value> arguments;
vector<Value> arguments; arguments.push_back(static_cast<Service::Ptr>(GetSelf()));
arguments.push_back(static_cast<Service::Ptr>(GetSelf()));
ScriptTask::Ptr task;
task = InvokeMethod("check", arguments, boost::bind(&Service::CheckCompletedHandler, this, scheduleInfo, _1, callback));
if (!task->IsFinished()) ScriptTask::Ptr task = MakeMethodTask("check", arguments);
Set("current_task", task); Set("current_task", task);
} catch (...) {
/* something went wrong while setting up the method call -
* reschedule the service and call the callback anyway. */
UpdateNextCheck(); task->Start(boost::bind(&Service::CheckCompletedHandler, this, scheduleInfo, _1, callback));
callback();
throw;
}
} }
void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo, void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,