mirror of
https://github.com/troglobit/finit.git
synced 2026-10-08 16:34:45 +07:00
conf: route service conditions through one owner primitive
A service's condition was computed with mkcond() at each of the six sites that assert or clear it, and svc_find_by_cond() reimplemented the reverse lookup a seventh time. maybe_clear_cond() had its own scan for another service supplying the same condition. svc_cond_owner() answers who owns a condition, svc_cond_nth() walks the conditions a service owns, and svc_cond_set()/svc_cond_clear() apply to all of them. svc_find_by_cond() becomes a wrapper, and maybe_clear_cond() keeps its rule per condition rather than for the one it used to compute. The provides[] storage lands here unused, since svc_cond_nth() reads num_provides. Nothing sets it yet, so a service still owns exactly its own pid/<ident> and there is no functional change. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+2
-2
@@ -148,12 +148,12 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
||||
}
|
||||
|
||||
if (svc->notify == SVC_NOTIFY_PID)
|
||||
cond_set(cond);
|
||||
svc_cond_set(svc);
|
||||
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
|
||||
service_ready(svc, 1);
|
||||
} else if (mask & IN_DELETE) {
|
||||
sneaky_zebra:
|
||||
cond_clear(cond);
|
||||
svc_cond_clear(svc);
|
||||
if (svc->notify == SVC_NOTIFY_PID)
|
||||
service_ready(svc, 0);
|
||||
}
|
||||
|
||||
@@ -112,8 +112,6 @@ static int restart(svc_t *svc, void *user_data)
|
||||
|
||||
static int reload(svc_t *svc, void *user_data)
|
||||
{
|
||||
char cond[MAX_COND_LEN];
|
||||
|
||||
(void)user_data;
|
||||
|
||||
if (!svc)
|
||||
@@ -138,7 +136,7 @@ static int reload(svc_t *svc, void *user_data)
|
||||
* mechanism which may not re-trigger on SIGHUP.
|
||||
*/
|
||||
if (svc_is_noreload(svc)) {
|
||||
cond_clear(mkcond(svc, cond, sizeof(cond)));
|
||||
svc_cond_clear(svc);
|
||||
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
|
||||
service_ready(svc, 0);
|
||||
}
|
||||
|
||||
@@ -145,6 +145,31 @@ char *mkcond(svc_t *svc, char *buf, size_t len)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assert or clear every condition a service owns: its own pid/<ident>
|
||||
* and anything it declares with provides. Each site that owns a
|
||||
* service's conditions goes through these, so the two cannot drift.
|
||||
*/
|
||||
void svc_cond_set(svc_t *svc)
|
||||
{
|
||||
char buf[MAX_COND_LEN];
|
||||
const char *cond;
|
||||
int i = 0;
|
||||
|
||||
while ((cond = svc_cond_nth(svc, i++, buf, sizeof(buf))))
|
||||
cond_set(cond);
|
||||
}
|
||||
|
||||
void svc_cond_clear(svc_t *svc)
|
||||
{
|
||||
char buf[MAX_COND_LEN];
|
||||
const char *cond;
|
||||
int i = 0;
|
||||
|
||||
while ((cond = svc_cond_nth(svc, i++, buf, sizeof(buf))))
|
||||
cond_clear(cond);
|
||||
}
|
||||
|
||||
static int cond_set_gen(const char *file, unsigned int gen)
|
||||
{
|
||||
char *ptr, path[256];
|
||||
|
||||
@@ -25,6 +25,8 @@ typedef enum cond_state {
|
||||
} cond_state_t;
|
||||
|
||||
char *mkcond (svc_t *svc, char *buf, size_t len);
|
||||
void svc_cond_set (svc_t *svc);
|
||||
void svc_cond_clear(svc_t *svc);
|
||||
const char *condstr (enum cond_state s);
|
||||
const char *cond_path (const char *name);
|
||||
unsigned int cond_get_gen (const char *path);
|
||||
|
||||
+2
-6
@@ -1271,8 +1271,6 @@ static void service_clean_pidfile(svc_t *svc, pid_t reaped)
|
||||
*/
|
||||
static void service_cleanup(svc_t *svc)
|
||||
{
|
||||
char cond[MAX_COND_LEN];
|
||||
|
||||
/* PID collected, cancel any pending SIGKILL */
|
||||
service_timeout_cancel(svc);
|
||||
|
||||
@@ -1297,7 +1295,7 @@ static void service_cleanup(svc_t *svc)
|
||||
* RUNNING to HALTED (skipping STOPPING where cond_clear()
|
||||
* is normally called).
|
||||
*/
|
||||
cond_clear(mkcond(svc, cond, sizeof(cond)));
|
||||
svc_cond_clear(svc);
|
||||
|
||||
service_notify_stop(svc);
|
||||
|
||||
@@ -3191,13 +3189,11 @@ restart:
|
||||
|
||||
case SVC_STOPPING_STATE:
|
||||
if (!svc->pid) {
|
||||
char condstr[MAX_COND_LEN];
|
||||
|
||||
dbg("%s: stopped, cleaning up timers and conditions ...", svc_ident(svc, NULL, 0));
|
||||
service_notify_stop(svc);
|
||||
|
||||
service_timeout_cancel(svc);
|
||||
cond_clear(mkcond(svc, condstr, sizeof(condstr)));
|
||||
svc_cond_clear(svc);
|
||||
|
||||
switch (svc->type) {
|
||||
case SVC_TYPE_SERVICE:
|
||||
|
||||
@@ -57,27 +57,24 @@ static TAILQ_HEAD(, svc) gc_list = TAILQ_HEAD_INITIALIZER(gc_list);
|
||||
static void maybe_clear_cond(svc_t *svc)
|
||||
{
|
||||
char ident[MAX_IDENT_LEN];
|
||||
char cond[MAX_COND_LEN];
|
||||
svc_t *iter = NULL;
|
||||
svc_t *s;
|
||||
char buf[MAX_COND_LEN];
|
||||
const char *cond;
|
||||
int i = 0;
|
||||
|
||||
mkcond(svc, cond, sizeof(cond));
|
||||
svc_ident(svc, ident, sizeof(ident));
|
||||
|
||||
for (s = svc_iterator(&iter, 1); s; s = svc_iterator(&iter, 0)) {
|
||||
char c[MAX_COND_LEN];
|
||||
while ((cond = svc_cond_nth(svc, i++, buf, sizeof(buf)))) {
|
||||
svc_t *owner = svc_cond_owner(cond, svc);
|
||||
|
||||
mkcond(s, c, sizeof(c));
|
||||
if (!string_compare(cond, c))
|
||||
if (owner) {
|
||||
dbg("Not clearing cond %s from gc svc %s, provided by new active service %s",
|
||||
cond, ident, svc_ident(owner, NULL, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
dbg("Not clearing cond %s from gc svc %s, provided by new active service %s",
|
||||
cond, ident, svc_ident(s, NULL, 0));
|
||||
return;
|
||||
dbg("Cleaning out %s, clearing cond %s ...", ident, cond);
|
||||
cond_clear(cond);
|
||||
}
|
||||
|
||||
dbg("Cleaning out %s, clearing any conditions ...", svc->name);
|
||||
cond_clear(mkcond(svc, cond, sizeof(cond)));
|
||||
}
|
||||
|
||||
static void svc_gc(void *arg)
|
||||
@@ -459,25 +456,92 @@ svc_t *svc_find_by_pid(pid_t pid)
|
||||
}
|
||||
|
||||
/**
|
||||
* svc_find_by_cond - Find a service object by its pid/foo condition
|
||||
* @cond: Full "pid/foo" condition
|
||||
* svc_cond_nth - Walk the conditions a service owns
|
||||
* @svc: Service object
|
||||
* @i: 0 for the service's own pid/<ident>, 1.. for provided ones
|
||||
* @buf: Scratch for the own condition, unused for the rest
|
||||
* @len: Size of @buf
|
||||
*
|
||||
* Returns:
|
||||
* The @i'th condition, or %NULL when @i is past the last one.
|
||||
*/
|
||||
const char *svc_cond_nth(svc_t *svc, int i, char *buf, size_t len)
|
||||
{
|
||||
if (!svc || i < 0)
|
||||
return NULL;
|
||||
if (i == 0)
|
||||
return mkcond(svc, buf, len);
|
||||
if (i > svc->num_provides)
|
||||
return NULL;
|
||||
|
||||
return svc->provides[i - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* svc_cond_owner - Find the service that owns a condition
|
||||
* @cond: Full condition, e.g. "pid/syslogd"
|
||||
* @skip: Service to leave out of the search, or %NULL
|
||||
*
|
||||
* A service's own pid/<ident> outranks one it merely provides, that is
|
||||
* how Finit tracks the service itself, so every identity is checked
|
||||
* before any provides.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to an &svc_t object, or %NULL if nobody owns @cond.
|
||||
*/
|
||||
svc_t *svc_cond_owner(const char *cond, svc_t *skip)
|
||||
{
|
||||
svc_t *svc, *iter = NULL;
|
||||
int i;
|
||||
|
||||
if (!cond || !cond[0])
|
||||
return NULL;
|
||||
|
||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||
char buf[MAX_COND_LEN];
|
||||
|
||||
if (svc == skip)
|
||||
continue;
|
||||
if (string_compare(mkcond(svc, buf, sizeof(buf)), cond))
|
||||
return svc;
|
||||
}
|
||||
|
||||
iter = NULL;
|
||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||
if (svc == skip)
|
||||
continue;
|
||||
for (i = 0; i < svc->num_provides; i++) {
|
||||
if (string_compare(svc->provides[i], cond))
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* svc_find_by_cond - Find a service object by a condition it owns
|
||||
* @cond: Full condition, e.g. "pid/syslogd"
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to an &svc_t object, or %NULL if not found.
|
||||
*/
|
||||
svc_t *svc_find_by_cond(const char *cond)
|
||||
{
|
||||
return svc_cond_owner(cond, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Provides are re-read from the .conf files on every reload, and a
|
||||
* service re-registering must not lose to a claim another service has
|
||||
* not dropped yet, so they all go at once before parsing starts.
|
||||
*/
|
||||
void svc_provides_reset(void)
|
||||
{
|
||||
svc_t *svc, *iter = NULL;
|
||||
|
||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||
char buf[MAX_COND_LEN];
|
||||
|
||||
mkcond(svc, buf, sizeof(buf));
|
||||
if (string_compare(buf, cond))
|
||||
return svc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0))
|
||||
svc->num_provides = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,6 +102,7 @@ typedef enum {
|
||||
#define MAX_COND_LEN (MAX_ARG_LEN * 3)
|
||||
#define MAX_USER_LEN 16
|
||||
#define MAX_NUM_SUPGROUPS 4
|
||||
#define MAX_NUM_PROVIDES 4
|
||||
#define MAX_NUM_FDS 64 /* Max number of I/O plugins */
|
||||
#define MAX_NUM_SVC_ARGS 64
|
||||
|
||||
@@ -151,6 +152,10 @@ typedef struct svc {
|
||||
svc_block_t block; /* Reason that this service is currently stopped */
|
||||
char cond[MAX_COND_LEN];
|
||||
|
||||
/* Conditions this service asserts on top of its own pid/<ident> */
|
||||
char provides[MAX_NUM_PROVIDES][MAX_COND_LEN];
|
||||
int num_provides;
|
||||
|
||||
/* Instance specifics */
|
||||
int job; /* For internal use only, canonical ref is NAME:ID */
|
||||
char name[MAX_ARG_LEN];
|
||||
@@ -266,6 +271,9 @@ svc_t *svc_find (char *name, char *id);
|
||||
svc_t *svc_find_by_str (const char *str);
|
||||
svc_t *svc_find_by_pid (pid_t pid);
|
||||
svc_t *svc_find_by_cond (const char *cond);
|
||||
svc_t *svc_cond_owner (const char *cond, svc_t *skip);
|
||||
const char *svc_cond_nth (svc_t *svc, int i, char *buf, size_t len);
|
||||
void svc_provides_reset (void);
|
||||
svc_t *svc_find_by_jobid (int job, char *id);
|
||||
svc_t *svc_find_by_tty (char *dev);
|
||||
svc_t *svc_find_by_pidfile (char *fn);
|
||||
|
||||
Reference in New Issue
Block a user