diff options
author | José Bollo <jose.bollo@iot.bzh> | 2019-05-24 12:21:33 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2019-05-24 12:21:33 +0200 |
commit | 395cd2eb66909c4396cdd7a3ae2ad8e4c5ec6ee8 (patch) | |
tree | 679d9b77ddf7b5b77163a901b7eacd4b4e7edf44 | |
parent | c715090f1faaa2ec53ee84895d61c7f72fcd4772 (diff) |
Add cacheid
The idea is to allow a client to disconnect
and reconnect without losing its cache.
Change-Id: I017176e5eb5f553b961a32ee466d1b7a175532bb
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | src/agent-at.c | 1 | ||||
-rw-r--r-- | src/cache.c | 14 | ||||
-rw-r--r-- | src/cache.h | 3 | ||||
-rw-r--r-- | src/cyn.c | 46 | ||||
-rw-r--r-- | src/cyn.h | 14 | ||||
-rw-r--r-- | src/db.c | 2 | ||||
-rw-r--r-- | src/main-cynarad.c | 27 | ||||
-rw-r--r-- | src/rcyn-client.c | 36 | ||||
-rw-r--r-- | src/rcyn-client.h | 6 | ||||
-rw-r--r-- | src/rcyn-protocol.txt | 4 | ||||
-rw-r--r-- | src/rcyn-server.c | 4 |
11 files changed, 116 insertions, 41 deletions
diff --git a/src/agent-at.c b/src/agent-at.c index f671fc7..02bcc6c 100644 --- a/src/agent-at.c +++ b/src/agent-at.c @@ -16,6 +16,7 @@ */ #include <stdlib.h> +#include <stdint.h> #include <stdbool.h> #include <time.h> #include <string.h> diff --git a/src/cache.c b/src/cache.c index b57536d..c8e7550 100644 --- a/src/cache.c +++ b/src/cache.c @@ -60,10 +60,11 @@ typedef struct item item_t; /** * The cache structure is a blob of memory ('content') * of 'count' bytes of only 'used' bytes. - * That blob containts at sequence of records of variable length + * That blob contains at sequence of records of variable length */ struct cache { + uint32_t cacheid; uint32_t used; uint32_t count; uint8_t content[1]; @@ -264,10 +265,13 @@ cache_search( void cache_clear( - cache_t *cache + cache_t *cache, + uint32_t cacheid ) { - if (cache) + if (cache && (!cacheid || cache->cacheid != cacheid)) { + cache->cacheid = cacheid; cache->used = 0; + } } int @@ -286,8 +290,10 @@ cache_resize( return -ENOMEM; nc->count = newsize; - if (!c) + if (!c) { + nc->cacheid = 0; nc->used = 0; + } *cache = nc; return 0; } diff --git a/src/cache.h b/src/cache.h index bf85e8e..4ddaa1e 100644 --- a/src/cache.h +++ b/src/cache.h @@ -39,7 +39,8 @@ cache_put( extern void cache_clear( - cache_t *cache + cache_t *cache, + uint32_t cacheid ); extern @@ -17,6 +17,7 @@ #include <assert.h> #include <stdlib.h> +#include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <string.h> @@ -52,6 +53,9 @@ static const void *lock; static struct callback *awaiters; static struct callback *observers; static struct agent *agents; +static uint32_t last_changeid; +static uint32_t last_changeid_string; +static char changeid_string[12]; static int @@ -92,6 +96,17 @@ addcb( return 0; } +static +void +changed( +) { + struct callback *c; + + ++last_changeid; + for (c = observers; c ; c = c->next) + c->on_change_cb(c->closure); +} + /** enter critical recoverable section */ int cyn_enter( @@ -147,7 +162,7 @@ cyn_leave( bool commit ) { int rc, rcp; - struct callback *c, *e, **p; + struct callback *e, **p; if (!magic) return -EINVAL; @@ -164,10 +179,8 @@ cyn_leave( if (rc == 0) { rcp = queue_play(); rc = db_transaction_end(rcp == 0) ?: rcp; - if (rcp == 0) { - for (c = observers; c ; c = c->next) - c->on_change_cb(c->closure); - } + if (rcp == 0) + changed(); } } queue_clear(); @@ -472,3 +485,26 @@ cyn_agent_remove( free(agent); return 0; } + +void +cyn_changeid_reset( +) { + last_changeid = 1; +} + +uint32_t +cyn_changeid( +) { + return last_changeid; +} + +extern +const char * +cyn_changeid_string( +) { + if (last_changeid != last_changeid_string) { + last_changeid_string = last_changeid; + snprintf(changeid_string, sizeof changeid_string, "%u", last_changeid); + } + return changeid_string; +}
\ No newline at end of file @@ -128,3 +128,17 @@ cyn_agent_remove( const char *name ); +extern +void +cyn_changeid_reset( +); + +extern +uint32_t +cyn_changeid( +); + +extern +const char * +cyn_changeid_string( +); @@ -55,7 +55,7 @@ db_open( rc = memdb_create(&memdb); if (!rc) { - rc = filedb_create(&filedb, directory, "CYNARA"); + rc = filedb_create(&filedb, directory, NULL); if (rc) anydb_destroy(memdb); } diff --git a/src/main-cynarad.c b/src/main-cynarad.c index 75b0169..19f0f4d 100644 --- a/src/main-cynarad.c +++ b/src/main-cynarad.c @@ -38,6 +38,7 @@ #include "data.h" #include "db.h" +#include "cyn.h" #include "rcyn-server.h" #include "rcyn-protocol.h" #include "dbinit.h" @@ -303,21 +304,8 @@ int main(int ac, char **av) cap_clear(caps); rc = cap_set_proc(caps); - /* initialize server */ - signal(SIGPIPE, SIG_IGN); /* avoid SIGPIPE! */ - rc = rcyn_server_create(&server, spec_socket_admin, spec_socket_check, spec_socket_agent); - if (rc < 0) { - fprintf(stderr, "can't initialise server: %m\n"); - return 1; - } - /* connection to the database */ - rc = chdir(dbdir); - if (rc < 0) { - fprintf(stderr, "can not chroot to database directory %s: %m\n", dbdir); - return 1; - } - rc = db_open("."); + rc = db_open(dbdir); if (rc < 0) { fprintf(stderr, "can not open database of directory %s: %m\n", dbdir); return 1; @@ -332,6 +320,17 @@ int main(int ac, char **av) } } + /* reset the change ids */ + cyn_changeid_reset(); + + /* initialize server */ + signal(SIGPIPE, SIG_IGN); /* avoid SIGPIPE! */ + rc = rcyn_server_create(&server, spec_socket_admin, spec_socket_check, spec_socket_agent); + if (rc < 0) { + fprintf(stderr, "can't initialise server: %m\n"); + return 1; + } + /* ready ! */ #if defined(WITH_SYSTEMD_ACTIVATION) if (systemd) diff --git a/src/rcyn-client.c b/src/rcyn-client.c index baffb83..575d72c 100644 --- a/src/rcyn-client.c +++ b/src/rcyn-client.c @@ -256,19 +256,23 @@ int get_reply( rcyn_t *rcyn ) { + ; int rc; prot_next(rcyn->prot); - rc = rcyn->reply.count = prot_get(rcyn->prot, &rcyn->reply.fields); - if (rc <= 0) - return rc; - if (0 != strcmp(rcyn->reply.fields[0], _clear_)) { - if (0 != strcmp(rcyn->reply.fields[0], _item_)) - rcyn->pending--; - return rc; + rc = prot_get(rcyn->prot, &rcyn->reply.fields); + if (rc > 0) { + if (0 == strcmp(rcyn->reply.fields[0], _clear_)) { + cache_clear(rcyn->cache, + rc > 1 ? (uint32_t)atol(rcyn->reply.fields[1]) : 0); + rc = 0; + } else { + if (0 != strcmp(rcyn->reply.fields[0], _item_)) + rcyn->pending--; + } } - cache_clear(rcyn->cache); - return rcyn->reply.count = 0; + rcyn->reply.count = rc; + return rc; } static @@ -406,7 +410,6 @@ connection( /* init the client */ rcyn->pending = 0; rcyn->reply.count = -1; - cache_clear(rcyn->cache); prot_reset(rcyn->prot); rcyn->fd = socket_open(rcyn->socketspec, 0); if (rcyn->fd < 0) @@ -418,9 +421,11 @@ connection( rc = wait_pending_reply(rcyn); if (rc >= 0) { rc = -EPROTO; - if (rcyn->reply.count == 2 + if (rcyn->reply.count >= 2 && 0 == strcmp(rcyn->reply.fields[0], _yes_) && 0 == strcmp(rcyn->reply.fields[1], "1")) { + cache_clear(rcyn->cache, + rcyn->reply.count > 2 ? (uint32_t)atol(rcyn->reply.fields[2]) : 0); rc = async(rcyn, EPOLL_CTL_ADD, EPOLLIN); if (rc >= 0) return 0; @@ -498,6 +503,13 @@ error: } void +rcyn_disconnect( + rcyn_t *rcyn +) { + disconnection(rcyn); +} + +void rcyn_close( rcyn_t *rcyn ) { @@ -701,7 +713,7 @@ void rcyn_cache_clear( rcyn_t *rcyn ) { - cache_clear(rcyn->cache); + cache_clear(rcyn->cache, 0); } int diff --git a/src/rcyn-client.h b/src/rcyn-client.h index a48d007..ad93689 100644 --- a/src/rcyn-client.h +++ b/src/rcyn-client.h @@ -52,6 +52,12 @@ rcyn_open( extern void +rcyn_disconnect( + rcyn_t *rcyn +); + +extern +void rcyn_close( rcyn_t *rcyn ); diff --git a/src/rcyn-protocol.txt b/src/rcyn-protocol.txt index 50fd918..72789a2 100644 --- a/src/rcyn-protocol.txt +++ b/src/rcyn-protocol.txt @@ -4,11 +4,11 @@ protocol hello: c->s rcyn 1 - s->c yes 1 + s->c yes 1 CACHEID invalidate cache: - s->c clear + s->c clear CACHEID test a permission: diff --git a/src/rcyn-server.c b/src/rcyn-server.c index 4ea49b0..8f14fdb 100644 --- a/src/rcyn-server.c +++ b/src/rcyn-server.c @@ -299,7 +299,7 @@ onrequest( if (!cli->version) { if (!ckarg(args[0], _rcyn_, 0) || count != 2 || !ckarg(args[1], "1", 0)) goto invalid; - putx(cli, _yes_, "1", NULL); + putx(cli, _yes_, "1", cyn_changeid_string(), NULL); flushw(cli); cli->version = 1; return; @@ -426,7 +426,7 @@ onchange( client_t *cli = closure; if (cli->checked) { cli->checked = false; - putx(cli, _clear_, NULL); + putx(cli, _clear_, cyn_changeid_string(), NULL); flushw(cli); } } |