Greatly simplify svc hook for external plugins

This commit removes a lot of unnecessary overhead for handling external
service plugins.  Instead of traversing the plugin array every time a
service callback should run we set the plugin callback in the svc_t when
the plugin is registered.

Also, make sure to check for norespawn/SIGSTOP in svc_reload() as well.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2012-10-02 06:39:26 +02:00
parent f55f68d032
commit 5116cd66ef
5 changed files with 44 additions and 67 deletions
+13 -18
View File
@@ -32,7 +32,6 @@
#include "private.h"
#include "helpers.h"
#include "plugin.h"
#include "svc.h"
#define is_io_plugin(p) ((p)->io.cb && (p)->io.fd >= 0)
@@ -69,11 +68,13 @@ int plugin_register(plugin_t *plugin)
}
if (plugin->svc.cb) {
svc_t *svc = svc_find_by_name(plugin->name);
svc_t *svc = svc_find(plugin->name);
if (svc) {
plugin->svc.id = svc_id(svc);
inuse++;
svc->cb = plugin->svc.cb;
svc->dynamic = plugin->svc.dynamic;
svc->dynamic_stop = plugin->svc.dynamic_stop;
}
}
@@ -91,6 +92,15 @@ int plugin_unregister(plugin_t *plugin)
{
LIST_REMOVE(plugin, link);
if (plugin->svc.cb) {
svc_t *svc = svc_find(plugin->name);
if (svc) {
svc->cb = NULL;
svc->dynamic = 0;
}
}
/* XXX: Unfinished, add cleanup code here! */
return 0;
@@ -109,21 +119,6 @@ void plugin_run_hooks(hook_point_t no)
}
}
/* Run registered plugin service callback for the given svc ID */
svc_cmd_t plugin_svc_enabled(svc_t *svc, int event, void *arg)
{
plugin_t *p;
/* Find matching plugin, pick first matching fd */
PLUGIN_ITERATOR(p) {
if (p->svc.id == svc_id(svc))
return p->svc.cb(svc, event, arg);
}
/* Unknown service, default to start (since it's in finit.conf) */
return SVC_START;
}
/* Generic libev I/O callback, looks up correct plugin and calls its callback */
static void generic_io_cb(int fd, int events)
{
+2 -5
View File
@@ -83,11 +83,8 @@ typedef struct plugin {
/* Service callback to be called once per lap of runloop. */
struct {
/* Private */
int id; /* Service ID# to match this service plugin against, set on installation. */
/* Public */
int dynamic; /* Reload (SIGHUP) on dynamic event? Set by plugin. */
int dynamic; /* Callback wants external events as well. */
int dynamic_stop; /* Callback allows dynamic events to stop. */
svc_cmd_t (*cb)(svc_t *svc, int event, void *event_arg);
} svc;
+5 -6
View File
@@ -28,13 +28,12 @@
#include "svc.h"
#include "plugin.h"
void svc_start_all (void);
void svc_monitor (void);
void svc_start_all (void);
void svc_monitor (void);
void plugin_run_hooks (hook_point_t no);
svc_cmd_t plugin_svc_enabled (svc_t *svc, int event, void *arg);
int plugin_load_all (char *path);
void plugin_monitor (void);
void plugin_run_hooks (hook_point_t no);
int plugin_load_all (char *path);
void plugin_monitor (void);
#endif /* FINIT_PRIVATE_H_ */
+13 -21
View File
@@ -66,7 +66,6 @@ svc_t *svc_new(void)
if (svc_counter < MAX_NUM_SVC) {
svc = &services[svc_counter++];
memset(svc, 0, sizeof(*svc));
svc->id = svc_counter; /* Array pos + 1 to avoid zero ID */
} else {
errno = ENOMEM;
return NULL;
@@ -76,29 +75,13 @@ svc_t *svc_new(void)
}
/**
* svc_find_by_id - Find a service object by its logical ID#
* @id: Logical ID#
*
* Returns:
* A pointer to an &svc_t object, or %NULL if not found.
*/
svc_t *svc_find_by_id(int id)
{
__connect_shm();
if (id < 1 || id > svc_counter)
return NULL;
return &services[id - 1];
}
/**
* svc_find_by_name - Find a service object by its full path name
* svc_find - Find a service object by its full path name
* @name: Full path name, e.g., /sbin/syslogd
*
* Returns:
* A pointer to an &svc_t object, or %NULL if not found.
*/
svc_t *svc_find_by_name(char *name)
svc_t *svc_find(char *name)
{
int i;
@@ -226,7 +209,12 @@ svc_cmd_t svc_enabled(svc_t *svc, int event, void *arg)
return SVC_STOP;
}
return plugin_svc_enabled(svc, event, arg);
/* Is there a service plugin registered? */
if (svc->cb)
return svc->cb(svc, event, arg);
/* No service plugin, default to start, since listed in finit.conf */
return SVC_START;
}
static int is_norespawn(void)
@@ -335,7 +323,7 @@ int svc_start(svc_t *svc)
int svc_start_by_name(char *name)
{
svc_t *svc = svc_find_by_name(name);
svc_t *svc = svc_find(name);
if (svc && svc_enabled(svc, 0, NULL))
return svc_start(svc);
@@ -369,6 +357,10 @@ int svc_stop(svc_t *svc)
int svc_reload(svc_t *svc)
{
/* Ignore if finit is SIGSTOP'ed */
if (is_norespawn())
return 0;
if (!svc) {
_e("Failed, no svc pointer.");
return 1;
+11 -17
View File
@@ -48,17 +48,22 @@ typedef enum {
* of issuing an initctl call. E.g.
* initctl <stop|start|restart> service */
typedef struct svc {
/* Private */
int id; /* Service ID#, set by svc_new() */
pid_t pid;
int reload;
char cmd[MAX_ARG_LEN];
char args[MAX_NUM_SVC_ARGS][MAX_ARG_LEN];
char desc[MAX_STR_LEN];
char username[MAX_USER_LEN];
/* Public */
int reload; /* For external plugins. */
int private; /* For callbacks to use freely, possibly to store "states", set by plugin. */
/* For external plugins. If @cb is set a plugin is loaded.
* @dynamic: Set by plugins that want dynamic events.
* @dynamic_stop: Set by plugins that allow dyn. events to stop it as well.
* @private: Can be used freely by plugin, e.g., to store "states".
*/
int dynamic;
int dynamic_stop;
int private;
svc_cmd_t (*cb)(struct svc *svc, int event, void *event_arg);
} svc_t;
typedef struct svc_map svc_map_t;
@@ -78,19 +83,8 @@ static inline svc_t *finit_svc_connect(void)
return (svc_t *)ptr;
}
static inline int svc_id(svc_t *svc)
{
if (!svc) {
errno = EINVAL;
return -1;
}
return svc->id;
}
svc_t *svc_new (void);
svc_t *svc_find_by_id (int id);
svc_t *svc_find_by_name (char *name);
svc_t *svc_find (char *name);
svc_t *svc_iterator (int restart);
int svc_register (char *line, char *username);