[haiku-commits] BRANCH axeld-github.launch_daemon [8541379b99dc] src/servers/launch

  • From: axeld-github.launch_daemon <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 14 Jul 2015 19:31:52 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/axeld-github/launch_daemon'
old head: 955efcfea94105eaaed1b1d948446fdd31bff37d
new head: 8541379b99dccf7a4376a6ec45abf756ef61deb8
overview: https://github.com/axeld/haiku/compare/955efcfea941...8541379b99dc

----------------------------------------------------------------------------

8541379b99dc: launch_daemon: Outlined basic event mechanism.

[ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit: 8541379b99dccf7a4376a6ec45abf756ef61deb8
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Tue Jul 14 16:36:05 2015 UTC

----------------------------------------------------------------------------

8 files changed, 618 insertions(+), 4 deletions(-)
src/servers/launch/BaseJob.cpp | 30 +++
src/servers/launch/BaseJob.h | 7 +
src/servers/launch/Events.cpp | 428 ++++++++++++++++++++++++++++++
src/servers/launch/Events.h | 59 ++++
src/servers/launch/Jamfile | 1 +
src/servers/launch/LaunchDaemon.cpp | 81 +++++-
src/servers/launch/LaunchDaemon.h | 15 ++
src/servers/launch/SettingsParser.cpp | 1 +

----------------------------------------------------------------------------

diff --git a/src/servers/launch/BaseJob.cpp b/src/servers/launch/BaseJob.cpp
index 61ed7a6..e6e1f22 100644
--- a/src/servers/launch/BaseJob.cpp
+++ b/src/servers/launch/BaseJob.cpp
@@ -14,6 +14,7 @@
#include <Message.h>

#include "Conditions.h"
+#include "Events.h"


BaseJob::BaseJob(const char* name)
@@ -68,6 +69,35 @@ BaseJob::CheckCondition(ConditionContext& context) const
}


+const ::Event*
+BaseJob::Event() const
+{
+ return fEvent;
+}
+
+
+::Event*
+BaseJob::Event()
+{
+ return fEvent;
+}
+
+
+void
+BaseJob::SetEvent(::Event* event)
+{
+ fEvent = event;
+ event->SetOwner(this);
+}
+
+
+bool
+BaseJob::EventHasTriggered() const
+{
+ return Event() != NULL && Event()->Triggered();
+}
+
+
const BStringList&
BaseJob::Environment() const
{
diff --git a/src/servers/launch/BaseJob.h b/src/servers/launch/BaseJob.h
index 6ebd1db..41d38f0 100644
--- a/src/servers/launch/BaseJob.h
+++ b/src/servers/launch/BaseJob.h
@@ -15,6 +15,7 @@ using namespace BSupportKit;
class BMessage;
class Condition;
class ConditionContext;
+class Event;


class BaseJob : public BJob {
@@ -29,6 +30,11 @@ public:
void
SetCondition(::Condition* condition);
bool
CheckCondition(ConditionContext& context) const;

+ const ::Event* Event() const;
+ ::Event* Event();
+ void SetEvent(::Event*
event);
+ bool EventHasTriggered()
const;
+
const BStringList& Environment() const;
BStringList& Environment();
const BStringList& EnvironmentSourceFiles() const;
@@ -47,6 +53,7 @@ private:

protected:
::Condition* fCondition;
+ ::Event* fEvent;
BStringList fEnvironment;
BStringList fSourceFiles;
};
diff --git a/src/servers/launch/Events.cpp b/src/servers/launch/Events.cpp
new file mode 100644
index 0000000..3745fd0
--- /dev/null
+++ b/src/servers/launch/Events.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "Events.h"
+
+#include <stdio.h>
+
+#include <Entry.h>
+#include <ObjectList.h>
+#include <Message.h>
+#include <Path.h>
+#include <StringList.h>
+
+#include "BaseJob.h"
+#include "LaunchDaemon.h"
+#include "Utility.h"
+
+
+class EventContainer : public Event {
+protected:
+
EventContainer(Event* parent,
+ const
BMessenger* target,
+ const
BMessage& args);
+
EventContainer(BaseJob* owner,
+ const
BMessenger& target);
+
+public:
+ void AddEvent(Event* event);
+ BObjectList<Event>& Events();
+
+ const BMessenger& Target() const;
+
+ virtual status_t Register(EventRegistrator&
registrator) const;
+ virtual void Unregister(EventRegistrator&
registrator) const;
+
+ virtual void Trigger();
+
+ virtual BaseJob* Owner() const;
+ virtual void SetOwner(BaseJob* owner);
+
+protected:
+ void ToString(BString&
string) const;
+
+protected:
+ BaseJob* fOwner;
+ BMessenger fTarget;
+ BObjectList<Event> fEvents;
+};
+
+
+class OrEvent : public EventContainer {
+public:
+ OrEvent(Event*
parent, const BMessenger* target,
+ const
BMessage& args);
+
OrEvent(BaseJob* owner,
+ const
BMessenger& target);
+
+ virtual BString ToString() const;
+};
+
+
+class DemandEvent : public Event {
+public:
+
DemandEvent(Event* parent);
+
+ virtual status_t Register(EventRegistrator&
registrator) const;
+ virtual void Unregister(EventRegistrator&
registrator) const;
+
+ virtual BString ToString() const;
+};
+
+
+class FileCreatedEvent : public Event {
+public:
+
FileCreatedEvent(Event* parent,
+ const
BMessage& args);
+
+ virtual status_t Register(EventRegistrator&
registrator) const;
+ virtual void Unregister(EventRegistrator&
registrator) const;
+
+ virtual BString ToString() const;
+
+private:
+ BPath fPath;
+};
+
+
+static Event*
+create_event(Event* parent, const char* name, const BMessenger* target,
+ const BMessage& args)
+{
+ if (strcmp(name, "or") == 0)
+ return new OrEvent(parent, target, args);
+
+ if (strcmp(name, "demand") == 0)
+ return new DemandEvent(parent);
+ if (strcmp(name, "file_created") == 0)
+ return new FileCreatedEvent(parent, args);
+
+ return NULL;
+}
+
+
+// #pragma mark -
+
+
+Event::Event(Event* parent)
+ :
+ fParent(parent)
+{
+}
+
+
+Event::~Event()
+{
+}
+
+
+bool
+Event::Triggered() const
+{
+ return fTriggered;
+}
+
+
+void
+Event::Trigger()
+{
+ fTriggered = true;
+ if (fParent != NULL)
+ fParent->Trigger();
+}
+
+
+BaseJob*
+Event::Owner() const
+{
+ if (fParent != NULL)
+ return fParent->Owner();
+
+ return NULL;
+}
+
+
+void
+Event::SetOwner(BaseJob* owner)
+{
+ if (fParent != NULL)
+ fParent->SetOwner(owner);
+}
+
+
+Event*
+Event::Parent() const
+{
+ return fParent;
+}
+
+
+// #pragma mark -
+
+
+EventContainer::EventContainer(Event* parent, const BMessenger* target,
+ const BMessage& args)
+ :
+ Event(parent),
+ fEvents(5, true)
+{
+ if (target != NULL)
+ fTarget = *target;
+
+ char* name;
+ type_code type;
+ int32 count;
+ for (int32 index = 0; args.GetInfo(B_MESSAGE_TYPE, index, &name, &type,
+ &count) == B_OK; index++) {
+ BMessage message;
+ for (int32 messageIndex = 0; args.FindMessage(name,
messageIndex,
+ &message) == B_OK; messageIndex++) {
+ AddEvent(create_event(this, name, target, message));
+ }
+ }
+}
+
+
+EventContainer::EventContainer(BaseJob* owner, const BMessenger& target)
+ :
+ Event(NULL),
+ fOwner(owner),
+ fTarget(target),
+ fEvents(5, true)
+{
+}
+
+
+void
+EventContainer::AddEvent(Event* event)
+{
+ if (event != NULL)
+ fEvents.AddItem(event);
+}
+
+
+BObjectList<Event>&
+EventContainer::Events()
+{
+ return fEvents;
+}
+
+
+const BMessenger&
+EventContainer::Target() const
+{
+ return fTarget;
+}
+
+
+status_t
+EventContainer::Register(EventRegistrator& registrator) const
+{
+ int32 count = fEvents.CountItems();
+ for (int32 index = 0; index < count; index++) {
+ Event* event = fEvents.ItemAt(index);
+ status_t status = event->Register(registrator);
+ if (status != B_OK)
+ return status;
+ }
+
+ return B_OK;
+}
+
+
+void
+EventContainer::Unregister(EventRegistrator& registrator) const
+{
+ int32 count = fEvents.CountItems();
+ for (int32 index = 0; index < count; index++) {
+ Event* event = fEvents.ItemAt(index);
+ event->Unregister(registrator);
+ }
+}
+
+
+void
+EventContainer::Trigger()
+{
+ Event::Trigger();
+
+ if (Parent() == NULL && Owner() != NULL) {
+ BMessage message(kMsgEventTriggered);
+ message.AddString("owner", Owner()->Name());
+ fTarget.SendMessage(&message);
+ }
+}
+
+
+BaseJob*
+EventContainer::Owner() const
+{
+ return fOwner;
+}
+
+
+void
+EventContainer::SetOwner(BaseJob* owner)
+{
+ Event::SetOwner(owner);
+ fOwner = owner;
+}
+
+
+void
+EventContainer::ToString(BString& string) const
+{
+ string += "[";
+
+ for (int32 index = 0; index < fEvents.CountItems(); index++) {
+ if (index != 0)
+ string += ", ";
+ string += fEvents.ItemAt(index)->ToString();
+ }
+ string += "]";
+}
+
+
+// #pragma mark - or
+
+
+OrEvent::OrEvent(Event* parent, const BMessenger* target, const BMessage& args)
+ :
+ EventContainer(parent, target, args)
+{
+}
+
+
+OrEvent::OrEvent(BaseJob* owner, const BMessenger& target)
+ :
+ EventContainer(owner, target)
+{
+}
+
+
+BString
+OrEvent::ToString() const
+{
+ BString string = "or ";
+ EventContainer::ToString(string);
+ return string;
+}
+
+
+// #pragma mark - demand
+
+
+DemandEvent::DemandEvent(Event* parent)
+ :
+ Event(parent)
+{
+}
+
+
+status_t
+DemandEvent::Register(EventRegistrator& registrator) const
+{
+ return B_OK;
+}
+
+
+void
+DemandEvent::Unregister(EventRegistrator& registrator) const
+{
+}
+
+
+BString
+DemandEvent::ToString() const
+{
+ return "event";
+}
+
+
+// #pragma mark - file_created
+
+
+FileCreatedEvent::FileCreatedEvent(Event* parent, const BMessage& args)
+ :
+ Event(parent)
+{
+ fPath.SetTo(args.GetString("args", NULL));
+}
+
+
+status_t
+FileCreatedEvent::Register(EventRegistrator& registrator) const
+{
+ return B_ERROR;
+}
+
+
+void
+FileCreatedEvent::Unregister(EventRegistrator& registrator) const
+{
+}
+
+
+BString
+FileCreatedEvent::ToString() const
+{
+ BString string = "file_created ";
+ string << fPath.Path();
+ return string;
+}
+
+
+// #pragma mark -
+
+
+/*static*/ Event*
+Events::FromMessage(const BMessenger& target, const BMessage& message)
+{
+ return create_event(NULL, "or", &target, message);
+}
+
+
+/*static*/ Event*
+Events::AddOnDemand(Event* event)
+{
+ OrEvent* or = dynamic_cast<OrEvent*>(event);
+ if (or == NULL) {
+ EventContainer* container =
dynamic_cast<EventContainer*>(event);
+ if (container == NULL)
+ return NULL;
+
+ or = new OrEvent(container->Owner(), container->Target());
+ }
+ if (or != event && event != NULL)
+ or->AddEvent(event);
+
+ or->AddEvent(new DemandEvent(or));
+ return or;
+}
+
+
+/*static*/ bool
+Events::TriggerDemand(Event* event)
+{
+ if (event == NULL)
+ return false;
+
+ if (EventContainer* container = dynamic_cast<EventContainer*>(event)) {
+ for (int32 index = 0; index < container->Events().CountItems();
+ index++) {
+ Event* event = container->Events().ItemAt(index);
+ if (dynamic_cast<DemandEvent*>(event) != NULL) {
+ event->Trigger();
+ return true;
+ }
+ if (dynamic_cast<EventContainer*>(event) != NULL) {
+ if (TriggerDemand(event))
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/servers/launch/Events.h b/src/servers/launch/Events.h
new file mode 100644
index 0000000..2552cb3
--- /dev/null
+++ b/src/servers/launch/Events.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef EVENTS_H
+#define EVENTS_H
+
+
+#include <Messenger.h>
+#include <String.h>
+
+
+class BaseJob;
+class Event;
+
+
+class EventRegistrator {
+public:
+ virtual status_t RegisterEvent(Event* event) = 0;
+ virtual void UnregisterEvent(Event* event) =
0;
+};
+
+
+class Event {
+public:
+ Event(Event*
parent);
+ virtual ~Event();
+
+ virtual status_t Register(
+
EventRegistrator& registrator) const = 0;
+ virtual void Unregister(
+
EventRegistrator& registrator) const = 0;
+
+ bool Triggered() const;
+ virtual void Trigger();
+
+ virtual BaseJob* Owner() const;
+ virtual void SetOwner(BaseJob* owner);
+
+ Event* Parent() const;
+
+ virtual BString ToString() const = 0;
+
+private:
+ Event* fParent;
+ bool fTriggered;
+};
+
+
+class Events {
+public:
+ static Event* FromMessage(const BMessenger& target,
+ const BMessage&
message);
+ static Event* AddOnDemand(Event* event);
+ static bool TriggerDemand(Event* event);
+};
+
+
+#endif // EVENTS_H
diff --git a/src/servers/launch/Jamfile b/src/servers/launch/Jamfile
index fe663a0..068a71c 100644
--- a/src/servers/launch/Jamfile
+++ b/src/servers/launch/Jamfile
@@ -11,6 +11,7 @@ Server launch_daemon

BaseJob.cpp
Conditions.cpp
+ Events.cpp
Job.cpp
SettingsParser.cpp
Target.cpp
diff --git a/src/servers/launch/LaunchDaemon.cpp
b/src/servers/launch/LaunchDaemon.cpp
index 63a6245..976a8e8 100644
--- a/src/servers/launch/LaunchDaemon.cpp
+++ b/src/servers/launch/LaunchDaemon.cpp
@@ -4,6 +4,8 @@
*/


+#include "LaunchDaemon.h"
+
#include <map>
#include <set>

@@ -31,6 +33,7 @@
#include "multiuser_utils.h"

#include "Conditions.h"
+#include "Events.h"
#include "InitRealTimeClockJob.h"
#include "InitSharedMemoryDirectoryJob.h"
#include "InitTemporaryDirectoryJob.h"
@@ -102,10 +105,13 @@ private:

BMessage& message);
void _InitJobs();
void _LaunchJobs(Target*
target);
+ void _TriggerJob(Job* job);
void _AddLaunchJob(Job* job);
void _AddTarget(Target*
target);
void _SetCondition(BaseJob*
job,
const
BMessage& message);
+ void _SetEvent(BaseJob* job,
+ const
BMessage& message);
void
_SetEnvironment(BaseJob* job,
const
BMessage& message);

@@ -261,7 +267,7 @@ LaunchDaemon::ReadyToRun()
_InitJobs();
_LaunchJobs(NULL);

- // Launch run targets
+ // Launch run targets (ignores events)
for (int32 index = 0; index < fRunTargets.CountStrings(); index++) {
Target* target = FindTarget(fRunTargets.StringAt(index));
if (target != NULL)
@@ -314,7 +320,7 @@ LaunchDaemon::MessageReceived(BMessage* message)

iterator->second.GetInt32("port", -1));
}

- _AddLaunchJob(job);
+ _TriggerJob(job);
}
message->SendReply(&reply);
break;
@@ -419,6 +425,28 @@ LaunchDaemon::MessageReceived(BMessage* message)
break;
}

+ case kMsgEventTriggered:
+ {
+ // An internal event has been triggered.
+ // Check if its job can be launched now.
+ const char* name = message->GetString("owner");
+ if (name == NULL)
+ break;
+
+ Job* job = FindJob(name);
+ if (job != NULL && job->EventHasTriggered()) {
+ _AddLaunchJob(job);
+ break;
+ }
+
+ Target* target = FindTarget(name);
+ if (target != NULL && target->EventHasTriggered()) {
+ _LaunchJobs(target);
+ break;
+ }
+ break;
+ }
+
default:
BServer::MessageReceived(message);
break;
@@ -542,6 +570,7 @@ LaunchDaemon::_AddTargets(BMessage& message)
}

_SetCondition(target, targetMessage);
+ _SetEvent(target, targetMessage);
_SetEnvironment(target, targetMessage);
_AddJobs(target, targetMessage);
}
@@ -620,6 +649,7 @@ LaunchDaemon::_AddJob(Target* target, bool service,
BMessage& message)
job->SetCreateDefaultPort(!message.GetBool("legacy", !service));

_SetCondition(job, message);
+ _SetEvent(job, message);
_SetEnvironment(job, message);

BMessage portMessage;
@@ -683,6 +713,9 @@ LaunchDaemon::_InitJobs()
}


+/*! Adds all jobs for the specified target (may be \c NULL) to the launch
+ queue, except those that are triggered by events.
+*/
void
LaunchDaemon::_LaunchJobs(Target* target)
{
@@ -692,9 +725,27 @@ LaunchDaemon::_LaunchJobs(Target* target)
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();
iterator++) {
Job* job = iterator->second;
- if (job->Target() == target)
- _AddLaunchJob(job);
+ if (job->Target() == target && job->Event() == NULL)
+ _TriggerJob(job);
+ }
+}
+
+
+void
+LaunchDaemon::_TriggerJob(Job* job)
+{
+ if (job == NULL)
+ return;
+
+ int32 count = job->Requirements().CountStrings();
+ for (int32 index = 0; index < count; index++) {
+ Job* requirement = FindJob(job->Requirements().StringAt(index));
+ if (requirement != NULL)
+ _TriggerJob(requirement);
}
+
+ if (!Events::TriggerDemand(job->Event()))
+ _AddLaunchJob(job);
}


@@ -739,6 +790,28 @@ LaunchDaemon::_SetCondition(BaseJob* job, const BMessage&
message)


void
+LaunchDaemon::_SetEvent(BaseJob* job, const BMessage& message)
+{
+ Event* event = job->Event();
+ bool updated = false;
+
+ BMessage events;
+ if (message.FindMessage("on", &events) == B_OK) {
+ event = Events::FromMessage(this, events);
+ updated = true;
+ }
+
+ if (message.GetBool("on_demand")) {
+ event = Events::AddOnDemand(event);
+ updated = true;
+ }
+
+ if (updated)
+ job->SetEvent(event);
+}
+
+
+void
LaunchDaemon::_SetEnvironment(BaseJob* job, const BMessage& message)
{
BMessage environmentMessage;
diff --git a/src/servers/launch/LaunchDaemon.h
b/src/servers/launch/LaunchDaemon.h
new file mode 100644
index 0000000..ace8a9f
--- /dev/null
+++ b/src/servers/launch/LaunchDaemon.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef LAUNCH_DAEMON_H
+#define LAUNCH_DAEMON_H
+
+
+#include <SupportDefs.h>
+
+
+static const uint32 kMsgEventTriggered = 'ldet';
+
+
+#endif // LAUNCH_DAEMON_H
diff --git a/src/servers/launch/SettingsParser.cpp
b/src/servers/launch/SettingsParser.cpp
index fcc631e..58f68d4 100644
--- a/src/servers/launch/SettingsParser.cpp
+++ b/src/servers/launch/SettingsParser.cpp
@@ -156,6 +156,7 @@ const static settings_template kJobTemplate[] = {
{B_MESSAGE_TYPE, "on", kEventTemplate},
{B_MESSAGE_TYPE, "if", kConditionTemplate},
{B_BOOL_TYPE, "no_safemode", NULL},
+ {B_BOOL_TYPE, "on_demand", NULL},
{B_MESSAGE_TYPE, "env", kEnvTemplate},
{0, NULL, NULL}
};


Other related posts:

  • » [haiku-commits] BRANCH axeld-github.launch_daemon [8541379b99dc] src/servers/launch - axeld-github . launch_daemon