launch_daemon: Implemented sticky events, and registration.

* Sticky events are events that keep their signal raised, ie. even if
  a job is initialized afterwards, it will still be triggered.
* Consolidated naming for external events.
* Events are now registered once they are actually being used. This
  allows them to allocate the resources they need to do their thing.
This commit is contained in:
Axel Dörfler 2015-10-17 14:07:53 +02:00
parent 5ab2b1457b
commit 7cd19b7e5c
9 changed files with 178 additions and 58 deletions

View File

@ -211,8 +211,13 @@ on {
The latter form can be used to solve ambiguous event definitions.
By specifying the \c B_STICKY_EVENT flag, you can mark the event as being
a permanent change. Once triggered, such an event will stay triggered, ie.
even new targets or jobs will consider it triggered.
\param source The messenger the event is coming from.
\param name The name of the event.
\param flags Flags for the event as described.
\return B_OK if the event could be registered, otherwise an error code.
\since Haiku R1

View File

@ -9,6 +9,12 @@
#include <Messenger.h>
// Flags for RegisterEvent()
enum {
B_STICKY_EVENT = 0x01
};
class BLaunchRoster {
public:
BLaunchRoster();
@ -31,7 +37,7 @@ public:
status_t StartSession(const char* login);
status_t RegisterEvent(const BMessenger& source,
const char* name);
const char* name, uint32 flags);
status_t UnregisterEvent(const BMessenger& source,
const char* name);
status_t NotifyEvent(const BMessenger& source,
@ -44,7 +50,8 @@ private:
void _InitMessenger();
status_t _UpdateEvent(uint32 what,
const BMessenger& source, const char* name);
const BMessenger& source, const char* name,
uint32 flags = 0);
private:
BMessenger fMessenger;

View File

@ -206,9 +206,10 @@ BLaunchRoster::StartSession(const char* login)
status_t
BLaunchRoster::RegisterEvent(const BMessenger& source, const char* name)
BLaunchRoster::RegisterEvent(const BMessenger& source, const char* name,
uint32 flags)
{
return _UpdateEvent(B_REGISTER_LAUNCH_EVENT, source, name);
return _UpdateEvent(B_REGISTER_LAUNCH_EVENT, source, name, flags);
}
@ -241,7 +242,7 @@ BLaunchRoster::_InitMessenger()
status_t
BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
const char* name)
const char* name, uint32 flags)
{
if (be_app == NULL || name == NULL || name[0] == '\0')
return B_BAD_VALUE;
@ -254,6 +255,8 @@ BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
status = request.AddString("owner", be_app->Signature());
if (status == B_OK)
status = request.AddString("name", name);
if (status == B_OK && flags != 0)
status = request.AddUInt32("flags", flags);
if (status != B_OK)
return status;

View File

@ -9,8 +9,9 @@
#include <stdio.h>
#include <Entry.h>
#include <ObjectList.h>
#include <LaunchRoster.h>
#include <Message.h>
#include <ObjectList.h>
#include <Path.h>
#include <StringList.h>
@ -33,8 +34,8 @@ public:
const BMessenger& Target() const;
virtual status_t Register(EventRegistrator& registrator) const;
virtual void Unregister(EventRegistrator& registrator) const;
virtual status_t Register(EventRegistrator& registrator);
virtual void Unregister(EventRegistrator& registrator);
virtual void Trigger();
@ -48,6 +49,7 @@ protected:
BaseJob* fOwner;
BMessenger fTarget;
BObjectList<Event> fEvents;
bool fRegistered;
};
@ -58,6 +60,8 @@ public:
OrEvent(BaseJob* owner,
const BMessenger& target);
virtual void ResetTrigger();
virtual BString ToString() const;
};
@ -66,8 +70,8 @@ class DemandEvent : public Event {
public:
DemandEvent(Event* parent);
virtual status_t Register(EventRegistrator& registrator) const;
virtual void Unregister(EventRegistrator& registrator) const;
virtual status_t Register(EventRegistrator& registrator);
virtual void Unregister(EventRegistrator& registrator);
virtual BString ToString() const;
};
@ -79,16 +83,19 @@ public:
const BMessage& args);
const BString& Name() const;
bool Resolve();
bool Resolve(uint32 flags);
virtual status_t Register(EventRegistrator& registrator) const;
virtual void Unregister(EventRegistrator& registrator) const;
virtual void ResetTrigger();
virtual status_t Register(EventRegistrator& registrator);
virtual void Unregister(EventRegistrator& registrator);
virtual BString ToString() const;
private:
BString fName;
BStringList fArguments;
uint32 fFlags;
bool fResolved;
};
@ -98,8 +105,8 @@ public:
FileCreatedEvent(Event* parent,
const BMessage& args);
virtual status_t Register(EventRegistrator& registrator) const;
virtual void Unregister(EventRegistrator& registrator) const;
virtual status_t Register(EventRegistrator& registrator);
virtual void Unregister(EventRegistrator& registrator);
virtual BString ToString() const;
@ -198,7 +205,8 @@ EventContainer::EventContainer(Event* parent, const BMessenger* target,
const BMessage& args)
:
Event(parent),
fEvents(5, true)
fEvents(5, true),
fRegistered(false)
{
if (target != NULL)
fTarget = *target;
@ -222,7 +230,8 @@ EventContainer::EventContainer(BaseJob* owner, const BMessenger& target)
Event(NULL),
fOwner(owner),
fTarget(target),
fEvents(5, true)
fEvents(5, true),
fRegistered(false)
{
}
@ -250,8 +259,11 @@ EventContainer::Target() const
status_t
EventContainer::Register(EventRegistrator& registrator) const
EventContainer::Register(EventRegistrator& registrator)
{
if (fRegistered)
return B_OK;
int32 count = fEvents.CountItems();
for (int32 index = 0; index < count; index++) {
Event* event = fEvents.ItemAt(index);
@ -260,12 +272,13 @@ EventContainer::Register(EventRegistrator& registrator) const
return status;
}
fRegistered = true;
return B_OK;
}
void
EventContainer::Unregister(EventRegistrator& registrator) const
EventContainer::Unregister(EventRegistrator& registrator)
{
int32 count = fEvents.CountItems();
for (int32 index = 0; index < count; index++) {
@ -334,6 +347,20 @@ OrEvent::OrEvent(BaseJob* owner, const BMessenger& target)
}
void
OrEvent::ResetTrigger()
{
fTriggered = false;
int32 count = fEvents.CountItems();
for (int32 index = 0; index < count; index++) {
Event* event = fEvents.ItemAt(index);
event->ResetTrigger();
fTriggered |= event->Triggered();
}
}
BString
OrEvent::ToString() const
{
@ -354,14 +381,14 @@ DemandEvent::DemandEvent(Event* parent)
status_t
DemandEvent::Register(EventRegistrator& registrator) const
DemandEvent::Register(EventRegistrator& registrator)
{
return B_OK;
}
void
DemandEvent::Unregister(EventRegistrator& registrator) const
DemandEvent::Unregister(EventRegistrator& registrator)
{
}
@ -381,6 +408,7 @@ ExternalEvent::ExternalEvent(Event* parent, const char* name,
:
Event(parent),
fName(name),
fFlags(0),
fResolved(false)
{
const char* argument;
@ -399,26 +427,38 @@ ExternalEvent::Name() const
bool
ExternalEvent::Resolve()
ExternalEvent::Resolve(uint32 flags)
{
if (fResolved)
return false;
fResolved = true;
fFlags = flags;
return true;
}
status_t
ExternalEvent::Register(EventRegistrator& registrator) const
void
ExternalEvent::ResetTrigger()
{
return B_OK;
if ((fFlags & B_STICKY_EVENT) != 0)
return;
Event::ResetTrigger();
}
status_t
ExternalEvent::Register(EventRegistrator& registrator)
{
return registrator.RegisterExternalEvent(this, Name().String(), fArguments);
}
void
ExternalEvent::Unregister(EventRegistrator& registrator) const
ExternalEvent::Unregister(EventRegistrator& registrator)
{
registrator.UnregisterExternalEvent(this, Name().String());
}
@ -441,7 +481,7 @@ FileCreatedEvent::FileCreatedEvent(Event* parent, const BMessage& args)
status_t
FileCreatedEvent::Register(EventRegistrator& registrator) const
FileCreatedEvent::Register(EventRegistrator& registrator)
{
// TODO: implement!
return B_ERROR;
@ -449,7 +489,7 @@ FileCreatedEvent::Register(EventRegistrator& registrator) const
void
FileCreatedEvent::Unregister(EventRegistrator& registrator) const
FileCreatedEvent::Unregister(EventRegistrator& registrator)
{
}
@ -493,7 +533,7 @@ Events::AddOnDemand(const BMessenger& target, Event* event)
/*static*/ bool
Events::ResolveRegisteredEvent(Event* event, const char* name)
Events::ResolveExternalEvent(Event* event, const char* name, uint32 flags)
{
if (event == NULL)
return false;
@ -503,10 +543,10 @@ Events::ResolveRegisteredEvent(Event* event, const char* name)
index++) {
Event* event = container->Events().ItemAt(index);
if (ExternalEvent* external = dynamic_cast<ExternalEvent*>(event)) {
if (external->Name() == name && external->Resolve())
if (external->Name() == name && external->Resolve(flags))
return true;
} else if (dynamic_cast<EventContainer*>(event) != NULL) {
if (ResolveRegisteredEvent(event, name))
if (ResolveExternalEvent(event, name, flags))
return true;
}
}
@ -516,7 +556,7 @@ Events::ResolveRegisteredEvent(Event* event, const char* name)
/*static*/ void
Events::TriggerRegisteredEvent(Event* event, const char* name)
Events::TriggerExternalEvent(Event* event, const char* name)
{
if (event == NULL)
return;
@ -531,7 +571,7 @@ Events::TriggerRegisteredEvent(Event* event, const char* name)
return;
}
} else if (dynamic_cast<EventContainer*>(event) != NULL) {
TriggerRegisteredEvent(event, name);
TriggerExternalEvent(event, name);
}
}
}

View File

@ -16,8 +16,11 @@ class Event;
class EventRegistrator {
public:
virtual status_t RegisterEvent(Event* event) = 0;
virtual void UnregisterEvent(Event* event) = 0;
virtual status_t RegisterExternalEvent(Event* event,
const char* name,
const BStringList& arguments) = 0;
virtual void UnregisterExternalEvent(Event* event,
const char* name) = 0;
};
@ -27,13 +30,13 @@ public:
virtual ~Event();
virtual status_t Register(
EventRegistrator& registrator) const = 0;
EventRegistrator& registrator) = 0;
virtual void Unregister(
EventRegistrator& registrator) const = 0;
EventRegistrator& registrator) = 0;
bool Triggered() const;
virtual void Trigger();
void ResetTrigger();
virtual void ResetTrigger();
virtual BaseJob* Owner() const;
virtual void SetOwner(BaseJob* owner);
@ -42,7 +45,7 @@ public:
virtual BString ToString() const = 0;
private:
protected:
Event* fParent;
bool fTriggered;
};
@ -53,9 +56,9 @@ public:
static Event* FromMessage(const BMessenger& target,
const BMessage& message);
static Event* AddOnDemand(const BMessenger& target, Event* event);
static bool ResolveRegisteredEvent(Event* event,
const char* name);
static void TriggerRegisteredEvent(Event* event,
static bool ResolveExternalEvent(Event* event,
const char* name, uint32 flags);
static void TriggerExternalEvent(Event* event,
const char* name);
static bool TriggerDemand(Event* event);
};

View File

@ -341,6 +341,14 @@ Job::IsLaunched() const
}
bool
Job::IsRunning() const
{
// TODO: monitor team status; should jobs be allowed to run multiple times?
return State() == B_JOB_STATE_SUCCEEDED && IsLaunched() && IsService();
}
status_t
Job::HandleGetLaunchData(BMessage* message)
{
@ -352,10 +360,23 @@ Job::HandleGetLaunchData(BMessage* message)
}
status_t
Job::Run()
{
status_t status = BJob::Run();
// TODO: monitor team, don't just do this
if (!IsService())
SetState(B_JOB_STATE_WAITING_TO_RUN);
return status;
}
status_t
Job::Execute()
{
if (!IsLaunched())
if (!IsLaunched() || !IsService())
return Launch();
return B_OK;

View File

@ -71,9 +71,12 @@ public:
status_t Launch();
bool IsLaunched() const;
bool IsRunning() const;
status_t HandleGetLaunchData(BMessage* message);
virtual status_t Run();
protected:
virtual status_t Execute();

View File

@ -85,10 +85,12 @@ class ExternalEventSource {
public:
ExternalEventSource(BMessenger& source,
const char* ownerName,
const char* name);
const char* name, uint32 flags);
~ExternalEventSource();
const char* Name() const;
uint32 Flags() const
{ return fFlags; }
int32 CountListeners() const;
BaseJob* ListenerAt(int32 index) const;
@ -98,6 +100,7 @@ public:
private:
BString fName;
uint32 fFlags;
BObjectList<BaseJob> fListeners;
};
@ -108,7 +111,8 @@ typedef std::map<BString, Target*> TargetMap;
typedef std::map<BString, ExternalEventSource*> EventMap;
class LaunchDaemon : public BServer, public Finder, public ConditionContext {
class LaunchDaemon : public BServer, public Finder, public ConditionContext,
public EventRegistrator {
public:
LaunchDaemon(bool userMode,
const EventMap& events, status_t& error);
@ -118,9 +122,17 @@ public:
virtual Target* FindTarget(const char* name) const;
Session* FindSession(uid_t user) const;
// ConditionContext
virtual bool IsSafeMode() const;
virtual bool BootVolumeIsReadOnly() const;
// EventRegistrator
virtual status_t RegisterExternalEvent(Event* event,
const char* name,
const BStringList& arguments);
virtual void UnregisterExternalEvent(Event* event,
const char* name);
virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message);
@ -218,9 +230,10 @@ Session::Session(uid_t user, const BMessenger& daemon)
ExternalEventSource::ExternalEventSource(BMessenger& source,
const char* ownerName, const char* name)
const char* ownerName, const char* name, uint32 flags)
:
fName(name),
fFlags(flags),
fListeners(5, true)
{
}
@ -352,6 +365,22 @@ LaunchDaemon::BootVolumeIsReadOnly() const
}
status_t
LaunchDaemon::RegisterExternalEvent(Event* event, const char* name,
const BStringList& arguments)
{
// TODO: register actual event with event source
return B_OK;
}
void
LaunchDaemon::UnregisterExternalEvent(Event* event, const char* name)
{
// TODO!
}
void
LaunchDaemon::ReadyToRun()
{
@ -482,7 +511,7 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message)
return;
}
reply.what = B_NAME_NOT_FOUND;
} else if (!job->IsLaunched()) {
} else if (job->IsService() && !job->IsLaunched()) {
if (job->InitCheck() == B_NO_INIT || !job->CheckCondition(*this)) {
// The job exists, but cannot be started yet, as its
// conditions are not met; don't make it available yet
@ -638,6 +667,7 @@ LaunchDaemon::_HandleRegisterLaunchEvent(BMessage* message)
const char* name = message->GetString("name");
const char* ownerName = message->GetString("owner");
uint32 flags = message->GetUInt32("flags", 0);
BMessenger source;
if (name != NULL && ownerName != NULL
&& message->FindMessenger("source", &source) == B_OK) {
@ -645,7 +675,7 @@ LaunchDaemon::_HandleRegisterLaunchEvent(BMessage* message)
ownerName = get_leaf(ownerName);
ExternalEventSource* event = new (std::nothrow)
ExternalEventSource(source, ownerName, name);
ExternalEventSource(source, ownerName, name, flags);
if (event != NULL) {
// Use short name, and fully qualified name
BString eventName = name;
@ -723,7 +753,7 @@ LaunchDaemon::_HandleNotifyLaunchEvent(BMessage* message)
int32 count = event->CountListeners();
for (int32 index = 0; index < count; index++) {
BaseJob* listener = event->ListenerAt(index);
Events::TriggerRegisteredEvent(listener->Event(), name);
Events::TriggerExternalEvent(listener->Event(), name);
}
}
}
@ -851,6 +881,9 @@ LaunchDaemon::_AddTargets(BMessage& message)
_SetEvent(target, targetMessage);
_SetEnvironment(target, targetMessage);
_AddJobs(target, targetMessage);
if (target->Event() != NULL)
target->Event()->Register(*this);
}
}
@ -980,6 +1013,8 @@ LaunchDaemon::_InitJobs(Target* target)
|| job->Condition()->Test(*this)) {
std::set<BString> dependencies;
status = job->Init(*this, dependencies);
if (status == B_OK && job->Event() != NULL)
status = job->Event()->Register(*this);
}
}
@ -1030,18 +1065,20 @@ LaunchDaemon::_LaunchJobs(Target* target, bool forceNow)
/*! Adds the specified \a job to the launch queue
queue, except those that are triggered by events.
Unless \a forceNow is true, the target is only launched if its events,
Unless \c FORCE_NOW is set, the target is only launched if its events,
if any, have been triggered already.
Calling this method will trigger a demand event.
Calling this method will trigger a demand event if \c TRIGGER_DEMAND has
been set.
*/
void
LaunchDaemon::_LaunchJob(Job* job, uint32 options)
{
if (job == NULL || job->IsLaunched() || ((options & FORCE_NOW) == 0
&& (!job->EventHasTriggered() || !job->CheckCondition(*this)
|| ((options & TRIGGER_DEMAND) != 0
&& Events::TriggerDemand(job->Event()))))) {
if (job == NULL || (job->IsService() && job->IsLaunched())
|| ((options & FORCE_NOW) == 0
&& (!job->EventHasTriggered() || !job->CheckCondition(*this)
|| ((options & TRIGGER_DEMAND) != 0
&& Events::TriggerDemand(job->Event()))))) {
return;
}
@ -1160,7 +1197,7 @@ LaunchDaemon::_ResolveExternalEvents(ExternalEventSource* event,
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();
iterator++) {
Job* job = iterator->second;
if (Events::ResolveRegisteredEvent(job->Event(), name))
if (Events::ResolveExternalEvent(job->Event(), name, event->Flags()))
event->AddListener(job);
}
}
@ -1175,7 +1212,8 @@ LaunchDaemon::_ResolveExternalEvents(BaseJob* job)
for (EventMap::iterator iterator = fEvents.begin();
iterator != fEvents.end(); iterator++) {
ExternalEventSource* event = iterator->second;
if (Events::ResolveRegisteredEvent(job->Event(), event->Name()))
if (Events::ResolveExternalEvent(job->Event(), event->Name(),
event->Flags()))
event->AddListener(job);
}
}

View File

@ -81,7 +81,7 @@ AutoMounter::AutoMounter()
BDiskDeviceRoster().StartWatching(this,
B_DEVICE_REQUEST_DEVICE | B_DEVICE_REQUEST_DEVICE_LIST);
BLaunchRoster().RegisterEvent(this, kInitialMountEvent);
BLaunchRoster().RegisterEvent(this, kInitialMountEvent, B_STICKY_EVENT);
}