Add cacheid
authorJosé Bollo <jose.bollo@iot.bzh>
Fri, 24 May 2019 10:21:33 +0000 (12:21 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Fri, 24 May 2019 10:21:33 +0000 (12:21 +0200)
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>
src/agent-at.c
src/cache.c
src/cache.h
src/cyn.c
src/cyn.h
src/db.c
src/main-cynarad.c
src/rcyn-client.c
src/rcyn-client.h
src/rcyn-protocol.txt
src/rcyn-server.c

index f671fc7..02bcc6c 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdbool.h>
 #include <time.h>
 #include <string.h>
index b57536d..c8e7550 100644 (file)
@@ -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;
 }
index bf85e8e..4ddaa1e 100644 (file)
@@ -39,7 +39,8 @@ cache_put(
 extern
 void
 cache_clear(
-       cache_t *cache
+       cache_t *cache,
+       uint32_t cacheid
 );
 
 extern
index f853a53..6b6b17a 100644 (file)
--- a/src/cyn.c
+++ b/src/cyn.c
@@ -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
index 2dbfa62..810026a 100644 (file)
--- a/src/cyn.h
+++ b/src/cyn.h
@@ -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(
+);
index e6eb3d1..aebead2 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -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);
        }
index 75b0169..19f0f4d 100644 (file)
@@ -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)
index baffb83..575d72c 100644 (file)
@@ -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;
@@ -497,6 +502,13 @@ error:
        return rc;
 }
 
+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
index a48d007..ad93689 100644 (file)
@@ -50,6 +50,12 @@ rcyn_open(
        const char *socketspec
 );
 
+extern
+void
+rcyn_disconnect(
+       rcyn_t *rcyn
+);
+
 extern
 void
 rcyn_close(
index 50fd918..72789a2 100644 (file)
@@ -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:
 
index 4ea49b0..8f14fdb 100644 (file)
@@ -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);
        }
 }