summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-06-28 17:26:47 +0000
committerLaurent Bercot <ska@appnovation.com>2021-06-28 17:26:47 +0000
commitae1a76cad535a04f0c059e8dae9c8a27a84222a4 (patch)
tree91648546a5c588a5f0e68ef530d311e594440f4e
parentc26824e1f078b8de0d38cb87d3f291235ab5cf76 (diff)
downloads6-rc-ae1a76cad535a04f0c059e8dae9c8a27a84222a4.tar.xz
Some more code around state
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--src/include/s6-rc/db.h110
-rw-r--r--src/include/s6-rc/event.h5
-rw-r--r--src/libs6rc/s6rc_service_common.c19
-rw-r--r--src/libs6rc/s6rc_service_resolve.c33
-rw-r--r--src/server/service.h108
-rw-r--r--src/server/state.c122
-rw-r--r--src/server/state.h45
-rw-r--r--src/server/transition.h24
8 files changed, 291 insertions, 175 deletions
diff --git a/src/include/s6-rc/db.h b/src/include/s6-rc/db.h
index 0f03967..8953a49 100644
--- a/src/include/s6-rc/db.h
+++ b/src/include/s6-rc/db.h
@@ -1,23 +1,53 @@
/* ISC license. */
-#ifndef S6RC_DB_H
-#define S6RC_DB_H
+#ifndef S6RC_SERVICE_H
+#define S6RC_SERVICE_H
#include <stdint.h>
-#include <skalibs/diuint32.h>
-#include <skalibs/buffer.h>
-#define S6RC_DB_BANNER_START "s6rc-db: start\n"
-#define S6RC_DB_BANNER_START_LEN (sizeof(S6RC_DB_BANNER_START) - 1)
-#define S6RC_DB_BANNER_END "\ns6rc-db: end\n"
-#define S6RC_DB_BANNER_END_LEN (sizeof(S6RC_DB_BANNER_END) - 1)
-#define S6RC_DB_FLAG_ESSENTIAL 0x00000001U
+ /* Service types and db representation in memory */
+typedef enum s6rc_stype_e s6rc_stype_t, *s6rc_stype_t_ref ;
+enum s6rc_stype_e
+{
+ S6RC_STYPE_LONGRUN,
+ S6RC_STYPE_ONESHOT,
+ S6RC_STYPE_EXTERNAL,
+ S6RC_STYPE_BUNDLE,
+ S6RC_STYPE_VIRTUAL,
+ S6RC_STYPE_PHAIL
+} ;
+
+typedef struct s6rc_sid_s s6rc_sid_t, *s6rc_sid_t_ref ;
+struct s6rc_sid_s
+{
+ uint32_t i ;
+ char const *param ;
+ s6rc_stype_t stype ;
+} ;
+
+typedef struct s6rc_common_s s6rc_common_t, *s6rc_common_t_ref ;
+struct s6rc_common_s
+{
+ uint32_t name ;
+ uint32_t deps[2] ;
+ uint32_t ndeps[2] ;
+ uint32_t flag_essential : 1 ;
+ uint32_t flags : 31 ;
+} ;
+
+typedef struct s6rc_atomic_s s6rc_atomic_t, *s6rc_atomic_t_ref ;
+struct s6rc_atomic_s
+{
+ s6rc_common_t common ;
+ 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 argc[2] ;
uint32_t argv[2] ;
} ;
@@ -25,52 +55,52 @@ struct s6rc_oneshot_s
typedef struct s6rc_longrun_s s6rc_longrun_t, *s6rc_longrun_t_ref ;
struct s6rc_longrun_s
{
- uint32_t consumer ;
+ s6rc_atomic_t satomic ;
+ s6rc_sid_t consumer ;
uint32_t nproducers ;
uint32_t producers ;
} ;
-typedef union s6rc_longshot_u s6rc_longshot_t, *s6rc_longshot_t_ref ;
-union s6rc_longshot_u
+typedef struct s6rc_external_s s6rc_external_t, *s6rc_external_t_ref ;
+struct s6rc_external_s
{
- s6rc_oneshot_t oneshot ;
- s6rc_longrun_t longrun ;
+ s6rc_common_t common ;
} ;
-typedef struct s6rc_service_s s6rc_service_t, *s6rc_service_t_ref ;
-struct s6rc_service_s
+typedef struct s6rc_bundle_s s6rc_bundle_t, *s6rc_bundle_t_ref ;
+struct s6rc_bundle_s
{
- uint32_t name ;
- uint32_t flags ;
- uint32_t deps[2] ;
- uint32_t ndeps[2] ;
- uint32_t timeout[2] ;
- s6rc_longshot_t x ;
+ s6rc_common_t common ;
+ uint32_t ncontents ;
+ uint32_t contents ;
+} ;
+
+typedef struct s6rc_deptype_s s6rc_deptype_t, *s6rc_deptype_t_ref ;
+struct s6rc_deptype_s
+{
+ uint8_t passive : 1 ;
+ uint8_t soft : 1 ;
+ uint8_t loose : 1 ;
} ;
typedef struct s6rc_db_s s6rc_db_t, *s6rc_db_t_ref ;
struct s6rc_db_s
{
- s6rc_service_t *services ;
- unsigned int nshort ;
- unsigned int nlong ;
- unsigned int stringlen ;
- unsigned int nargvs ;
- unsigned int ndeps ;
- unsigned int nproducers ;
- char *string ;
+ uint32_t ntotal ;
+ uint32_t n[STYPE_PHAIL << 1] ;
+ uint32_t storagelen ;
+ s6rc_longrun_t *longruns ;
+ s6rc_oneshot_t *oneshots ;
+ s6rc_external_t *externals ;
+ s6rc_bundle_t *bundles ;
+ s6rc_bundle_t *virtuals ;
+ s6rc_sid_t *deps[2] ;
+ s6rc_deptype_t *deptypes[2] ;
+ s6rc_sid_t *producers ;
char const **argvs ;
- uint32_t *deps ;
- uint32_t *producers ;
+ char *storage ;
} ;
-extern int s6rc_db_read_uint32 (buffer *, uint32_t *) ;
-
-extern int s6rc_db_read_sizes (int, s6rc_db_t *) ;
-extern int s6rc_db_read (int, s6rc_db_t *) ;
-
-extern int s6rc_db_check_pipelines (s6rc_db_t const *, diuint32 *) ;
-extern int s6rc_db_check_depcycles (s6rc_db_t const *, int, diuint32 *) ;
-extern int s6rc_db_check_revdeps (s6rc_db_t const *) ;
+extern s6rc_common_t const *s6rc_service_common (s6rc_db_t const *, s6rc_sid_t const *) ;
#endif
diff --git a/src/include/s6-rc/event.h b/src/include/s6-rc/event.h
index f99b571..864c90c 100644
--- a/src/include/s6-rc/event.h
+++ b/src/include/s6-rc/event.h
@@ -9,11 +9,10 @@ typedef struct s6rc_event_s s6rc_event_t, *s6rc_event_t_ref ;
struct s6rc_event_s
{
uint32_t name ;
- uint32_t instance ;
- uint8_t wanted : 1 ;
+ uint8_t current : 1 ;
uint8_t up : 1 ;
uint8_t extra : 6 ;
} ;
-#define S6RC_EVENT_ZERO { .name = 0, .instance = 0, .wanted = 0, .updown = 0, .extra = 0 }
+#define S6RC_EVENT_ZERO { .name = 0, .current = 0, .up = 0, .extra = 0 }
#endif
diff --git a/src/libs6rc/s6rc_service_common.c b/src/libs6rc/s6rc_service_common.c
new file mode 100644
index 0000000..f3146be
--- /dev/null
+++ b/src/libs6rc/s6rc_service_common.c
@@ -0,0 +1,19 @@
+/* ISC license. */
+
+#include <stdint.h>
+
+#include <s6-rc/db.h>
+
+s6rc_common_t const *s6rc_service_common (s6rc_db_t const *db, s6rc_sid_t const *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 ;
+ }
+}
diff --git a/src/libs6rc/s6rc_service_resolve.c b/src/libs6rc/s6rc_service_resolve.c
new file mode 100644
index 0000000..858f67c
--- /dev/null
+++ b/src/libs6rc/s6rc_service_resolve.c
@@ -0,0 +1,33 @@
+/* ISC license. */
+
+#include <string.h>
+#include <errno.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/cdb.h>
+
+#include <s6-rc/db.h>
+
+int s6rc_service_resolve (cdb_t *c, s6rc_sid_t *id, char const *s)
+{
+ size_t len = strlen(s) ;
+ char const *param = 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 ;
+ param = 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 ;
+ return 1 ;
+}
diff --git a/src/server/service.h b/src/server/service.h
deleted file mode 100644
index 86ee341..0000000
--- a/src/server/service.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ISC license. */
-
-#ifndef S6RCD_SERVICE_H
-#define S6RCD_SERVICE_H
-
-#include <stdint.h>
-
-#include <skalibs/stralloc.h>
-
-
- /* Service types and db representation in memory */
-
-typedef enum stype_e stype_t, *stype_t_ref ;
-enum stype_e
-{
- STYPE_LONGRUN,
- STYPE_ONESHOT,
- STYPE_EXTERNAL,
- STYPE_BUNDLE,
- STYPE_VIRTUAL,
- STYPE_PHAIL
-} ;
-
-typedef struct common_s common_t, *common_t_ref ;
-struct common_s
-{
- uint32_t name ;
- uint32_t deps[2] ;
- uint32_t ndeps[2] ;
- uint32_t flag_dynamic : 1 ;
- uint32_t flag_essential : 1 ;
- uint32_t flags : 30 ;
-} ;
-
-typedef struct satomic_s satomic_t, *satomic_t_ref ;
-struct satomic_s
-{
- common_t common ;
- uint32_t timeout[2] ;
-} ;
-
-typedef struct oneshot_s oneshot_t, *oneshot_t_ref ;
-struct oneshot_s
-{
- satomic_t satomic ;
- uint32_t argc[2] ;
- uint32_t argv[2] ;
-} ;
-
-typedef struct longrun_s longrun_t, *longrun_t_ref ;
-struct longrun_s
-{
- satomic_t satomic ;
- uint32_t consumer ;
- uint32_t nproducers ;
- uint32_t producers ;
-} ;
-
-typedef struct external_s external_t, *external_t_ref ;
-struct external_s
-{
- common_t common ;
-} ;
-
-typedef struct bundle_s bundle_t, *bundle_t_ref ;
-struct bundle_s
-{
- common_t common ;
- uint32_t ncontents ;
- uint32_t contents ;
-} ;
-
-typedef struct virtual_s virtual_t, *virtual_t_ref ;
-struct virtual_s
-{
- common_t common ;
- uint32_t ncontents ;
- uint32_t contents ;
-} ;
-
-typedef struct deptype_s deptype_t, *deptype_t_ref ;
-struct deptype_s
-{
- uint8_t passive : 1 ;
- uint8_t soft : 1 ;
- uint8_t loose : 1 ;
-} ;
-
-typedef struct db_s db_t, *db_t_ref ;
-struct db_s
-{
- uint32_t n[STYPE_PHAIL] ;
- longrun_t *longruns ;
- oneshot_t *oneshots ;
- external_t *externals ;
- bundle_t *bundles ;
- virtual_t *virtuals ;
- char const **argvs ;
- uint32_t *deps[2] ;
- deptype_t *deptypes[2] ;
- uint32_t *producers ;
- char *storage ;
- uint32_t storagelen ;
-} ;
-
-extern common_t const *service_common (db_t const *, stype_t, uint32_t) ;
-
-#endif
diff --git a/src/server/state.c b/src/server/state.c
new file mode 100644
index 0000000..0e2afe3
--- /dev/null
+++ b/src/server/state.c
@@ -0,0 +1,122 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <skalibs/alloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+
+#include <s6-rc/db.h>
+#include "state.h"
+
+void state_free (state_t *st, uint32_t const *dbn)
+{
+ for (s6rc_stype_t type = S6RC_STYPE_LONGRUN ; type < S6RC_STYPE_PHAIL ; type++)
+ {
+ alloc_free(st->sta[type]) ;
+ for (size_t i = 0 ; i < dbn[S6RC_STYPE_PHAIL + type] ; i++)
+ genalloc_free(instance_t, st->dyn[type] + i) ;
+ alloc_free(st->dyn[type]) ;
+ }
+}
+
+int state_ready (state_t *st, uint32_t const *dbn)
+{
+ s6rc_stype_t type = 0 ;
+ for (; type < S6RC_STYPE_PHAIL ; type++)
+ {
+ genalloc *q ;
+ stateatom_t *p = alloc(sizeof(stateatom_t) * dbn[type]) ;
+ if (!p) goto err ;
+ q = alloc(sizeof(genalloc) * dbn[S6RC_STYPE_PHAIL + type]) ;
+ if (!q) { alloc_free(p) ; goto err ; }
+ st->sta[type] = p ;
+ for (size_t i = 0 ; i < dbn[S6RC_STYPE_PHAIL + type] ; i++) q[i] = genalloc_zero ;
+ st->dyn[type] = q ;
+ }
+ return 1 ;
+
+ err:
+ while (type--)
+ {
+ alloc_free(st->dyn[type]) ;
+ alloc_free(st->sta[type]) ;
+ }
+ return 0 ;
+}
+
+stateatom_t *state_atom (state_t const *st, s6rc_sid_t const *id)
+{
+ if (id->param)
+ {
+ size_t n = genalloc_len(instance_t, st->dyn[id->stype] + id->i) ;
+ instance_t *instances = genalloc_s(instance_t, st->dyn[id->stype] + id->i) ;
+ for (size_t i = 0 ; i < n ; i++)
+ if (!strcmp(id->param, instances[i].param)) return &instances[i].state ;
+ return 0 ;
+ }
+ else return st->sta[id->stype] + id->i ;
+}
+
+static int atom_write (buffer *b, stateatom_t const *state)
+{
+ char c = state->wanted | (state->current << 1) | (state->transitioning << 2) ;
+ return buffer_put(b, &c, 1) == 1 ;
+}
+
+int state_write (char const *file, state_t const *st, uint32_t const *dbn)
+{
+ size_t filelen = strlen(file) ;
+ int fd ;
+ buffer b ;
+ char buf[1024] ;
+ char fn[filelen + 12] ;
+ memcpy(fn, file, filelen) ;
+ memcpy(fn + filelen, ":tmp:XXXXXX", 12) ;
+ fd = mkstemp(fn) ;
+ if (fd == -1) return 0 ;
+ buffer_init(&b, &buffer_write, fd, buf, 1024) ;
+
+ for (s6rc_stype_t type = 0 ; type < S6RC_STYPE_PHAIL ; type++)
+ {
+ char pack[4] ;
+ uint32_pack_big(pack, dbn[type]) ;
+ if (buffer_put(&b, pack, 4) < 4) goto err ;
+ }
+ for (s6rc_stype_t type = 0 ; type < S6RC_STYPE_PHAIL ; type++)
+ {
+ for (uint32_t i = 0 ; i < dbn[type] ; i++)
+ if (!atom_write(&b, st->sta[type] + i)) goto err ;
+ for (uint32_t i = 0 ; i < dbn[S6RC_STYPE_PHAIL + 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++)
+ {
+ uint32_t len = strlen(p[j].param) ;
+ uint32_pack_big(pack, len) ;
+ if (!atom_write(&p[j].state)) goto err ;
+ if (buffer_put(&b, pack, 4) < 4) goto err ;
+ if (buffer_put(&b, p[j].param, len+1) < len+1) goto err ;
+ }
+ }
+ }
+
+ if (!buffer_flush(&b)) goto err ;
+ fd_close(fd) ;
+ if (rename(fn, file) == -1) goto err0 ;
+ return 1 ;
+
+ err:
+ fd_close(fd) ;
+ err0:
+ unlink_void(fn) ;
+ return 0 ;
+}
diff --git a/src/server/state.h b/src/server/state.h
new file mode 100644
index 0000000..f0149bc
--- /dev/null
+++ b/src/server/state.h
@@ -0,0 +1,45 @@
+/* ISC license. */
+
+#ifndef S6RCD_STATE_H
+#define S6RCD_STATE_H
+
+#include <skalibs/genalloc.h>
+
+#include <s6-rc/db.h>
+
+
+ /* Service states, instances, machine state */
+
+typedef struct stateatom_s stateatom_t, *stateatom_t_ref ;
+struct stateatom_s
+{
+ uint8_t wanted : 1 ;
+ uint8_t current : 1 ;
+ uint8_t transitioning : 1 ;
+} ;
+
+typedef struct instance_s instance_t, *instance_t_ref ;
+struct instance_s
+{
+ char const *param ;
+ stateatom_t state ;
+} ;
+
+typedef struct state_s state_t, *state_t_ref ;
+struct state_s
+{
+ stateatom_t *sta[S6RC_STYPE_PHAIL] ;
+ genalloc *dyn[S6RC_STYPE_PHAIL] ; /* every genalloc is a list of instance_t */
+} ;
+
+extern void state_free (state_t *, uint32_t const *) ;
+extern int state_ready (state_t *, uint32_t const *) ;
+
+extern int state_write (char const *, state_t const *, uint32_t const *) ;
+extern int state_read (char const *, state_t *, uint32_t const *) ;
+
+
+extern stateatom_t *state_atom (s6rc_db_t const *, state_t const *, s6rc_sid_t const *) ;
+
+
+#endif
diff --git a/src/server/transition.h b/src/server/transition.h
deleted file mode 100644
index 3ade951..0000000
--- a/src/server/transition.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ISC license. */
-
-#ifndef S6RCD_TRANSITION_H
-#define S6RCD_TRANSITION_H
-
-#include <sys/types.h>
-#include <stdint.h>
-
-
- /* Transitions */
-
-typedef struct transition_s transition_t, *transition_t_ref ;
-struct transition_s
-{
- pid_t pid ;
- uint32_t service ;
- uint8_t updown : 1 ;
-} ;
-#define TRANSITION_ZERO { .pid = 0, .service = 0, }
-
-extern uint32_t ntransitions ;
-transitions_t *transitions ;
-
-#endif