aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2019-05-24 12:21:33 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2019-05-24 12:21:33 +0200
commit395cd2eb66909c4396cdd7a3ae2ad8e4c5ec6ee8 (patch)
tree679d9b77ddf7b5b77163a901b7eacd4b4e7edf44
parentc715090f1faaa2ec53ee84895d61c7f72fcd4772 (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.c1
-rw-r--r--src/cache.c14
-rw-r--r--src/cache.h3
-rw-r--r--src/cyn.c46
-rw-r--r--src/cyn.h14
-rw-r--r--src/db.c2
-rw-r--r--src/main-cynarad.c27
-rw-r--r--src/rcyn-client.c36
-rw-r--r--src/rcyn-client.h6
-rw-r--r--src/rcyn-protocol.txt4
-rw-r--r--src/rcyn-server.c4
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
diff --git a/src/cyn.c b/src/cyn.c
index f853a53..6b6b17a 100644
--- 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
diff --git a/src/cyn.h b/src/cyn.h
index 2dbfa62..810026a 100644
--- 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(
+);
diff --git a/src/db.c b/src/db.c
index e6eb3d1..aebead2 100644
--- 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);
}
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);
}
}