launch_daemon: added support for arbitrary ports.

* Dropped "create_port" -- this is now the default for services.
* Additionally (or alternatively, if you use the "legacy" mode), you can
  now create named ports, and specify their capacity.
* Added convenience methods to BLaunchRoster that automatically use the
  signature of the current be_app.
This commit is contained in:
Axel Dörfler 2015-04-21 18:40:26 +02:00
parent 89168ad8b9
commit 43aec2c726
5 changed files with 153 additions and 41 deletions

View File

@ -1,11 +1,9 @@
service x-vnd.Haiku-registrar { service x-vnd.Haiku-registrar {
launch /system/servers/registrar launch /system/servers/registrar
create_port
} }
service x-vnd.Haiku-app_server { service x-vnd.Haiku-app_server {
launch /system/servers/app_server launch /system/servers/app_server
create_port
} }
service x-vnd.Haiku-debug_server { service x-vnd.Haiku-debug_server {
@ -14,57 +12,69 @@ service x-vnd.Haiku-debug_server {
service x-vnd.Haiku-package_daemon { service x-vnd.Haiku-package_daemon {
launch /system/servers/package_daemon launch /system/servers/package_daemon
create_port
} }
service x-vnd.Haiku-syslog_daemon { service x-vnd.Haiku-SystemLogger {
launch /system/servers/syslog_daemon launch /system/servers/syslog_daemon
port logger {
capacity 256
}
} }
service x-vnd.Haiku-mount_server { service x-vnd.Haiku-mount_server {
launch /system/servers/mount_server launch /system/servers/mount_server
legacy
} }
service x-vnd.Haiku-media_server { service x-vnd.Haiku-media_server {
launch /system/servers/media_server launch /system/servers/media_server
no_safemode no_safemode
legacy
} }
service x-vnd.Haiku-midi_server { service x-vnd.Haiku-midi_server {
launch /system/servers/midi_server launch /system/servers/midi_server
no_safemode no_safemode
legacy
} }
service x-vnd.Haiku-mail_daemon { service x-vnd.Haiku-mail_daemon {
launch /system/servers/mail_daemon -E launch /system/servers/mail_daemon -E
no_safemode no_safemode
legacy
} }
service x-vnd.Haiku-cddb_daemon { service x-vnd.Haiku-cddb_daemon {
launch /system/servers/cddb_daemon launch /system/servers/cddb_daemon
no_safemode no_safemode
legacy
} }
service x-vnd.Haiku-print_server { service x-vnd.Haiku-print_server {
launch /system/servers/print_server launch /system/servers/print_server
no_safemode no_safemode
legacy
} }
service x-vnd.Haiku-notification_server { service x-vnd.Haiku-notification_server {
launch /system/servers/notification_server launch /system/servers/notification_server
no_safemode no_safemode
legacy
} }
service x-vnd.Haiku-power_daemon { service x-vnd.Haiku-power_daemon {
launch /system/servers/power_daemon launch /system/servers/power_daemon
no_safemode no_safemode
legacy
} }
# The following will be moved into the user launch data # The following will be moved into the user launch data
service x-vnd.Be-TRAK { service x-vnd.Be-TRAK {
launch /system/Tracker launch /system/Tracker
legacy
} }
service x-vnd.Be-TSKB { service x-vnd.Be-TSKB {
launch /system/Deskbar launch /system/Deskbar
legacy
} }

View File

@ -16,9 +16,11 @@ public:
status_t InitCheck() const; status_t InitCheck() const;
status_t GetData(BMessage& data);
status_t GetData(const char* signature, BMessage& data); status_t GetData(const char* signature, BMessage& data);
port_id GetPort(const char* name = NULL);
port_id GetPort(const char* signature, port_id GetPort(const char* signature,
const char* name = NULL); const char* name);
private: private:
void _InitMessenger(); void _InitMessenger();

View File

@ -531,7 +531,7 @@ DBG(OUT("BApplication::InitData() done\n"));
port_id port_id
BApplication::_GetPort(const char* signature) BApplication::_GetPort(const char* signature)
{ {
return BLaunchRoster().GetPort(signature); return BLaunchRoster().GetPort(signature, NULL);
} }

View File

@ -9,6 +9,7 @@
#include <LaunchRoster.h> #include <LaunchRoster.h>
#include <Application.h>
#include <String.h> #include <String.h>
#include <LaunchDaemonDefs.h> #include <LaunchDaemonDefs.h>
@ -39,6 +40,16 @@ BLaunchRoster::InitCheck() const
} }
status_t
BLaunchRoster::GetData(BMessage& data)
{
if (be_app == NULL)
return B_BAD_VALUE;
return GetData(be_app->Signature(), data);
}
status_t status_t
BLaunchRoster::GetData(const char* signature, BMessage& data) BLaunchRoster::GetData(const char* signature, BMessage& data)
{ {
@ -55,12 +66,22 @@ BLaunchRoster::GetData(const char* signature, BMessage& data)
// evaluate the reply // evaluate the reply
if (status == B_OK) if (status == B_OK)
status = data.GetInt32("error", B_OK); status = data.what;
return status; return status;
} }
port_id
BLaunchRoster::GetPort(const char* name)
{
if (be_app == NULL)
return B_BAD_VALUE;
return GetPort(be_app->Signature(), name);
}
port_id port_id
BLaunchRoster::GetPort(const char* signature, const char* name) BLaunchRoster::GetPort(const char* signature, const char* name)
{ {
@ -69,12 +90,10 @@ BLaunchRoster::GetPort(const char* signature, const char* name)
status_t status = launchRoster.GetData(signature, data); status_t status = launchRoster.GetData(signature, data);
if (status == B_OK) { if (status == B_OK) {
BString fieldName; BString fieldName;
if (name == NULL) if (name != NULL)
fieldName = "port"; fieldName << name << "_";
else { fieldName << "port";
fieldName = name;
fieldName << "_port";
}
port_id port = data.GetInt32(fieldName.String(), B_NAME_NOT_FOUND); port_id port = data.GetInt32(fieldName.String(), B_NAME_NOT_FOUND);
if (port >= 0) if (port >= 0)
return port; return port;

View File

@ -30,11 +30,17 @@ using namespace BPrivate;
static const char* kLaunchDirectory = "launch"; static const char* kLaunchDirectory = "launch";
const static settings_template kPortTemplate[] = {
{B_STRING_TYPE, "name", NULL, true},
{B_INT32_TYPE, "capacity", NULL},
};
const static settings_template kJobTemplate[] = { const static settings_template kJobTemplate[] = {
{B_STRING_TYPE, "name", NULL, true}, {B_STRING_TYPE, "name", NULL, true},
{B_BOOL_TYPE, "disabled", NULL}, {B_BOOL_TYPE, "disabled", NULL},
{B_STRING_TYPE, "launch", NULL}, {B_STRING_TYPE, "launch", NULL},
{B_BOOL_TYPE, "create_port", NULL}, {B_BOOL_TYPE, "legacy", NULL},
{B_MESSAGE_TYPE, "port", kPortTemplate},
{B_BOOL_TYPE, "no_safemode", NULL}, {B_BOOL_TYPE, "no_safemode", NULL},
{0, NULL, NULL} {0, NULL, NULL}
}; };
@ -46,6 +52,9 @@ const static settings_template kSettingsTemplate[] = {
}; };
typedef std::map<BString, BMessage> PortMap;
class Job { class Job {
public: public:
Job(const char* name); Job(const char* name);
@ -59,8 +68,10 @@ public:
bool IsService() const; bool IsService() const;
void SetService(bool service); void SetService(bool service);
bool CreatePort() const; bool CreateDefaultPort() const;
void SetCreatePort(bool createPort); void SetCreateDefaultPort(bool createPort);
void AddPort(BMessage& data);
bool LaunchInSafeMode() const; bool LaunchInSafeMode() const;
void SetLaunchInSafeMode(bool launch); void SetLaunchInSafeMode(bool launch);
@ -73,7 +84,9 @@ public:
status_t InitCheck() const; status_t InitCheck() const;
team_id Team() const; team_id Team() const;
port_id Port() const;
const PortMap& Ports() const;
port_id Port(const char* name = NULL) const;
status_t Launch(); status_t Launch();
bool IsLaunched() const; bool IsLaunched() const;
@ -83,9 +96,9 @@ private:
BStringList fArguments; BStringList fArguments;
bool fEnabled; bool fEnabled;
bool fService; bool fService;
bool fCreatePort; bool fCreateDefaultPort;
bool fLaunchInSafeMode; bool fLaunchInSafeMode;
port_id fPort; PortMap fPortMap;
status_t fInitStatus; status_t fInitStatus;
team_id fTeam; team_id fTeam;
}; };
@ -141,9 +154,8 @@ Job::Job(const char* name)
fName(name), fName(name),
fEnabled(true), fEnabled(true),
fService(false), fService(false),
fCreatePort(false), fCreateDefaultPort(false),
fLaunchInSafeMode(true), fLaunchInSafeMode(true),
fPort(-1),
fInitStatus(B_NO_INIT), fInitStatus(B_NO_INIT),
fTeam(-1) fTeam(-1)
{ {
@ -153,8 +165,12 @@ Job::Job(const char* name)
Job::~Job() Job::~Job()
{ {
if (fPort >= 0) PortMap::const_iterator iterator = Ports().begin();
delete_port(fPort); for (; iterator != Ports().end(); iterator++) {
port_id port = iterator->second.GetInt32("port", -1);
if (port >= 0)
delete_port(port);
}
} }
@ -194,16 +210,24 @@ Job::SetService(bool service)
bool bool
Job::CreatePort() const Job::CreateDefaultPort() const
{ {
return fCreatePort; return fCreateDefaultPort;
} }
void void
Job::SetCreatePort(bool createPort) Job::SetCreateDefaultPort(bool createPort)
{ {
fCreatePort = createPort; fCreateDefaultPort = createPort;
}
void
Job::AddPort(BMessage& data)
{
const char* name = data.GetString("name");
fPortMap.insert(std::pair<BString, BMessage>(BString(name), data));
} }
@ -247,11 +271,42 @@ Job::Init()
{ {
fInitStatus = B_OK; fInitStatus = B_OK;
if (fCreatePort) { // Create ports
// TODO: prefix system ports with "system:" // TODO: prefix system ports with "system:"
fPort = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
if (fPort < 0) bool defaultPort = false;
fInitStatus = fPort;
for (PortMap::iterator iterator = fPortMap.begin();
iterator != fPortMap.end(); iterator++) {
BString name(Name());
const char* suffix = iterator->second.GetString("name");
if (suffix != NULL)
name << ':' << suffix;
else
defaultPort = true;
const int32 capacity = iterator->second.GetInt32("capacity",
B_LOOPER_PORT_DEFAULT_CAPACITY);
port_id port = create_port(capacity, name.String());
if (port < 0) {
fInitStatus = port;
break;
}
iterator->second.SetInt32("port", port);
}
if (fInitStatus == B_OK && fCreateDefaultPort && !defaultPort) {
BMessage data;
data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY);
port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
if (port < 0)
fInitStatus = port;
else {
data.SetInt32("port", port);
AddPort(data);
}
} }
return fInitStatus; return fInitStatus;
@ -272,10 +327,21 @@ Job::Team() const
} }
port_id const PortMap&
Job::Port() const Job::Ports() const
{ {
return fPort; return fPortMap;
}
port_id
Job::Port(const char* name) const
{
PortMap::const_iterator found = fPortMap.find(name);
if (found != fPortMap.end())
return found->second.GetInt32("port", -1);
return B_NAME_NOT_FOUND;
} }
@ -366,18 +432,27 @@ LaunchDaemon::MessageReceived(BMessage* message)
switch (message->what) { switch (message->what) {
case B_GET_LAUNCH_DATA: case B_GET_LAUNCH_DATA:
{ {
BMessage reply; BMessage reply((uint32)B_OK);
Job* job = _Job(get_leaf(message->GetString("name"))); Job* job = _Job(get_leaf(message->GetString("name")));
if (job == NULL) { if (job == NULL) {
reply.AddInt32("error", B_NAME_NOT_FOUND); reply.what = B_NAME_NOT_FOUND;
} else { } else {
// If the job has not been launched yet, we'll pass on our // If the job has not been launched yet, we'll pass on our
// team here. The rationale behind this is that this team // team here. The rationale behind this is that this team
// will temporarily own the synchronous reply ports. // will temporarily own the synchronous reply ports.
reply.AddInt32("team", job->Team() < 0 reply.AddInt32("team", job->Team() < 0
? current_team() : job->Team()); ? current_team() : job->Team());
if (job->CreatePort())
reply.AddInt32("port", job->Port()); PortMap::const_iterator iterator = job->Ports().begin();
for (; iterator != job->Ports().end(); iterator++) {
BString name;
if (iterator->second.HasString("name"))
name << iterator->second.GetString("name") << "_";
name << "port";
reply.AddInt32(name.String(),
iterator->second.GetInt32("port", -1));
}
// Launch job now if it isn't running yet // Launch job now if it isn't running yet
if (!job->IsLaunched()) if (!job->IsLaunched())
@ -447,7 +522,7 @@ LaunchDaemon::_ReadFile(const char* context, BEntry& entry)
BMessage job; BMessage job;
for (int32 index = 0; message.FindMessage("service", index, for (int32 index = 0; message.FindMessage("service", index,
&job) == B_OK; index++) { &job) == B_OK; index++) {
_AddJob(false, job); _AddJob(true, job);
} }
for (int32 index = 0; message.FindMessage("job", index, &job) == B_OK; for (int32 index = 0; message.FindMessage("job", index, &job) == B_OK;
@ -475,10 +550,16 @@ LaunchDaemon::_AddJob(bool service, BMessage& message)
job->SetEnabled(!message.GetBool("disabled", !job->IsEnabled())); job->SetEnabled(!message.GetBool("disabled", !job->IsEnabled()));
job->SetService(service); job->SetService(service);
job->SetCreatePort(message.GetBool("create_port", job->CreatePort())); job->SetCreateDefaultPort(!message.GetBool("legacy", !service));
job->SetLaunchInSafeMode( job->SetLaunchInSafeMode(
!message.GetBool("no_safemode", !job->LaunchInSafeMode())); !message.GetBool("no_safemode", !job->LaunchInSafeMode()));
BMessage portMessage;
for (int32 index = 0;
message.FindMessage("port", index, &portMessage) == B_OK; index++) {
job->AddPort(portMessage);
}
const char* argument; const char* argument;
for (int32 index = 0; for (int32 index = 0;
message.FindString("launch", index, &argument) == B_OK; index++) { message.FindString("launch", index, &argument) == B_OK; index++) {