launch_daemon: Added basic logging facility
* The daemon now stores many events in am internal log. * You can use "launch_roster log" to retrieve it.
This commit is contained in:
parent
6d7b8a3088
commit
a77aa747ea
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2017, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2015-2018, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
|
@ -45,6 +45,7 @@ enum {
|
|||
B_GET_LAUNCH_JOBS = 'lngj',
|
||||
B_GET_LAUNCH_TARGET_INFO = 'lntI',
|
||||
B_GET_LAUNCH_JOB_INFO = 'lnjI',
|
||||
B_GET_LAUNCH_LOG = 'lnLL',
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2015-2018 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _LAUNCH_ROSTER_H
|
||||
|
@ -56,6 +56,9 @@ public:
|
|||
status_t GetJobs(const char* target, BStringList& jobs);
|
||||
status_t GetJobInfo(const char* name, BMessage& info);
|
||||
|
||||
status_t GetLog(BMessage& info);
|
||||
status_t GetLog(const BMessage& filter, BMessage& info);
|
||||
|
||||
class Private;
|
||||
|
||||
private:
|
||||
|
@ -70,6 +73,7 @@ private:
|
|||
uint32 flags = 0);
|
||||
status_t _GetInfo(uint32 what, const char* name,
|
||||
BMessage& info);
|
||||
status_t _GetLog(const BMessage* filter, BMessage& info);
|
||||
|
||||
private:
|
||||
BMessenger fMessenger;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2016, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2015-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
@ -10,11 +10,12 @@
|
|||
#include <LaunchRoster.h>
|
||||
#include <StringList.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
static struct option const kLongOptions[] = {
|
||||
|
@ -23,6 +24,16 @@ static struct option const kLongOptions[] = {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
static struct option const kLogLongOptions[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"raw", no_argument, 0, 'r'},
|
||||
{"user", no_argument, 0, 'u'},
|
||||
{"system", no_argument, 0, 's'},
|
||||
{"event", required_argument, 0, 'e'},
|
||||
{"limit", required_argument, 0, 'l'},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
extern const char *__progname;
|
||||
static const char *kProgramName = __progname;
|
||||
|
||||
|
@ -61,6 +72,127 @@ list_targets(bool verbose)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
print_log(const BMessage& log)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
bigtime_t runtime = system_time();
|
||||
|
||||
for (int32 index = 0;; index++) {
|
||||
BMessage item;
|
||||
if (log.FindMessage("item", index, &item) != B_OK)
|
||||
break;
|
||||
|
||||
uint64 when;
|
||||
const char* message;
|
||||
if (item.FindUInt64("when", &when) != B_OK
|
||||
|| item.FindString("message", &message) != B_OK)
|
||||
break;
|
||||
|
||||
time_t at = now - (runtime - when) / 1000000l;
|
||||
struct tm tm;
|
||||
localtime_r(&at, &tm);
|
||||
char label[256];
|
||||
strftime(label, sizeof(label), "%F %X", &tm);
|
||||
printf("%s %s\n", label, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
log_usage(int status)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s log [-rusel] [<job-name>]\n"
|
||||
"Where the following options are allowed:\n"
|
||||
" -u --user List only user log entries\n"
|
||||
" -s --system List only system log entries\n"
|
||||
" -e --event Filter by event name (partial names accepted)\n"
|
||||
" -l --limit <n> Limit output to <n> events\n"
|
||||
"<job-name>, if given, filters the jobs by name.\n",
|
||||
kProgramName);
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_log(int argCount, char** args)
|
||||
{
|
||||
bool raw = false;
|
||||
bool userOnly = false;
|
||||
bool systemOnly = false;
|
||||
int32 limit = 0;
|
||||
const char* event = NULL;
|
||||
const char* job = NULL;
|
||||
|
||||
optind = 0;
|
||||
int c;
|
||||
while ((c = getopt_long(argCount, args, "hruse:l:", kLogLongOptions, NULL))
|
||||
!= -1) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
break;
|
||||
case 'h':
|
||||
log_usage(0);
|
||||
break;
|
||||
case 'r':
|
||||
raw = true;
|
||||
break;
|
||||
case 'u':
|
||||
userOnly = true;
|
||||
break;
|
||||
case 's':
|
||||
systemOnly = true;
|
||||
break;
|
||||
case 'e':
|
||||
event = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
limit = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argCount - optind >= 1)
|
||||
job = args[optind];
|
||||
|
||||
BLaunchRoster roster;
|
||||
BMessage filter;
|
||||
if (userOnly)
|
||||
filter.AddBool("userOnly", true);
|
||||
if (systemOnly)
|
||||
filter.AddBool("systemOnly", true);
|
||||
if (event != NULL)
|
||||
filter.AddString("event", event);
|
||||
if (job != NULL)
|
||||
filter.AddString("job", job);
|
||||
if (limit != 0)
|
||||
filter.AddInt32("limit", limit);
|
||||
|
||||
BMessage info;
|
||||
status_t status = roster.GetLog(filter, info);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Could not get log: %s\n", kProgramName,
|
||||
strerror(status));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (raw) {
|
||||
info.PrintToStream();
|
||||
return;
|
||||
}
|
||||
|
||||
print_log(info);
|
||||
|
||||
BMessage user;
|
||||
if (info.FindMessage("user", &user) == B_OK) {
|
||||
if (user.HasMessage("item"))
|
||||
puts("User log:");
|
||||
print_log(user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_info(const char* name)
|
||||
{
|
||||
|
@ -165,7 +297,7 @@ main(int argc, char** argv)
|
|||
bool verbose = false;
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "hv", kLongOptions, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "+hv", kLongOptions, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
break;
|
||||
|
@ -188,6 +320,8 @@ main(int argc, char** argv)
|
|||
list_jobs(verbose);
|
||||
} else if (strcmp(command, "list-targets") == 0) {
|
||||
list_targets(verbose);
|
||||
} else if (strcmp(command, "log") == 0) {
|
||||
get_log(argc - optind, &argv[optind]);
|
||||
} else if (argc == optind + 1) {
|
||||
// For convenience (the "info" command can be omitted)
|
||||
get_info(command);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2015-2017 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
|
@ -338,6 +338,20 @@ BLaunchRoster::GetJobInfo(const char* name, BMessage& info)
|
|||
}
|
||||
|
||||
|
||||
status_t
|
||||
BLaunchRoster::GetLog(BMessage& info)
|
||||
{
|
||||
return _GetLog(NULL, info);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BLaunchRoster::GetLog(const BMessage& filter, BMessage& info)
|
||||
{
|
||||
return _GetLog(&filter, info);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BLaunchRoster::_InitMessenger()
|
||||
{
|
||||
|
@ -414,3 +428,17 @@ BLaunchRoster::_GetInfo(uint32 what, const char* name, BMessage& info)
|
|||
|
||||
return _SendRequest(request, info);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BLaunchRoster::_GetLog(const BMessage* filter, BMessage& info)
|
||||
{
|
||||
BMessage request(B_GET_LAUNCH_LOG);
|
||||
status_t status = request.AddInt32("user", getuid());
|
||||
if (status == B_OK && filter != NULL)
|
||||
status = request.AddMessage("filter", filter);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return _SendRequest(request, info);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2015-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
|||
virtual status_t Register(EventRegistrator& registrator);
|
||||
virtual void Unregister(EventRegistrator& registrator);
|
||||
|
||||
virtual void Trigger();
|
||||
virtual void Trigger(Event* origin);
|
||||
|
||||
virtual BaseJob* Owner() const;
|
||||
virtual void SetOwner(BaseJob* owner);
|
||||
|
@ -205,11 +205,11 @@ Event::Triggered() const
|
|||
|
||||
|
||||
void
|
||||
Event::Trigger()
|
||||
Event::Trigger(Event* origin)
|
||||
{
|
||||
fTriggered = true;
|
||||
if (fParent != NULL)
|
||||
fParent->Trigger();
|
||||
fParent->Trigger(origin);
|
||||
}
|
||||
|
||||
|
||||
|
@ -336,12 +336,13 @@ EventContainer::Unregister(EventRegistrator& registrator)
|
|||
|
||||
|
||||
void
|
||||
EventContainer::Trigger()
|
||||
EventContainer::Trigger(Event* origin)
|
||||
{
|
||||
Event::Trigger();
|
||||
Event::Trigger(origin);
|
||||
|
||||
if (Parent() == NULL && Owner() != NULL) {
|
||||
BMessage message(kMsgEventTriggered);
|
||||
message.AddPointer("event", origin);
|
||||
message.AddString("owner", Owner()->Name());
|
||||
fTarget.SendMessage(&message);
|
||||
}
|
||||
|
@ -620,7 +621,7 @@ VolumeMountedEvent::ToString() const
|
|||
void
|
||||
VolumeMountedEvent::VolumeMounted(dev_t device)
|
||||
{
|
||||
Trigger();
|
||||
Trigger(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -667,7 +668,7 @@ void
|
|||
NetworkAvailableEvent::NetworkAvailabilityChanged(bool available)
|
||||
{
|
||||
if (available)
|
||||
Trigger();
|
||||
Trigger(this);
|
||||
else
|
||||
ResetSticky();
|
||||
}
|
||||
|
@ -737,7 +738,7 @@ Events::TriggerExternalEvent(Event* event, const char* name)
|
|||
Event* event = container->Events().ItemAt(index);
|
||||
if (ExternalEvent* external = dynamic_cast<ExternalEvent*>(event)) {
|
||||
if (external->Name() == name) {
|
||||
external->Trigger();
|
||||
external->Trigger(container);
|
||||
return;
|
||||
}
|
||||
} else if (dynamic_cast<EventContainer*>(event) != NULL) {
|
||||
|
@ -794,7 +795,7 @@ Events::TriggerDemand(Event* event, bool testOnly)
|
|||
if (testOnly)
|
||||
return true;
|
||||
|
||||
childEvent->Trigger();
|
||||
childEvent->Trigger(childEvent);
|
||||
break;
|
||||
}
|
||||
if (dynamic_cast<EventContainer*>(childEvent) != NULL) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2015-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef EVENTS_H
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
EventRegistrator& registrator) = 0;
|
||||
|
||||
bool Triggered() const;
|
||||
virtual void Trigger();
|
||||
virtual void Trigger(Event* origin);
|
||||
virtual void ResetTrigger();
|
||||
|
||||
virtual BaseJob* Owner() const;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SubDir HAIKU_TOP src servers launch ;
|
||||
|
||||
UsePrivateHeaders app libroot shared storage support ;
|
||||
UsePrivateHeaders app kernel libroot shared storage support ;
|
||||
UsePrivateSystemHeaders ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src bin multiuser ] ;
|
||||
|
@ -13,6 +13,7 @@ Server launch_daemon
|
|||
Conditions.cpp
|
||||
Events.cpp
|
||||
Job.cpp
|
||||
Log.cpp
|
||||
NetworkWatcher.cpp
|
||||
SettingsParser.cpp
|
||||
Target.cpp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2016, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2015-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
@ -34,7 +34,8 @@ Job::Job(const char* name)
|
|||
fToken((uint32)B_PREFERRED_TOKEN),
|
||||
fLaunchStatus(B_NO_INIT),
|
||||
fTarget(NULL),
|
||||
fPendingLaunchDataReplies(0, false)
|
||||
fPendingLaunchDataReplies(0, false),
|
||||
fTeamListener(NULL)
|
||||
{
|
||||
mutex_init(&fLaunchStatusLock, "launch status lock");
|
||||
}
|
||||
|
@ -694,7 +695,7 @@ Job::_Launch(const char* signature, entry_ref* ref, int argCount,
|
|||
resume_thread(mainThread);
|
||||
|
||||
if (fTeamListener != NULL)
|
||||
fTeamListener->TeamLaunched(this);
|
||||
fTeamListener->TeamLaunched(this, result);
|
||||
} else
|
||||
kill_thread(mainThread);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2015-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef JOB_H
|
||||
|
@ -34,7 +34,7 @@ typedef std::map<BString, BMessage> PortMap;
|
|||
|
||||
class TeamListener {
|
||||
public:
|
||||
virtual void TeamLaunched(Job* job) = 0;
|
||||
virtual void TeamLaunched(Job* job, status_t status) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2017, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2015-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
|||
#include "InitSharedMemoryDirectoryJob.h"
|
||||
#include "InitTemporaryDirectoryJob.h"
|
||||
#include "Job.h"
|
||||
#include "Log.h"
|
||||
#include "SettingsParser.h"
|
||||
#include "Target.h"
|
||||
#include "Utility.h"
|
||||
|
@ -147,7 +148,7 @@ public:
|
|||
const char* name);
|
||||
|
||||
// TeamListener
|
||||
virtual void TeamListener(Job* job);
|
||||
virtual void TeamLaunched(Job* job, status_t status);
|
||||
|
||||
virtual void ReadyToRun();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
@ -170,6 +171,7 @@ private:
|
|||
void _HandleGetLaunchTargetInfo(BMessage* message);
|
||||
void _HandleGetLaunchJobs(BMessage* message);
|
||||
void _HandleGetLaunchJobInfo(BMessage* message);
|
||||
void _HandleGetLaunchLog(BMessage* message);
|
||||
uid_t _GetUserID(BMessage* message);
|
||||
|
||||
void _ReadPaths(const BStringList& paths);
|
||||
|
@ -222,6 +224,7 @@ private:
|
|||
void _AddInitJob(BJob* job);
|
||||
|
||||
private:
|
||||
Log fLog;
|
||||
JobMap fJobs;
|
||||
TargetMap fTargets;
|
||||
BStringList fRunTargets;
|
||||
|
@ -425,8 +428,10 @@ LaunchDaemon::UnregisterExternalEvent(Event* event, const char* name)
|
|||
|
||||
|
||||
void
|
||||
LaunchDaemon::RegisterTeam(Job* job)
|
||||
LaunchDaemon::TeamLaunched(Job* job, status_t status)
|
||||
{
|
||||
fLog.JobLaunched(job, status);
|
||||
|
||||
MutexLocker locker(fTeamsLock);
|
||||
fTeams.insert(std::make_pair(job->Team(), job));
|
||||
}
|
||||
|
@ -514,6 +519,11 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||
if (found != fTeams.end()) {
|
||||
Job* job = found->second;
|
||||
TRACE("Job %s ended!\n", job->Name());
|
||||
|
||||
// Get the exit status, and pass it on to the log
|
||||
status_t exitStatus = B_OK;
|
||||
wait_for_thread(team, &exitStatus);
|
||||
fLog.JobTerminated(job, exitStatus);
|
||||
job->TeamDeleted();
|
||||
|
||||
if (job->IsService()) {
|
||||
|
@ -613,22 +623,30 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||
_HandleGetLaunchJobInfo(message);
|
||||
break;
|
||||
|
||||
case B_GET_LAUNCH_LOG:
|
||||
_HandleGetLaunchLog(message);
|
||||
break;
|
||||
|
||||
case kMsgEventTriggered:
|
||||
{
|
||||
// An internal event has been triggered.
|
||||
// Check if its job can be launched now.
|
||||
// Check if its job(s) can be launched now.
|
||||
const char* name = message->GetString("owner");
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
Event* event = (Event*)message->GetPointer("event");
|
||||
|
||||
Job* job = FindJob(name);
|
||||
if (job != NULL) {
|
||||
fLog.EventTriggered(job, event);
|
||||
_LaunchJob(job);
|
||||
break;
|
||||
}
|
||||
|
||||
Target* target = FindTarget(name);
|
||||
if (target != NULL) {
|
||||
fLog.EventTriggered(target, event);
|
||||
_LaunchJobs(target);
|
||||
break;
|
||||
}
|
||||
|
@ -785,7 +803,9 @@ LaunchDaemon::_HandleStopLaunchTarget(BMessage* message)
|
|||
if (message->FindMessage("data", &data) == B_OK)
|
||||
target->AddData(data.GetString("name"), data);
|
||||
|
||||
_StopJobs(target, message->GetBool("force"));
|
||||
bool force = message->GetBool("force");
|
||||
fLog.JobStopped(target, force);
|
||||
_StopJobs(target, force);
|
||||
|
||||
BMessage reply((uint32)B_OK);
|
||||
message->SendReply(&reply);
|
||||
|
@ -848,6 +868,7 @@ LaunchDaemon::_HandleEnableLaunchJob(BMessage* message)
|
|||
}
|
||||
|
||||
job->SetEnabled(enable);
|
||||
fLog.JobEnabled(job, enable);
|
||||
|
||||
BMessage reply((uint32)B_OK);
|
||||
message->SendReply(&reply);
|
||||
|
@ -877,7 +898,9 @@ LaunchDaemon::_HandleStopLaunchJob(BMessage* message)
|
|||
return;
|
||||
}
|
||||
|
||||
_StopJob(job, message->GetBool("force"));
|
||||
bool force = message->GetBool("force");
|
||||
fLog.JobStopped(job, force);
|
||||
_StopJob(job, force);
|
||||
|
||||
BMessage reply((uint32)B_OK);
|
||||
message->SendReply(&reply);
|
||||
|
@ -965,6 +988,8 @@ LaunchDaemon::_HandleRegisterLaunchEvent(BMessage* message)
|
|||
eventName.Prepend(ownerName);
|
||||
fEvents.insert(std::make_pair(eventName, event));
|
||||
_ResolveExternalEvents(event, eventName);
|
||||
|
||||
fLog.ExternalEventRegistered(name);
|
||||
} else
|
||||
status = B_NO_MEMORY;
|
||||
} else
|
||||
|
@ -1002,6 +1027,8 @@ LaunchDaemon::_HandleUnregisterLaunchEvent(BMessage* message)
|
|||
eventName.Prepend("/");
|
||||
eventName.Prepend(ownerName);
|
||||
fEvents.erase(eventName);
|
||||
|
||||
fLog.ExternalEventRegistered(name);
|
||||
} else
|
||||
status = B_BAD_VALUE;
|
||||
|
||||
|
@ -1028,6 +1055,8 @@ LaunchDaemon::_HandleNotifyLaunchEvent(BMessage* message)
|
|||
|
||||
ExternalEventSource* event = _FindEvent(ownerName, name);
|
||||
if (event != NULL) {
|
||||
fLog.ExternalEventTriggered(name);
|
||||
|
||||
// Evaluate all of its jobs
|
||||
int32 count = event->CountListeners();
|
||||
for (int32 index = 0; index < count; index++) {
|
||||
|
@ -1223,6 +1252,90 @@ LaunchDaemon::_HandleGetLaunchJobInfo(BMessage* message)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchDaemon::_HandleGetLaunchLog(BMessage* message)
|
||||
{
|
||||
uid_t user = _GetUserID(message);
|
||||
if (user < 0)
|
||||
return;
|
||||
|
||||
BMessage filter;
|
||||
BString jobName;
|
||||
const char* event = NULL;
|
||||
int32 limit = 0;
|
||||
bool systemOnly = false;
|
||||
bool userOnly = false;
|
||||
if (message->FindMessage("filter", &filter) == B_OK) {
|
||||
limit = filter.GetInt32("limit", 0);
|
||||
jobName = filter.GetString("job");
|
||||
jobName.ToLower();
|
||||
event = filter.GetString("event");
|
||||
systemOnly = filter.GetBool("systemOnly");
|
||||
userOnly = filter.GetBool("userOnly");
|
||||
}
|
||||
|
||||
BMessage info((uint32)B_OK);
|
||||
int32 count = 0;
|
||||
|
||||
if (user == 0 || !userOnly) {
|
||||
LogItemList::Iterator iterator = fLog.Iterator();
|
||||
while (iterator.HasNext()) {
|
||||
LogItem* item = iterator.Next();
|
||||
if (!item->Matches(jobName.IsEmpty() ? NULL : jobName.String(),
|
||||
event)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BMessage itemMessage;
|
||||
itemMessage.AddUInt64("when", item->When());
|
||||
itemMessage.AddInt32("type", (int32)item->Type());
|
||||
itemMessage.AddString("message", item->Message());
|
||||
|
||||
BMessage parameter;
|
||||
item->GetParameter(parameter);
|
||||
itemMessage.AddMessage("parameter", ¶meter);
|
||||
|
||||
info.AddMessage("item", &itemMessage);
|
||||
|
||||
// limit == 0 means no limit
|
||||
if (++count == limit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the list from the user daemon, and merge it into our reply
|
||||
Session* session = FindSession(user);
|
||||
if (session != NULL && !systemOnly) {
|
||||
if (limit != 0) {
|
||||
// Update limit for user daemon
|
||||
limit -= count;
|
||||
if (limit <= 0) {
|
||||
message->SendReply(&info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BMessage reply;
|
||||
|
||||
BMessage request(B_GET_LAUNCH_LOG);
|
||||
status_t status = request.AddInt32("user", 0);
|
||||
if (status == B_OK && (limit != 0 || !jobName.IsEmpty()
|
||||
|| event != NULL)) {
|
||||
// Forward filter specification when needed
|
||||
status = filter.SetInt32("limit", limit);
|
||||
if (status == B_OK)
|
||||
status = request.AddMessage("filter", &filter);
|
||||
}
|
||||
if (status == B_OK)
|
||||
status = session->Daemon().SendMessage(&request, &reply);
|
||||
if (status == B_OK)
|
||||
info.AddMessage("user", &reply);
|
||||
}
|
||||
|
||||
message->SendReply(&info);
|
||||
}
|
||||
|
||||
|
||||
uid_t
|
||||
LaunchDaemon::_GetUserID(BMessage* message)
|
||||
{
|
||||
|
@ -1419,8 +1532,10 @@ LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
|
|||
} else
|
||||
TRACE(" amend job \"%s\"\n", name.String());
|
||||
|
||||
if (message.HasBool("disabled"))
|
||||
if (message.HasBool("disabled")) {
|
||||
job->SetEnabled(!message.GetBool("disabled", !job->IsEnabled()));
|
||||
fLog.JobEnabled(job, job->IsEnabled());
|
||||
}
|
||||
|
||||
if (message.HasBool("legacy"))
|
||||
job->SetCreateDefaultPort(!message.GetBool("legacy", !service));
|
||||
|
@ -1477,12 +1592,15 @@ LaunchDaemon::_InitJobs(Target* target)
|
|||
}
|
||||
}
|
||||
|
||||
if (status != B_OK) {
|
||||
if (status == B_OK) {
|
||||
fLog.JobInitialized(job);
|
||||
} else {
|
||||
if (status != B_NO_INIT) {
|
||||
// TODO: log error
|
||||
debug_printf("Init \"%s\" failed: %s\n", job->Name(),
|
||||
strerror(status));
|
||||
}
|
||||
fLog.JobIgnored(job, status);
|
||||
|
||||
// Remove jobs that won't be used later on
|
||||
fJobs.erase(remove);
|
||||
|
|
|
@ -0,0 +1,810 @@
|
|||
/*
|
||||
* Copyright 2017-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include "Events.h"
|
||||
#include "Job.h"
|
||||
|
||||
|
||||
const size_t kMaxItems = 10000;
|
||||
|
||||
|
||||
class AbstractJobLogItem : public LogItem {
|
||||
public:
|
||||
AbstractJobLogItem(BaseJob* job);
|
||||
virtual ~AbstractJobLogItem();
|
||||
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
virtual bool Matches(const char* jobName,
|
||||
const char* eventName);
|
||||
|
||||
protected:
|
||||
BaseJob* fJob;
|
||||
};
|
||||
|
||||
|
||||
class JobInitializedLogItem : public AbstractJobLogItem {
|
||||
public:
|
||||
JobInitializedLogItem(Job* job);
|
||||
virtual ~JobInitializedLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
};
|
||||
|
||||
|
||||
class JobIgnoredLogItem : public LogItem {
|
||||
public:
|
||||
JobIgnoredLogItem(Job* job, status_t error);
|
||||
virtual ~JobIgnoredLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
virtual bool Matches(const char* jobName,
|
||||
const char* eventName);
|
||||
|
||||
private:
|
||||
BString fJobName;
|
||||
status_t fError;
|
||||
};
|
||||
|
||||
|
||||
class JobLaunchedLogItem : public AbstractJobLogItem {
|
||||
public:
|
||||
JobLaunchedLogItem(Job* job, status_t status);
|
||||
virtual ~JobLaunchedLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
|
||||
private:
|
||||
status_t fStatus;
|
||||
};
|
||||
|
||||
|
||||
class JobTerminatedLogItem : public AbstractJobLogItem {
|
||||
public:
|
||||
JobTerminatedLogItem(Job* job, status_t status);
|
||||
virtual ~JobTerminatedLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
|
||||
private:
|
||||
status_t fStatus;
|
||||
};
|
||||
|
||||
|
||||
class JobEnabledLogItem : public AbstractJobLogItem {
|
||||
public:
|
||||
JobEnabledLogItem(Job* job, bool enabled);
|
||||
virtual ~JobEnabledLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
|
||||
private:
|
||||
bool fEnabled;
|
||||
};
|
||||
|
||||
|
||||
class JobStoppedLogItem : public AbstractJobLogItem {
|
||||
public:
|
||||
JobStoppedLogItem(BaseJob* job, bool force);
|
||||
virtual ~JobStoppedLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
|
||||
private:
|
||||
bool fForce;
|
||||
};
|
||||
|
||||
|
||||
class EventLogItem : public AbstractJobLogItem {
|
||||
public:
|
||||
EventLogItem(BaseJob* job, Event* event);
|
||||
virtual ~EventLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
virtual bool Matches(const char* jobName,
|
||||
const char* eventName);
|
||||
|
||||
private:
|
||||
Event* fEvent;
|
||||
};
|
||||
|
||||
|
||||
class AbstractExternalEventLogItem : public LogItem {
|
||||
public:
|
||||
AbstractExternalEventLogItem(const char* name);
|
||||
virtual ~AbstractExternalEventLogItem();
|
||||
|
||||
virtual status_t GetParameter(BMessage& parameter) const;
|
||||
virtual bool Matches(const char* jobName,
|
||||
const char* eventName);
|
||||
|
||||
protected:
|
||||
BString fEventName;
|
||||
};
|
||||
|
||||
|
||||
class ExternalEventLogItem : public AbstractExternalEventLogItem {
|
||||
public:
|
||||
ExternalEventLogItem(const char* name);
|
||||
virtual ~ExternalEventLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
};
|
||||
|
||||
|
||||
class ExternalEventRegisteredLogItem : public AbstractExternalEventLogItem {
|
||||
public:
|
||||
ExternalEventRegisteredLogItem(
|
||||
const char* name);
|
||||
virtual ~ExternalEventRegisteredLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
};
|
||||
|
||||
|
||||
class ExternalEventUnregisteredLogItem : public AbstractExternalEventLogItem {
|
||||
public:
|
||||
ExternalEventUnregisteredLogItem(
|
||||
const char* name);
|
||||
virtual ~ExternalEventUnregisteredLogItem();
|
||||
|
||||
virtual LogItemType Type() const;
|
||||
virtual status_t GetMessage(BString& target) const;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
LogItem::LogItem()
|
||||
:
|
||||
fWhen(system_time())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItem::~LogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
LogItem::Message() const
|
||||
{
|
||||
BString message;
|
||||
GetMessage(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Log
|
||||
|
||||
|
||||
Log::Log()
|
||||
:
|
||||
fCount(0)
|
||||
{
|
||||
mutex_init(&fLock, "log lock");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::Add(LogItem* item)
|
||||
{
|
||||
MutexLocker locker(fLock);
|
||||
if (fCount == kMaxItems)
|
||||
fItems.Remove(fItems.First());
|
||||
else
|
||||
fCount++;
|
||||
|
||||
fItems.Add(item);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::JobInitialized(Job* job)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) JobInitializedLogItem(job);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else
|
||||
debug_printf("Initialized job \"%s\"\n", job->Name());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::JobIgnored(Job* job, status_t status)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) JobIgnoredLogItem(job, status);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else {
|
||||
debug_printf("Ignored job \"%s\": %s\n", job->Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::JobLaunched(Job* job, status_t status)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) JobLaunchedLogItem(job, status);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else {
|
||||
debug_printf("Launched job \"%s\": %s\n", job->Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::JobTerminated(Job* job, status_t status)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) JobTerminatedLogItem(job, status);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else {
|
||||
debug_printf("Terminated job \"%s\": %s\n", job->Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::JobEnabled(Job* job, bool enabled)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) JobEnabledLogItem(job, enabled);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else
|
||||
debug_printf("Enabled job \"%s\": %d\n", job->Name(), enabled);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::JobStopped(BaseJob* job, bool force)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) JobStoppedLogItem(job, force);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else
|
||||
debug_printf("Stopped job \"%s\"\n", job->Name());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::EventTriggered(BaseJob* job, Event* event)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) EventLogItem(job, event);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else {
|
||||
debug_printf("Event triggered for \"%s\": %s\n", job->Name(),
|
||||
event->ToString().String());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::ExternalEventTriggered(const char* name)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) ExternalEventLogItem(name);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else
|
||||
debug_printf("External event triggered: %s\n", name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::ExternalEventRegistered(const char* name)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) ExternalEventRegisteredLogItem(name);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else
|
||||
debug_printf("External event registered: %s\n", name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Log::ExternalEventUnregistered(const char* name)
|
||||
{
|
||||
LogItem* item = new(std::nothrow) ExternalEventUnregisteredLogItem(name);
|
||||
if (item != NULL)
|
||||
Add(item);
|
||||
else
|
||||
debug_printf("External event unregistered: %s\n", name);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AbstractJobLogItem
|
||||
|
||||
|
||||
AbstractJobLogItem::AbstractJobLogItem(BaseJob* job)
|
||||
:
|
||||
fJob(job)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AbstractJobLogItem::~AbstractJobLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AbstractJobLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
return parameter.AddString("job", fJob->Name());
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AbstractJobLogItem::Matches(const char* jobName, const char* eventName)
|
||||
{
|
||||
if (jobName == NULL && eventName == NULL)
|
||||
return true;
|
||||
|
||||
if (jobName != NULL && strcmp(fJob->Name(), jobName) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - JobInitializedLogItem
|
||||
|
||||
|
||||
JobInitializedLogItem::JobInitializedLogItem(Job* job)
|
||||
:
|
||||
AbstractJobLogItem(job)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JobInitializedLogItem::~JobInitializedLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
JobInitializedLogItem::Type() const
|
||||
{
|
||||
return kJobInitialized;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobInitializedLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Job \"%s\" initialized.", fJob->Name());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - JobIgnoredLogItem
|
||||
|
||||
|
||||
JobIgnoredLogItem::JobIgnoredLogItem(Job* job, status_t error)
|
||||
:
|
||||
fJobName(job->Name()),
|
||||
fError(error)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JobIgnoredLogItem::~JobIgnoredLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
JobIgnoredLogItem::Type() const
|
||||
{
|
||||
return kJobIgnored;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobIgnoredLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Ignored job \"%s\" due %s", fJobName.String(),
|
||||
strerror(fError));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobIgnoredLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
status_t status = parameter.AddString("job", fJobName);
|
||||
if (status == B_OK)
|
||||
status = parameter.AddInt32("error", fError);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
JobIgnoredLogItem::Matches(const char* jobName, const char* eventName)
|
||||
{
|
||||
if (jobName == NULL && eventName == NULL)
|
||||
return true;
|
||||
|
||||
if (jobName != NULL && fJobName == jobName)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - JobLaunchedLogItem
|
||||
|
||||
|
||||
JobLaunchedLogItem::JobLaunchedLogItem(Job* job, status_t status)
|
||||
:
|
||||
AbstractJobLogItem(job),
|
||||
fStatus(status)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JobLaunchedLogItem::~JobLaunchedLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
JobLaunchedLogItem::Type() const
|
||||
{
|
||||
return kJobLaunched;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobLaunchedLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Job \"%s\" launched: %s", fJob->Name(),
|
||||
strerror(fStatus));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobLaunchedLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
status_t status = AbstractJobLogItem::GetParameter(parameter);
|
||||
if (status == B_OK)
|
||||
status = parameter.AddInt32("status", fStatus);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - JobTerminatedLogItem
|
||||
|
||||
|
||||
JobTerminatedLogItem::JobTerminatedLogItem(Job* job, status_t status)
|
||||
:
|
||||
AbstractJobLogItem(job),
|
||||
fStatus(status)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JobTerminatedLogItem::~JobTerminatedLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
JobTerminatedLogItem::Type() const
|
||||
{
|
||||
return kJobTerminated;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobTerminatedLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Job \"%s\" terminated: %s", fJob->Name(),
|
||||
strerror(fStatus));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobTerminatedLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
status_t status = AbstractJobLogItem::GetParameter(parameter);
|
||||
if (status == B_OK)
|
||||
status = parameter.AddInt32("status", fStatus);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - JobEnabledLogItem
|
||||
|
||||
|
||||
JobEnabledLogItem::JobEnabledLogItem(Job* job, bool enabled)
|
||||
:
|
||||
AbstractJobLogItem(job),
|
||||
fEnabled(enabled)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JobEnabledLogItem::~JobEnabledLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
JobEnabledLogItem::Type() const
|
||||
{
|
||||
return kJobEnabled;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobEnabledLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Job \"%s\" %sabled", fJob->Name(),
|
||||
fEnabled ? "en" : "dis");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobEnabledLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
status_t status = AbstractJobLogItem::GetParameter(parameter);
|
||||
if (status == B_OK)
|
||||
status = parameter.AddBool("enabled", fEnabled);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - JobStoppedLogItem
|
||||
|
||||
|
||||
JobStoppedLogItem::JobStoppedLogItem(BaseJob* job, bool force)
|
||||
:
|
||||
AbstractJobLogItem(job),
|
||||
fForce(force)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JobStoppedLogItem::~JobStoppedLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
JobStoppedLogItem::Type() const
|
||||
{
|
||||
return kJobStopped;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobStoppedLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Job \"%s\" %sstopped", fJob->Name(),
|
||||
fForce ? "force " : "");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
JobStoppedLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
status_t status = AbstractJobLogItem::GetParameter(parameter);
|
||||
if (status == B_OK)
|
||||
status = parameter.AddBool("force", fForce);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - EventLogItem
|
||||
|
||||
|
||||
EventLogItem::EventLogItem(BaseJob* job, Event* event)
|
||||
:
|
||||
AbstractJobLogItem(job),
|
||||
fEvent(event)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EventLogItem::~EventLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
EventLogItem::Type() const
|
||||
{
|
||||
return kEvent;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EventLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("Event triggered \"%s\": \"%s\"", fJob->Name(),
|
||||
fEvent->ToString().String());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EventLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
status_t status = AbstractJobLogItem::GetParameter(parameter);
|
||||
if (status == B_OK)
|
||||
status = parameter.AddString("event", fEvent->ToString());
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EventLogItem::Matches(const char* jobName, const char* eventName)
|
||||
{
|
||||
if (eventName != NULL && strstr(fEvent->ToString(), eventName) == NULL)
|
||||
return false;
|
||||
|
||||
return AbstractJobLogItem::Matches(jobName, NULL);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ExternalEventLogItem
|
||||
|
||||
|
||||
AbstractExternalEventLogItem::AbstractExternalEventLogItem(const char* name)
|
||||
:
|
||||
fEventName(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AbstractExternalEventLogItem::~AbstractExternalEventLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AbstractExternalEventLogItem::GetParameter(BMessage& parameter) const
|
||||
{
|
||||
return parameter.AddString("event", fEventName);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AbstractExternalEventLogItem::Matches(const char* jobName,
|
||||
const char* eventName)
|
||||
{
|
||||
if (jobName == NULL && eventName == NULL)
|
||||
return true;
|
||||
|
||||
if (eventName != NULL && strstr(fEventName.String(), eventName) != NULL)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ExternalEventLogItem
|
||||
|
||||
|
||||
ExternalEventLogItem::ExternalEventLogItem(const char* name)
|
||||
:
|
||||
AbstractExternalEventLogItem(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ExternalEventLogItem::~ExternalEventLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
ExternalEventLogItem::Type() const
|
||||
{
|
||||
return kExternalEvent;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ExternalEventLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("External event triggered: \"%s\"",
|
||||
fEventName.String());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ExternalEventRegisteredLogItem
|
||||
|
||||
|
||||
ExternalEventRegisteredLogItem::ExternalEventRegisteredLogItem(const char* name)
|
||||
:
|
||||
AbstractExternalEventLogItem(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ExternalEventRegisteredLogItem::~ExternalEventRegisteredLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
ExternalEventRegisteredLogItem::Type() const
|
||||
{
|
||||
return kExternalEventRegistered;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ExternalEventRegisteredLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("External event registered: \"%s\"",
|
||||
fEventName.String());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ExternalEventUnregisteredLogItem
|
||||
|
||||
|
||||
ExternalEventUnregisteredLogItem::ExternalEventUnregisteredLogItem(
|
||||
const char* name)
|
||||
:
|
||||
AbstractExternalEventLogItem(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ExternalEventUnregisteredLogItem::~ExternalEventUnregisteredLogItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogItemType
|
||||
ExternalEventUnregisteredLogItem::Type() const
|
||||
{
|
||||
return kExternalEventUnregistered;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ExternalEventUnregisteredLogItem::GetMessage(BString& target) const
|
||||
{
|
||||
target.SetToFormat("External event unregistered: \"%s\"",
|
||||
fEventName.String());
|
||||
return B_OK;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2017-2018, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <locks.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
class BMessage;
|
||||
|
||||
class BaseJob;
|
||||
class Event;
|
||||
class Job;
|
||||
|
||||
|
||||
enum LogItemType {
|
||||
kJobInitialized,
|
||||
kJobIgnored,
|
||||
kJobLaunched,
|
||||
kJobTerminated,
|
||||
kJobEnabled,
|
||||
kJobStopped,
|
||||
kEvent,
|
||||
kExternalEvent,
|
||||
kExternalEventRegistered,
|
||||
kExternalEventUnregistered,
|
||||
};
|
||||
|
||||
|
||||
class LogItem : public DoublyLinkedListLinkImpl<LogItem> {
|
||||
public:
|
||||
public:
|
||||
LogItem();
|
||||
virtual ~LogItem();
|
||||
|
||||
bigtime_t When()
|
||||
{ return fWhen; }
|
||||
BString Message() const;
|
||||
|
||||
virtual LogItemType Type() const = 0;
|
||||
virtual status_t GetMessage(BString& target) const = 0;
|
||||
virtual status_t GetParameter(BMessage& parameter) const = 0;
|
||||
virtual bool Matches(const char* jobName,
|
||||
const char* eventName) = 0;
|
||||
|
||||
private:
|
||||
bigtime_t fWhen;
|
||||
};
|
||||
|
||||
|
||||
typedef DoublyLinkedList<LogItem> LogItemList;
|
||||
|
||||
|
||||
class Log {
|
||||
public:
|
||||
Log();
|
||||
|
||||
void Add(LogItem* item);
|
||||
|
||||
LogItemList::Iterator
|
||||
Iterator()
|
||||
{ return fItems.GetIterator(); }
|
||||
|
||||
mutex& Lock()
|
||||
{ return fLock; }
|
||||
|
||||
void JobInitialized(Job* job);
|
||||
void JobIgnored(Job* job, status_t status);
|
||||
|
||||
void JobLaunched(Job* job, status_t status);
|
||||
void JobTerminated(Job* job, status_t status);
|
||||
|
||||
void JobEnabled(Job* job, bool enabled);
|
||||
void JobStopped(BaseJob* job, bool force);
|
||||
|
||||
void EventTriggered(BaseJob* job, Event* event);
|
||||
|
||||
void ExternalEventTriggered(const char* name);
|
||||
void ExternalEventRegistered(const char* name);
|
||||
void ExternalEventUnregistered(const char* name);
|
||||
|
||||
private:
|
||||
mutex fLock;
|
||||
LogItemList fItems;
|
||||
size_t fCount;
|
||||
};
|
||||
|
||||
|
||||
#endif // LOG_H
|
|
@ -2,7 +2,7 @@ SubDir HAIKU_TOP src tests servers launch ;
|
|||
|
||||
AddSubDirSupportedPlatforms libbe_test ;
|
||||
|
||||
UsePrivateHeaders app libroot shared storage support ;
|
||||
UsePrivateHeaders app kernel libroot shared storage support ;
|
||||
UsePrivateSystemHeaders ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src bin multiuser ] ;
|
||||
|
@ -39,6 +39,7 @@ Server test_launch_daemon :
|
|||
Conditions.cpp
|
||||
Events.cpp
|
||||
Job.cpp
|
||||
Log.cpp
|
||||
NetworkWatcher.cpp
|
||||
SettingsParser.cpp
|
||||
Target.cpp
|
||||
|
|
Loading…
Reference in New Issue