summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-07-21 13:16:39 +0000
committerLaurent Bercot <ska@appnovation.com>2021-07-21 13:16:39 +0000
commit53d7f0de3feeb8ad93bb8c319c3f0f314c7d31cf (patch)
treeba85733fc50c6f1ee56261cbd33328e4c78af435
parent89a440efc603e6d6c7fa85b01a5a904baff5cd26 (diff)
downloads6-rc-53d7f0de3feeb8ad93bb8c319c3f0f314c7d31cf.tar.xz
New id/typenum mapping, monitor filter, cdb in db_load, etc.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--src/include/s6-rc/db.h (renamed from src/include-local/db.h)43
-rw-r--r--src/libs6rc/s6rc_db_free.c (renamed from src/libs6rcd/s6rc_db_free.c)3
-rw-r--r--src/libs6rc/s6rc_db_load.c (renamed from src/libs6rcd/s6rc_db_load.c)31
-rw-r--r--src/libs6rc/s6rc_service_common.c16
-rw-r--r--src/libs6rc/s6rc_service_common_tn.c21
-rw-r--r--src/libs6rc/s6rc_service_id.c12
-rw-r--r--src/libs6rc/s6rc_service_num.c13
-rw-r--r--src/libs6rc/s6rc_service_recheck_instance.c31
-rw-r--r--src/libs6rc/s6rc_service_resolve.c13
-rw-r--r--src/libs6rc/s6rc_service_type.c13
-rw-r--r--src/libs6rc/s6rc_service_typenum.c13
-rw-r--r--src/libs6rcd/s6rc_service_common.c16
-rw-r--r--src/libs6rcd/s6rc_service_resolve.c31
-rw-r--r--src/server/client.c19
-rw-r--r--src/server/client.h8
-rw-r--r--src/server/deps.c88
-rw-r--r--src/server/deps.h19
-rw-r--r--src/server/state.c179
-rw-r--r--src/server/state.h39
19 files changed, 422 insertions, 186 deletions
diff --git a/src/include-local/db.h b/src/include/s6-rc/db.h
index b35fc42..be2c46c 100644
--- a/src/include-local/db.h
+++ b/src/include/s6-rc/db.h
@@ -3,6 +3,7 @@
#ifndef S6RCD_SERVICE_H
#define S6RCD_SERVICE_H
+#include <sys/types.h>
#include <stdint.h>
#include <skalibs/cdb.h>
@@ -20,11 +21,6 @@
#define S6RC_STYPE_VIRTUAL 4
#define S6RC_STYPE_N 5
-typedef uint32_t s6rc_id_t, *s6rc_id_t_ref ;
-
-#define stype(sid) ((sid) >> 28)
-#define snum(sid) ((sid) & 0x0fffffffu)
-
typedef struct s6rc_common_s s6rc_common_t, *s6rc_common_t_ref ;
struct s6rc_common_s
{
@@ -37,6 +33,12 @@ struct s6rc_common_s
#define S6RC_DB_FLAG_ESSENTIAL 0x80000000u
#define S6RC_DB_FLAG_WEAK 0x40000000u
+ /*
+ s6rc_common_t must always be the first field of a service,
+ so we can cast the pointer to s6rc_longrun_t * and friends
+ in a C-approved way.
+ */
+
typedef struct s6rc_atomic_s s6rc_atomic_t, *s6rc_atomic_t_ref ;
struct s6rc_atomic_s
{
@@ -44,13 +46,6 @@ struct s6rc_atomic_s
uint32_t timeout[2] ;
} ;
-typedef struct s6rc_oneshot_s s6rc_oneshot_t, *s6rc_oneshot_t_ref ;
-struct s6rc_oneshot_s
-{
- s6rc_atomic_t satomic ;
- uint32_t argv[2] ;
-} ;
-
typedef struct s6rc_longrun_s s6rc_longrun_t, *s6rc_longrun_t_ref ;
struct s6rc_longrun_s
{
@@ -60,6 +55,13 @@ struct s6rc_longrun_s
s6rc_id_t consumer ;
} ;
+typedef struct s6rc_oneshot_s s6rc_oneshot_t, *s6rc_oneshot_t_ref ;
+struct s6rc_oneshot_s
+{
+ s6rc_atomic_t satomic ;
+ uint32_t argv[2] ;
+} ;
+
typedef struct s6rc_external_s s6rc_external_t, *s6rc_external_t_ref ;
struct s6rc_external_s
{
@@ -74,15 +76,11 @@ struct s6rc_bundle_s
uint32_t contents ;
} ;
-#define s6rc_deptype_passive(dep) ((dep) & 0x01u)
-#define s6rc_deptype_soft(dep) ((dep) & 0x02u)
-#define s6rc_deptype_loose(dep) ((dep) & 0x04u)
-
typedef struct s6rc_db_s s6rc_db_t, *s6rc_db_t_ref ;
struct s6rc_db_s
{
char const *map ;
- size_t size ;
+ off_t size ;
uint32_t const *n ;
s6rc_longrun_t const *longruns ;
s6rc_oneshot_t const *oneshots ;
@@ -97,7 +95,14 @@ struct s6rc_db_s
} ;
#define S6RC_DB_ZERO = { .map = 0, .len = 0 }
-extern int s6rc_service_resolve (cdb_t *, char const *, s6rc_id_t *, char const **) ;
-extern s6rc_common_t const *s6rc_service_common (s6rc_db_t const *, s6rc_id_t) ;
+extern uint32_t s6rc_service_id (uint32_t const *, uint8_t, uint32_t) ;
+extern void s6rc_service_typenum (uin32_t const *, uint32_t, uint8_t *, uint32_t *) ;
+extern uint8_t s6rc_service_type (uint32_t const *, uint32_t) ;
+extern uint32_t s6rc_service_num (uint32_t const *, uint32_t) ;
+
+extern int s6rc_service_resolve (cdb_t *, char const *, uint32_t *, char const **) ;
+extern s6rc_common_t const *s6rc_service_common (s6rc_db_t const *, uint32_t) ;
+extern s6rc_common_t const *s6rc_service_common_tn (s6rc_db_t const *, uint8_t, uint32_t) ;
+extern int s6rc_service_recheck_instance (s6rc_db_t const *, cdb_t *, uint32_t *, char const **) ;
#endif
diff --git a/src/libs6rcd/s6rc_db_free.c b/src/libs6rc/s6rc_db_free.c
index 07f4ccd..7e7ed54 100644
--- a/src/libs6rcd/s6rc_db_free.c
+++ b/src/libs6rc/s6rc_db_free.c
@@ -1,10 +1,11 @@
/* ISC license. */
+#include <sys/mman.h>
#include <errno.h>
#include <skalibs/alloc.h>
-#include "db.h"
+#include <s6-rc/db.h>
void s6rc_db_free (s6rc_db_t *db)
{
diff --git a/src/libs6rcd/s6rc_db_load.c b/src/libs6rc/s6rc_db_load.c
index e42afc9..8463e55 100644
--- a/src/libs6rcd/s6rc_db_load.c
+++ b/src/libs6rc/s6rc_db_load.c
@@ -10,9 +10,10 @@
#include <skalibs/alloc.h>
#include <skalibs/buffer.h>
#include <skalibs/djbunix.h>
+#include <skalibs/cdb.h>
#include <skalibs/sha256.h>
-#include "db.h"
+#include <s6-rc/db.h>
#include <skalibs/posixishard.h>
@@ -23,7 +24,7 @@ static int gethu32 (buffer *b, SHA256Schedule *ctx, uint32_t *n)
return 1 ;
}
-int s6rc_db_load (char const *dir, s6rc_db_t *db)
+int s6rc_db_load (char const *dir, s6rc_db_t *db, cdb_t *c)
{
SHA256Schedule ctx = SHA256_INIT() ;
uint32_t ntotal, ndeps, nproducers, storagelen, nargv ;
@@ -31,7 +32,7 @@ int s6rc_db_load (char const *dir, s6rc_db_t *db)
buffer b ;
int fd ;
char buf[4096] ;
- char fn[len + 10] ;
+ char fn[len + 13] ;
memcpy(fn, dir, len) ;
memcpy(fn + len, "/db_nomap", 10) ;
fd = openc_read(fn) ;
@@ -77,17 +78,25 @@ int s6rc_db_load (char const *dir, s6rc_db_t *db)
db->map = map ;
}
db->n = (uint32_t const *)db->map ;
- if (ntotal != db->n[0] + db->n[1] + db->n[2] + db->n[3] + db->n[4] + db->n[5] + db->n[6] + db->n[7] + db->n[8] + db->n[9]) goto eproto1 ;
+ if (ntotal != db->n[0] + db->n[1] + db->n[2] + db->n[3] + db->n[4] + db->n[5] + db->n[6] + db->n[7] + db->n[8] + db->n[9])
+ {
+ errno = EPROTO ;
+ goto err1 ;
+ }
+
+ memcpy(fn + len, "/resolve.cdb", 13) ;
+ if (!cdb_mapfile(fn, c)) goto err1 ;
{
ssize_t r ;
memcpy(fn + len, "/hash", 6) ;
r = openreadnclose(fn, buf+32, 33) ;
- if (r == 33) goto eproto1 ;
- if (r < 32) goto err1 ;
+ if (r == 33) goto eproto2 ;
+ if (r < 32) goto err2 ;
sha256_update(&ctx, db->map, db->size) ;
+ sha256_update(&ctx, c->map, c->size) ;
sha256_final(&ctx, buf) ;
- if (memcmp(buf, buf+32, 32)) goto eproto1 ;
+ if (memcmp(buf, buf+32, 32)) goto eproto2 ;
}
db->longruns = (s6rc_longrun_t const *)(db->map + 4 * 2 * S6RC_STYPE_N) ;
@@ -101,17 +110,19 @@ int s6rc_db_load (char const *dir, s6rc_db_t *db)
db->deptypes[0] = (uint8_t const *)(db->producers + nproducers) ;
db->deptypes[1] = db->deptypes[0] + ndeps ;
db->storage = (char const *)(db->deptypes[1] + ndeps) ;
- if (db->storage + storagelen != db->map + db->size) goto eproto1 ;
+ if (db->storage + storagelen != db->map + db->size) goto eproto2 ;
db->argvs = (char const **)alloc(sizeof(char const *) * nargv) ;
- if (!db->argvs) goto err1 ;
+ if (!db->argvs) goto err2 ;
for (uint32_t i = 0 ; i < nargv ; i++)
db->argvs[i] = argvs[i] ? db->storage + argvs[i] : 0 ;
}
return 1 ;
- eproto1:
+ eproto2:
errno = EPROTO ;
+ err2:
+ cdb_free(c) ;
err1:
{
int e = errno ;
diff --git a/src/libs6rc/s6rc_service_common.c b/src/libs6rc/s6rc_service_common.c
index f3146be..8cbf839 100644
--- a/src/libs6rc/s6rc_service_common.c
+++ b/src/libs6rc/s6rc_service_common.c
@@ -4,16 +4,10 @@
#include <s6-rc/db.h>
-s6rc_common_t const *s6rc_service_common (s6rc_db_t const *db, s6rc_sid_t const *id)
+s6rc_common_t const *s6rc_service_common (s6rc_db_t const *db, uint32_t id)
{
- uint32_t i = id->i + (id->param ? db->n[id->stype] : 0) ;
- switch (id->stype)
- {
- case STYPE_LONGRUN : return &db->longruns[i].common ;
- case STYPE_ONESHOT : return &db->oneshots[i].common ;
- case STYPE_EXTERNAL : return &db->externals[i].common ;
- case STYPE_BUNDLE : return &db->bundles[i].common ;
- case STYPE_VIRTUAL : return &db->virtuals[i].common ;
- default : return 0 ;
- }
+ uint32_t num ;
+ uint8_t type ;
+ s6rc_service_typenum(db->n, id, &type, &num) ;
+ return s6rc_service_common_tn(db, type, num) ;
}
diff --git a/src/libs6rc/s6rc_service_common_tn.c b/src/libs6rc/s6rc_service_common_tn.c
new file mode 100644
index 0000000..85ab3b5
--- /dev/null
+++ b/src/libs6rc/s6rc_service_common_tn.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <s6-rc/db.h>
+
+s6rc_common_t const *s6rc_service_common_tn (s6rc_db_t const *db, uint8_t type, uint32_t num)
+{
+ switch (type)
+ {
+ case STYPE_LONGRUN : return &db->longruns[num].common ;
+ case S6RC_STYPE_N + STYPE_LONGRUN : return &db->longruns[db->n[S6RC_STYPE_LONGRUN] + num].common ;
+ case STYPE_ONESHOT : return &db->oneshots[num].common ;
+ case S6RC_STYPE_N + STYPE_ONESHOT : return &db->oneshots[db->n[S6RC_STYPE_ONESHOT] + num].common ;
+ case STYPE_EXTERNAL : return &db->externals[num].common ;
+ case S6RC_STYPE_N + STYPE_EXTERNAL : return &db->externals[db->n[S6RC_STYPE_EXTERNAL] + num].common ;
+ case STYPE_BUNDLE : return &db->bundles[num].common ;
+ case S6RC_STYPE_N + STYPE_BUNDLE : return &db->bundles[db->n[S6RC_STYPE_BUNDLE] + num].common ;
+ case STYPE_VIRTUAL : return &db->virtuals[num].common ;
+ case S6RC_STYPE_N + STYPE_VIRTUAL : return &db->virtuals[db->n[S6RC_STYPE_VIRTUAL] + num].common ;
+ default : return 0 ;
+ }
+}
diff --git a/src/libs6rc/s6rc_service_id.c b/src/libs6rc/s6rc_service_id.c
new file mode 100644
index 0000000..3b23161
--- /dev/null
+++ b/src/libs6rc/s6rc_service_id.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include <s6-rc/db.h>
+
+uint32_t s6rc_service_id (uint32_t const *dbn, uint8_t type, uint32_t num)
+{
+ uint32_t acc = 0 ;
+ for (uint8_t t = 0 ; t < type ; t++) acc += dbn[t] ;
+ return acc + num ;
+}
diff --git a/src/libs6rc/s6rc_service_num.c b/src/libs6rc/s6rc_service_num.c
new file mode 100644
index 0000000..a70fc82
--- /dev/null
+++ b/src/libs6rc/s6rc_service_num.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include <s6-rc/db.h>
+
+uint32_t s6rc_service_num (uint32_t const *dbn, uint32_t id)
+{
+ uint32_t num ;
+ uint8_t type ;
+ s6rc_service_typenum(dbn, id, &type, &num) ;
+ return num ;
+}
diff --git a/src/libs6rc/s6rc_service_recheck_instance.c b/src/libs6rc/s6rc_service_recheck_instance.c
new file mode 100644
index 0000000..b91ea2e
--- /dev/null
+++ b/src/libs6rc/s6rc_service_recheck_instance.c
@@ -0,0 +1,31 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/cdb.h>
+
+#include <s6-rc/db.h>
+
+int s6rc_service_recheck_instance (s6rc_db_t const *db, cdb_t *c, uint32_t *id, char const **param)
+{
+ uint8_t type ;
+ uint32_t num ;
+ s6rc_service_typenum(db->n, *id) ;
+ if (type < S6RC_STYPE_N) return 0 ;
+ else
+ {
+ s6rc_common_t *common = s6rc_service_common(db->n, type, num) ;
+ size_t namelen = strlen(db->storage + common->name) ;
+ size_t paramlen = strlen(*param) ;
+ int r ;
+ char tmp[namelen + paramlen] ;
+ memcpy(tmp, db->storage + common->name, namelen) ;
+ memcpy(tmp + namelen, *param, paramlen) ;
+ r = cdb_find(c, tmp, namelen + paramlen) ;
+ if (r <= 0) return r ;
+ }
+ uint32_unpack_big(cdb_datapos(c), id) ;
+ *param = 0 ;
+ return 1 ;
+}
diff --git a/src/libs6rc/s6rc_service_resolve.c b/src/libs6rc/s6rc_service_resolve.c
index 858f67c..52caae7 100644
--- a/src/libs6rc/s6rc_service_resolve.c
+++ b/src/libs6rc/s6rc_service_resolve.c
@@ -9,11 +9,10 @@
#include <s6-rc/db.h>
-int s6rc_service_resolve (cdb_t *c, s6rc_sid_t *id, char const *s)
+int s6rc_service_resolve (cdb_t *c, char const *s, uint32_t *id, char const **param)
{
size_t len = strlen(s) ;
- char const *param = 0 ;
- char pack[5] ;
+ char const *p = 0 ;
int r = cdb_find(c, s, len) ;
if (r < 0) return r ;
if (!r)
@@ -23,11 +22,9 @@ int s6rc_service_resolve (cdb_t *c, s6rc_sid_t *id, char const *s)
if (at == len - 1) return (errno = EINVAL, -1) ;
r = cdb_find(c, s, at + 1) ;
if (r <= 0) return r ;
- param = s + at + 1 ;
+ p = s + at + 1 ;
}
- if (cdb_read(c, pack, 5, cdb_datapos(c)) < 0) return -1 ;
- id->stype = pack[0] ;
- uint32_unpack_big(pack + 1, &id->i) ;
- id->param = param ;
+ uint32_unpack_big(cdb_datapos(c), id) ;
+ *param = p ;
return 1 ;
}
diff --git a/src/libs6rc/s6rc_service_type.c b/src/libs6rc/s6rc_service_type.c
new file mode 100644
index 0000000..aadd5a3
--- /dev/null
+++ b/src/libs6rc/s6rc_service_type.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include <s6-rc/db.h>
+
+uint8_t s6rc_service_type (uint32_t const *dbn, uint32_t id)
+{
+ uint32_t num ;
+ uint8_t type ;
+ s6rc_service_typenum(dbn, id, &type, &num) ;
+ return type ;
+}
diff --git a/src/libs6rc/s6rc_service_typenum.c b/src/libs6rc/s6rc_service_typenum.c
new file mode 100644
index 0000000..3c008c6
--- /dev/null
+++ b/src/libs6rc/s6rc_service_typenum.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include <s6-rc/db.h>
+
+void s6rc_service_typenum (uint32_t const *db, uint32_t id, uint8_t *type, uint32_t *num)
+{
+ uint8_t t = 0 ;
+ while (id >= dbn[t]) id -= dbn[t++] ;
+ *type = t ;
+ *num = id ;
+}
diff --git a/src/libs6rcd/s6rc_service_common.c b/src/libs6rcd/s6rc_service_common.c
deleted file mode 100644
index b91c902..0000000
--- a/src/libs6rcd/s6rc_service_common.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/* ISC license. */
-
-#include "db.h"
-
-s6rc_common_t const *s6rc_service_common (s6rc_db_t const *db, s6rc_id_t id)
-{
- switch (stype(id))
- {
- case STYPE_LONGRUN : return &db->longruns[snum(id)].common ;
- case STYPE_ONESHOT : return &db->oneshots[snum(id)].common ;
- case STYPE_EXTERNAL : return &db->externals[snum(id)].common ;
- case STYPE_BUNDLE : return &db->bundles[snum(id)].common ;
- case STYPE_VIRTUAL : return &db->virtuals[snum(id)].common ;
- default : return 0 ;
- }
-}
diff --git a/src/libs6rcd/s6rc_service_resolve.c b/src/libs6rcd/s6rc_service_resolve.c
deleted file mode 100644
index fe863be..0000000
--- a/src/libs6rcd/s6rc_service_resolve.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* ISC license. */
-
-#include <string.h>
-#include <errno.h>
-
-#include <skalibs/uint32.h>
-#include <skalibs/bytestr.h>
-#include <skalibs/cdb.h>
-
-#include "db.h"
-
-int s6rc_service_resolve (cdb_t *c, char const *s, s6rc_id_t *id, char const **param)
-{
- size_t len = strlen(s) ;
- char const *p = 0 ;
- char pack[5] ;
- int r = cdb_find(c, s, len) ;
- if (r < 0) return r ;
- if (!r)
- {
- size_t at = byte_chr(s, len, '@') ;
- if (at == len) return 0 ;
- if (at == len - 1) return (errno = EINVAL, -1) ;
- r = cdb_find(c, s, at + 1) ;
- if (r <= 0) return r ;
- p = s + at + 1 ;
- }
- uint32_unpack_big(cdb_datapos(c), id) ;
- *param = p ;
- return 1 ;
-}
diff --git a/src/server/client.c b/src/server/client.c
index c69794f..29ee197 100644
--- a/src/server/client.c
+++ b/src/server/client.c
@@ -51,7 +51,7 @@ void client_yoink (client_t **c)
client_t *prev = (*c)->prev ;
if (prev) prev->next = (*c)->next ; else client_head = (*c)->next ;
if ((*c)->next) (*c)->next->prev = prev ;
- if (ismonitored(*c)) nmonitors-- ;
+ if (ismonitored(*c)) client_monitors-- ;
client_free(*c) ;
*c = prev ;
client_connections-- ;
@@ -134,6 +134,19 @@ void monitor_put (uint32_t v, char const *s, size_t len)
{
if (!client_monitors) return ;
for (client_t *c = client_head ; c ; c = c->next)
- if (ismonitored(c) && v >= c->monitor_verbosity && !textmessage_put(&c->monitor, s, len))
- strerr_diefu1sys("queue message to monitor") ;
+ if (ismonitored(c) && v >= c->monitor_verbosity)
+ if (!textmessage_put(&c->monitor, s, len))
+ strerr_diefu1sys("queue message to monitor") ;
+}
+
+void monitor_announce (uint32_t id, uint8_t state)
+{
+ char pack[6] = "E" ;
+ if (!client_monitors) return ;
+ uint32_pack_big(pack + 1, id) ;
+ pack[5] = state ;
+ for (client_t *c = client_head ; c ; c = c->next)
+ if (ismonitored(c) && bitarray_peek(c->monitor_filter, id))
+ if (!textmessage_put(&c->monitor, pack, 6))
+ strerr_diefu1sys("queue message to monitor") ;
}
diff --git a/src/server/client.h b/src/server/client.h
index 4b6cccc..1acdf53 100644
--- a/src/server/client.h
+++ b/src/server/client.h
@@ -22,10 +22,11 @@ struct client_s
uint32_t xindex[2] ;
s6rc_connection_t connection ;
textmessage_sender_t monitor ;
+ unsigned char *monitor_filter ;
uint32_t monitor_verbosity ;
uint8_t perms ;
} ;
-#define CLIENT_ZERO { .next = 0, .xindex = 0, .connection = S6RC_CONNECTION_ZERO, .monitor = TEXTMESSAGE_SENDER_ZERO, .monitor_verbosity = 0, .perms = 0 }
+#define CLIENT_ZERO { .next = 0, .xindex = 0, .connection = S6RC_CONNECTION_ZERO, .monitor = TEXTMESSAGE_SENDER_ZERO, .monitor_filter = 0, .monitor_verbosity = 0, .perms = 0 }
extern tain_t client_answer_tto ;
extern client_t *client_head ;
@@ -40,7 +41,8 @@ extern int client_add (int, uint8_t) ;
/* Monitors */
extern uint32_t client_monitors ;
-extern int monitor_finish (client_t *) ;
-extern int monitor_put (uint32_t, char const *, size_t) ;
+extern void monitor_finish (client_t *) ;
+extern void monitor_put (uint32_t, char const *, size_t) ;
+extern void monitor_announce (uint32_t, uint8_t) ;
#endif
diff --git a/src/server/deps.c b/src/server/deps.c
new file mode 100644
index 0000000..fc8028d
--- /dev/null
+++ b/src/server/deps.c
@@ -0,0 +1,88 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <sys/uio.h>
+#include <errno.h>
+
+#include "db.h"
+#include "state.h"
+
+int deps_fulfilled (s6rc_db_t const *db, mstate_t const *m, s6rc_id_t id, char const *param, int h)
+{
+ s6rc_common_t const *common = s6rc_service_common(db, id) ;
+ for (uint32_t i = 0 ; i < common->ndeps[h] ; i++)
+ {
+ s6rc_id_t depid = db->deps[h][common->deps[h] + i] ;
+ sstate_t *st = sstate(m, depid, param) ;
+ uint8_t deptype = db->deptypes[h][common->deps[h] + i] ;
+ if (!(st->bits & SSTATE_WANTED) == h && stype(depid) != S6RC_STYPE_EXTERNAL && stype(depid) != S6RC_STYPE_N + S6RC_STYPE_EXTERNAL) return 0 ;
+ if (!(st->bits & SSTATE_CURRENT) != h && !(st->bits & SSTATE_TRANSITIONING)) continue ;
+ if (s6rc_deptype_soft(deptype) && st->bits & SSTATE_FAILED) continue ;
+ if (s6rc_deptype_loose(deptype) && !(st->bits & SSTATE_TRANSITIONING)) continue ;
+ return 0 ;
+ }
+ return 1 ;
+}
+
+static int sstate_zerotmp (sstate_t *st, void *arg)
+{
+ st->tmp = 0 ;
+ (void)arg ;
+ return 1 ;
+}
+
+static int instance_zerotmp (instance_t *ins, void *arg)
+{
+ return sstate_zerotmp(&ins->sstate) ;
+}
+
+typedef struct recinfo_s recinfo_t, *recinfo_t_ref ;
+struct recinfo_s
+{
+ s6rc_db_t const *db ;
+ mstate_t *m ;
+ char const *param ;
+ uint8_t h : 1 ;
+}
+
+static int mstate_dep_closure_rec (recinfo_t *recinfo, s6rc_id_t id)
+{
+ sstate_t *st = sstate(recinfo->db, recinfo->m, id, recinfo->param) ;
+ if (!st)
+ {
+ st = instance_create(recinfo->m, id, recinfo->param) ;
+ if (!st) return 0 ;
+ }
+ if (!(st->tmp & SSTATE_GRAY))
+ {
+ uint32_t ndeps = re
+ }
+}
+
+static void mstate_dep_closure (s6rc_db_t const *db, mstate_t *m, sstate_t *st, char const *param, int h)
+{
+ recinfo_t recinfo = { .db = db, .m = m, .param = param, .h = !!h } ;
+ mstate_dep_closure_rec(&recinfo, st) ;
+}
+
+int mstate_change_wanted (s6rc_db_t const *db, cdb_t *c, mstate_t *m, char const *const *args, size_t n, int h)
+{
+ mstate_iterate(m, db->n, &sstate_zerotmp, &instancelen_nop, &instance_zerotmp, 0) ;
+ for (size_t i = 0 ; i < n ; n++)
+ {
+ sstate_t *st ;
+ s6rc_id_t id ;
+ char const *param ;
+ int r = s6rc_service_resolve(c, args[i], &id, &param) ;
+ if (r < 0) return -1 ;
+ if (!r) return 1 + i ;
+ st = sstate(db, m, id, param) ;
+ if (!st) /* instance not found */
+ {
+ st = instance_create(m, id, param) ;
+ if (!st) return -1 ;
+ }
+ st->tmp |= SSTATE_MARK | SSTATE_EXPLICIT ;
+ mstate_dep_closure(db, m, st, param, h) ;
+ }
+}
diff --git a/src/server/deps.h b/src/server/deps.h
new file mode 100644
index 0000000..f8321dd
--- /dev/null
+++ b/src/server/deps.h
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#ifndef S6RCD_DEPS_H
+#define S6RCD_DEPS_H
+
+#include <stdint.h>
+
+#include "db.h"
+
+
+ /* Dependencies */
+
+#define deptype_passive(dt) ((dt) & 0x01u)
+#define deptype_soft(dt) ((dt) & 0x02u)
+#define deptype_loose(dt) ((dt) & 0x04u)
+
+extern int deps_fulfilled (s6rc_db_t const *, mstate_t const *, s6rc_id_t, char const *, int) ;
+
+#endif
diff --git a/src/server/state.c b/src/server/state.c
index d9e3f61..f106c20 100644
--- a/src/server/state.c
+++ b/src/server/state.c
@@ -11,7 +11,7 @@
#include <skalibs/buffer.h>
#include <skalibs/djbunix.h>
-#include "db.h"
+#include <s6-rc/db.h>
#include "dynstorage.h"
#include "state.h"
@@ -19,26 +19,43 @@
static sstate_t const sstate_zero = SSTATE_ZERO ;
-void instance_free (instance_t *ins)
+static inline void instance_free (instance_t *ins)
{
dynstorage_remove(ins->param) ;
}
-int instance_new (instance_t *ins, sstate_t const *st, char const *param) ;
+void instance_remove (mstate_t *m, uint8_t type, uint32_t num, char const *param)
{
- char const *s = dynstorage_add(param) ;
- if (!s) return 0 ;
- ins->state = *st ;
- inst->param = s ;
- return 1 ;
+ genalloc *g = m->dyn[type] + num ;
+ instance_t *ins = genalloc_s(instance_t, g) ;
+ uint32_t n = genalloc_len(instance_t, g) ;
+ uint32_t i = 0 ;
+ for (; i < n ; i++) if (!strcmp(param, ins[i].param)) break ;
+ if (i >= n) return ;
+ instance_free(ins + i) ;
+ ins[i] = ins[n-1] ;
+ genalloc_setlen(instance_t, g, n-1) ;
+}
+
+sstate_t *instance_create (mstate_t *m, uint8_t type, uint32_t num, char const *param)
+{
+ genalloc *g = m->dyn[type] + num ;
+ instance_t ins = { .sstate = SSTATE_ZERO, .param = dynstorage_add(param) } ;
+ if (!ins.param) return 0 ;
+ if (!genalloc_catb(instance_t, g, &ins, 1))
+ {
+ dynstorage_remove(ins.param) ;
+ return 0 ;
+ }
+ return &genalloc_s(instance_t, g)[genalloc_len(instance_t, g) - 1].sstate ;
}
void mstate_free (mstate_t *st, uint32_t const *dbn)
{
- for (size_t type = 0 ; type < S6RC_STYPE_N ; type++)
+ for (uint8_t type = 0 ; type < S6RC_STYPE_N ; type++)
{
alloc_free(st->sta[type]) ;
- for (size_t i = 0 ; i < dbn[S6RC_STYPE_N + type] ; i++)
+ for (uint32_t i = 0 ; i < dbn[S6RC_STYPE_N + type] ; i++)
{
for (size_t j = 0 ; j < genalloc_len(instance_t, st->dyn[type] + i) ; j++)
instance_free(genalloc_s(instance_t, st->dyn[type] + i) + j) ;
@@ -50,7 +67,7 @@ void mstate_free (mstate_t *st, uint32_t const *dbn)
int mstate_init (mstate_t *st, uint32_t const *dbn)
{
- size_t type = 0 ;
+ uint8_t type = 0 ;
for (; type < S6RC_STYPE_N ; type++)
{
st->sta[type] = alloc(dbn[type]) ;
@@ -73,18 +90,40 @@ int mstate_init (mstate_t *st, uint32_t const *dbn)
return 0 ;
}
-static int sstate_write (buffer *b, sstate_t const *state)
+int mstate_iterate (mstate_t *m, uint32_t const *dbn, sstate_func_ref staf, instancelen_func_ref lenf, instance_func_ref dynf, void *arg)
+{
+ for (uint8_t type = 0 ; type < S6RC_STYPE_N ; type++)
+ for (uint32_t i = 0 ; i < dbn[type] ; i++)
+ if (!staf(m->sta[type] + i, arg)) return 0 ;
+
+ for (uint8_t type = 0 ; type < S6RC_STYPE_N ; type++)
+ for (uint32_t i = 0 ; i < dbn[S6RC_STYPE_N + type] ; i++)
+ {
+ uint32_t n = genalloc_len(instance_t, m->dyn[type] + i) ;
+ instance_t const *p = genalloc_s(instance_t, m->dyn[type] + i) ;
+ if (!lenf(n, arg)) return 0 ;
+ for (size_t j = 0 ; j < n ; j++)
+ if (!dynf(p + j, arg)) goto err ;
+ }
+
+ return 1 ;
+}
+
+static int sstate_write (sstate_t *state, void *b)
{
- return buffer_put(b, (char *)state->bits, 1) == 1 ;
+ return buffer_put((buffer *)b, (char *)&state->bits, 1) == 1 ;
}
-static int sstate_read (buffer *b, sstate_t *state)
+static int instancelen_write (uint32_t n, void *b)
{
- return buffer_get(b, (char *)state->bits, 1) == 1 ;
+ char pack[4] ;
+ uint32_pack_big(pack, n) ;
+ return buffer_put((buffer *)b, pack, 4) == 4 ;
}
-static inline int instance_write (buffer *b, instance_t const *ins)
+static int instance_write (instance_t *ins, void *arg)
{
+ buffer *b = arg ;
uint32_t len = strlen(ins->param) ;
char pack[4] ;
uint32_pack_big(pack, len) ;
@@ -94,29 +133,7 @@ static inline int instance_write (buffer *b, instance_t const *ins)
return 1 ;
}
-static inline int instance_read (buffer *b, instance_t *ins)
-{
- sstate_t st ;
- char const *p ;
- uint32_t len ;
- char pack[4] ;
- if (!sstate_read(b, &st)) return 0 ;
- if (buffer_get(&b, pack, 4) < 4) return 0 ;
- uint32_unpack_big(pack, &len) ;
- if (len > S6RC_INSTANCE_MAXLEN) return (errno = EPROTO, 0) ;
- {
- char param[len + 1] ;
- if (buffer_get(&b, param, len + 1) < len + 1) return 0 ;
- if (param[len]) return (errno = EPROTO, 0) ;
- p = dynstorage_add(param) ;
- if (!p) return 0 ;
- }
- ins->sstate = st ;
- ins->param = p ;
- return 1 ;
-}
-
-int mstate_write (char const *file, mstate_t const *st, uint32_t const *dbn)
+int mstate_write (char const *file, mstate_t const *m, uint32_t const *dbn)
{
size_t filelen = strlen(file) ;
int fd ;
@@ -128,23 +145,7 @@ int mstate_write (char const *file, mstate_t const *st, uint32_t const *dbn)
fd = mkstemp(fn) ;
if (fd == -1) return 0 ;
buffer_init(&b, &buffer_write, fd, buf, 1024) ;
-
- for (size_t type = 0 ; type < S6RC_STYPE_N ; type++)
- for (uint32_t i = 0 ; i < dbn[type] ; i++)
- if (!sstate_write(&b, st->sta[type] + i)) goto err ;
-
- for (size_t type = 0 ; type < S6RC_STYPE_N ; type++)
- for (uint32_t i = 0 ; i < dbn[S6RC_STYPE_N + type] ; i++)
- {
- uint32_t n = genalloc_len(instance_t, st->dyn[type] + i) ;
- instance_t const *p = genalloc_s(instance_t, st->dyn[type] + i) ;
- char pack[4] ;
- uint32_pack_big(pack, n) ;
- if (buffer_put(&b, pack, 4) < 4) goto err ;
- for (uint32_t j = 0 ; j < n ; j++)
- if (!instance_write(&b, p + j)) goto err ;
- }
-
+ if (!mstate_iterate(m, &sstate_write, &instancelen_write, &instance_write, &b)) goto err ;
if (!buffer_flush(&b)) goto err ;
fd_close(fd) ;
if (rename(fn, file) == -1) goto err0 ;
@@ -157,6 +158,33 @@ int mstate_write (char const *file, mstate_t const *st, uint32_t const *dbn)
return 0 ;
}
+static int sstate_read (buffer *b, sstate_t *state)
+{
+ return buffer_get(b, (char *)&state->bits, 1) == 1 ;
+}
+
+static int instance_read (buffer *b, instance_t *ins)
+{
+ sstate_t st ;
+ char const *p ;
+ uint32_t len ;
+ char pack[4] ;
+ if (!sstate_read(b, &st)) return 0 ;
+ if (buffer_get(&b, pack, 4) < 4) return 0 ;
+ uint32_unpack_big(pack, &len) ;
+ if (len > S6RC_INSTANCE_MAXLEN) return (errno = EPROTO, 0) ;
+ {
+ char param[len + 1] ;
+ if (buffer_get(&b, param, len + 1) < len + 1) return 0 ;
+ if (param[len]) return (errno = EPROTO, 0) ;
+ p = dynstorage_add(param) ;
+ if (!p) return 0 ;
+ }
+ ins->sstate = st ;
+ ins->param = p ;
+ return 1 ;
+}
+
int mstate_read (char const *file, mstate_t *st, uint32_t const *dbn)
{
int fd ;
@@ -167,11 +195,11 @@ int mstate_read (char const *file, mstate_t *st, uint32_t const *dbn)
if (fd == -1) goto err0 ;
buffer_init(&b, &buffer_read, fd, buf, 1024) ;
- for (size_t type = 0 ; type < S6RC_STYPE_N ; type++)
+ for (uint8_t type = 0 ; type < S6RC_STYPE_N ; type++)
for (uint32_t i = 0 ; i < dbn[type] ; i++)
if (!sstate_read(&b, st->sta[type] + i)) goto err ;
- for (size_t type = 0 ; type < S6RC_STYPE_N ; type++)
+ for (uint8_t type = 0 ; type < S6RC_STYPE_N ; type++)
for (uint32_t i = 0 ; i < dbn[S6RC_STYPE_N + type] ; i++)
{
uint32_t n ;
@@ -180,7 +208,7 @@ int mstate_read (char const *file, mstate_t *st, uint32_t const *dbn)
uint32_unpack_big(pack, &n) ;
if (n > S6RC_INSTANCES_MAX) goto eproto ;
if (!genalloc_ready(instance_t, st->dyn[type] + i, n)) goto err ;
- for (uint32_t j = 0 ; j < n ; j++)
+ for (size_t j = 0 ; j < n ; j++)
if (!instance_read(&b, genalloc_s(instance_t, st->dyn[type] + i) + j)) goto err ;
genalloc_setlen(instance_t, st->dyn[type] + i, n) ;
}
@@ -206,25 +234,32 @@ int mstate_read (char const *file, mstate_t *st, uint32_t const *dbn)
return 0 ;
}
-sstate_t *sstate (mstate_t const *m, s6rc_id_t id, char const *param)
+sstate_t *sstate_tn (mstate_t *m, uint8_t type, uint32_t num, char const *param)
{
- if (stype(id) >= S6RC_STYPE_N)
+ if (type >= S6RC_STYPE_N)
{
- size_t n = genalloc_len(instance_t, st->dyn[stype(id)] + snum(id)) ;
- instance_t *instances = genalloc_s(instance_t, st->dyn[stype(id)] + snum(id)) ;
+ size_t n = genalloc_len(instance_t, m->dyn[type] + num) ;
+ instance_t *instances = genalloc_s(instance_t, m->dyn[type] + num) ;
for (size_t i = 0 ; i < n ; i++)
if (!strcmp(param, instances[i].param)) return &instances[i].sstate ;
- return STATE_PHAIL ;
+ return 0 ;
}
- else return st->sta[stype(id)] + snum(id) ;
+ else return m->sta[type] + num ;
}
-int state_deps_fulfilled (s6rc_db_t const *db, mstate_t const *m, s6rc_id_t id, char const *param, int h)
+sstate_t *sstate (uint32_t const *dbn, mstate_t *m, uint32_t id, char const *param)
{
- s6rc_common_t const *common = s6rc_service_common(db, id) ;
- for (uint32_t i = 0 ; i < common->ndeps[h] ; i++)
- {
- uint8_t deptype = db->deptypes[h][common->deps[h] + i] ;
- sstate_t *st = sstate(m, db->deps[h][common->deps[h] + i], param) ;
- }
+ uint32_t num ;
+ uint8_t type ;
+ s6rc_service_typenum(dbn, id, &type, &num) ;
+ return sstate_tn(m, type, num, param) ;
}
+
+static int instancelen_nop_ (uint32_t n, void *arg)
+{
+ (void)n ;
+ (void)arg ;
+ return 1 ;
+}
+
+instancelen_func_ref const instancelen_nop = &instancelen_nop_ ;
diff --git a/src/server/state.h b/src/server/state.h
index 2084437..9831115 100644
--- a/src/server/state.h
+++ b/src/server/state.h
@@ -11,23 +11,27 @@
/* Service states, instances, machine state */
-#define SSTATE_STABLE 0x00u
-#define SSTATE_WAITING 0x01u
-#define SSTATE_TRANSITIONING 0x02u
-#define SSTATE_FAILED 0x03u
-
+ /* bits */
+#define SSTATE_TRANSITIONING 0x01u
+#define SSTATE_FAILED 0x02u
#define SSTATE_CURRENT 0x04u
#define SSTATE_WANTED 0x08u
#define SSTATE_EXPLICIT 0x10u
-#define SSTATE_GRAY 0x20u
-#define SSTATE_BLACK 0x40u
#define SSTATE_INVALID 0x80u
+ /* tmp */
+#define SSTATE_GRAY 0x01u
+#define SSTATE_BLACK 0x02u
+#define SSTATE_MARK 0x04u
+#define SSTATE_EXPLICIT 0x08u
+
typedef struct sstate_s sstate_t, *sstate_t_ref ;
struct sstate_s
{
- uint8_t bits ;
+ uint8_t bits ; /* the real state, saved to the fs */
+ uint8_t tmp ; /* bits used for computations e.g. recursive dep walks */
}
+#define SSTATE_ZERO { .bits = 0, .tmp = 0 }
typedef struct instance_s instance_t, *instance_t_ref ;
struct instance_s
@@ -43,8 +47,17 @@ struct mstate_s
genalloc *dyn[S6RC_STYPE_N] ; /* every genalloc is a list of instance_t */
} ;
-extern void instance_free (instance_t *) ;
-extern int instance_new (instance_t *, uint8_t *, char const *) ;
+typedef int sstate_func (sstate_t *, void *) ;
+typedef sstate_func *sstate_func_ref ;
+typedef int instancelen_func (uint32_t, void *) ;
+typedef instancelen_func *instancelen_func_ref ;
+typedef instance_func (instance_t *, void *) ;
+typedef instance_func *instance_func_ref ;
+
+extern instancelen_func_ref const instancelen_nop ;
+
+extern sstate_t *instance_create (mstate_t *, s6rc_id_t, char const *) ;
+extern void instance_remove (mstate_t *, s6rc_id_t, char const *) ;
extern void mstate_free (mstate_t *, uint32_t const *) ;
extern int mstate_init (mstate_t *, uint32_t const *) ;
@@ -52,7 +65,9 @@ extern int mstate_init (mstate_t *, uint32_t const *) ;
extern int mstate_write (char const *, mstate_t const *, uint32_t const *) ;
extern int mstate_read (char const *, mstate_t *, uint32_t const *) ; /* also inits */
-extern sstate_t *sstate_get (s6rc_db_t const *, mstate_t const *, s6rc_id_t, char const *) ;
-extern int sstate_deps_fulfilled (s6rc_db_t const *, mstate_t const *, s6rc_id_t, char const *, int) ;
+extern int mstate_iterate (mstate_t *, uint32_t const *, sstate_func_ref, instancelen_func_ref, instance_func_ref, void *) ;
+
+extern sstate_t *sstate_tn (mstate_t *, uint8_t, uint32_t, char const *) ;
+extern sstate_t *sstate (uint32_t const *, mstate_t *, uint32_t, char const *) ;
#endif