aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cache.c2
-rw-r--r--src/cynagora-protocol.txt122
-rw-r--r--src/cynagora.c39
-rw-r--r--src/cynagora.h18
-rw-r--r--src/main-cynagora-admin.c31
5 files changed, 149 insertions, 63 deletions
diff --git a/src/cache.c b/src/cache.c
index c3f83cc..c19cc66 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -338,7 +338,7 @@ cache_clear(
cache_t *cache,
uint32_t cacheid
) {
- if (cache && (!cacheid || cache->cacheid != cacheid)) {
+ if (cache && (cache->cacheid != cacheid || !cacheid)) {
cache->cacheid = cacheid;
cache->used = 0;
}
diff --git a/src/cynagora-protocol.txt b/src/cynagora-protocol.txt
index 10668ca..2afd43b 100644
--- a/src/cynagora-protocol.txt
+++ b/src/cynagora-protocol.txt
@@ -1,15 +1,47 @@
-protocol
-========
+The cynagora protocol
+=====================
-hello:
+Introduction
+------------
- c->s cynagora 1
- s->c yes 1 CACHEID
+### Notations:
-invalidate cache:
+ - c->s: from client to cynagora server
+ - s->c: from cynagora server to client
+ - EXPIRE: if missing, means forever
+ if positive, a number of second since EPOCH, invalid after it
+ - CACHEID: a 32 bits positive integer
+ - ASKID: a 32 bits positive integer
- s->c clear CACHEID
+Messages
+--------
+
+### hello
+
+synopsis:
+
+ c->s cynagora 1
+ s->c yes 1 CACHEID
+
+The client present itself with the version of the protocol it expects to
+speak (today version 1 only). The server answer yes with the acknoledged
+version it will use and the CACHEID that identify the cache (see note on
+CACHEID)
+
+If hello is used, it must be the first message. If it is not used, the
+protocol implicitely switch to the default version.
+
+
+### invalidate cache
+
+synopsis:
+
+ s->c clear CACHEID
+
+The server ask the client to clear its cache and to start the cache whose
+identifier is CACHEID
+
### test a permission
synopsis:
@@ -27,6 +59,7 @@ synopsis:
s->c (yes|no) [EXPIRE]
+
### enter critical (admin)
synopsis:
@@ -45,52 +78,59 @@ synopsis:
synopsis:
- c->s drop CLIENT SESSION USER PERMISSION
- s->c done|error ...
+ c->s drop CLIENT SESSION USER PERMISSION
+ s->c done|error ...
-set (admin):
+### set (admin)
- c->s set CLIENT SESSION USER PERMISSION VALUE [EXPIRE]
- s->c done|error ...
+synopsis:
-list permissions (admin):
+ c->s set CLIENT SESSION USER PERMISSION VALUE [EXPIRE]
+ s->c done|error ...
+
+### list permissions (admin):
+
+synopsis:
- c->s get CLIENT SESSION USER PERMISSION
- s->c item CLIENT SESSION USER PERMISSION VALUE [EXPIRE]
- s->c ...
- s->c done
+ c->s get CLIENT SESSION USER PERMISSION
+ s->c item CLIENT SESSION USER PERMISSION VALUE [EXPIRE]
+ s->c ...
+ s->c done
-logging set/get (admin)
+### logging set/get (admin)
- c->s log [on|off]
- s->c done (on|off)
+synopsis:
-register agent (agent):
+ c->s log [on|off]
+ s->c done (on|off)
- s->c ask ASKID NAME VALUE CLIENT SESSION USER PERMISSION
- c->s reply ASKID (yes|no|error) [EXPIRE]
+### register agent (agent)
-ask agent (agent):
+synopsis:
- s->c ask NAME VALUE CLIENT SESSION USER PERMISSION
- c->s done | ([yes|no] [always|session|one-time|EXPIRE])
+ c->s agent NAME
+ s->c done|error ...
+
+### ask agent (agent):
+
+synopsis:
+
+ s->c ask ASKID NAME VALUE CLIENT SESSION USER PERMISSION
+ c->s reply ASKID ([yes|no] [always|session|one-time|EXPIRE])
+
+### sub queries (agent):
+
+synopsis:
+ c->s sub ASKID (test|check) CLIENT SESSION USER PERMISSION
+ s->c reply ASKID (done|yes|no) [EXPIRE]
-----------------------------------------------------------
- c->s c(heck) CLIENT SESSION USER PERMISSION
- c->s d(rop) CLIENT SESSION USER PERMISSION
- c->s e(nter)
- c->s g(et) CLIENT SESSION USER PERMISSION
- c->s l(eave) [commit|rollback]
- c->s r(cyn)
- c->s s(et) CLIENT SESSION USER PERMISSION VALUE EXPIRE
- c->s t(est) CLIENT SESSION USER PERMISSION
+Notes
+-----
- s->c clear
- s->c done
- s->c done [CLIENT SESSION USER PERMISSION VALUE]
- s->c done|error ...
- s->c item CLIENT SESSION USER PERMISSION VALUE EXPIRE
- s->c done VALUE EXPIRE
+### CACHEID
+The cacheid identify the current cache. It changes each time the database
+changes. After a disconnection, clients can use HELLO to check whether their
+version of cache is still valid. This is implemented by the default C library.
diff --git a/src/cynagora.c b/src/cynagora.c
index b4bd7e9..2928779 100644
--- a/src/cynagora.c
+++ b/src/cynagora.c
@@ -613,9 +613,10 @@ ensure_opened(
/**
* Check or test synchronously
*
- * @param cynagora
- * @param key
- * @param action
+ * @param cynagora the handler of the client
+ * @param key the key to test/check
+ * @param force if not set forbids cache use
+ * @param action test or check
*
* @return 0 in case of success or a negative -errno value
*/
@@ -624,6 +625,7 @@ int
check_or_test(
cynagora_t *cynagora,
const cynagora_key_t *key,
+ int force,
const char *action
) {
int rc;
@@ -642,9 +644,11 @@ check_or_test(
flushr(cynagora);
/* check cache item */
- rc = cache_search(cynagora->cache, key);
- if (rc >= 0)
- return rc;
+ if (!force) {
+ rc = cache_search(cynagora->cache, key);
+ if (rc >= 0)
+ return rc;
+ }
/* send the request */
rc = putxkv(cynagora, action, 0, key, 0);
@@ -851,18 +855,20 @@ cynagora_cache_check(
int
cynagora_check(
cynagora_t *cynagora,
- const cynagora_key_t *key
+ const cynagora_key_t *key,
+ int force
) {
- return check_or_test(cynagora, key, _check_);
+ return check_or_test(cynagora, key, force, _check_);
}
/* see cynagora.h */
int
cynagora_test(
cynagora_t *cynagora,
- const cynagora_key_t *key
+ const cynagora_key_t *key,
+ int force
) {
- return check_or_test(cynagora, key, _test_);
+ return check_or_test(cynagora, key, force, _test_);
}
/* see cynagora.h */
@@ -870,6 +876,7 @@ int
cynagora_async_check(
cynagora_t *cynagora,
const cynagora_key_t *key,
+ int force,
int simple,
cynagora_async_check_cb_t *callback,
void *closure
@@ -882,6 +889,18 @@ cynagora_async_check(
if (rc < 0)
return rc;
+ /* ensure there is no clear cache pending */
+ flushr(cynagora);
+
+ /* check cache item */
+ if (!force) {
+ rc = cache_search(cynagora->cache, key);
+ if (rc >= 0) {
+ callback(closure, rc);
+ return 0;
+ }
+ }
+
/* allocate */
ar = malloc(sizeof *ar + strlen(key->client) + strlen(key->session) + strlen(key->user) + strlen(key->permission) + 4);
if (ar == NULL)
diff --git a/src/cynagora.h b/src/cynagora.h
index aff1720..d5dc80f 100644
--- a/src/cynagora.h
+++ b/src/cynagora.h
@@ -20,7 +20,9 @@
/* IMPLEMENTATION OF CLIENT PART OF CYNAGORA-PROTOCOL */
/******************************************************************************/
/******************************************************************************/
-
+/**
+ * @file cynagora.h
+ */
/******************************************************************************/
/* COMMON PART - types and functions common to check/admin/agent clients */
/******************************************************************************/
@@ -216,6 +218,7 @@ cynagora_cache_check(
*
* @param cynagora the client handler
* @param key the key to check
+ * @param force if not set forbids cache use
*
* @return 0 if permission forbidden, 1 if permission granted
* or if error a negative -errno value
@@ -226,7 +229,8 @@ extern
int
cynagora_check(
cynagora_t *cynagora,
- const cynagora_key_t *key
+ const cynagora_key_t *key,
+ int force
);
/**
@@ -235,7 +239,10 @@ cynagora_check(
*
* @param cynagora the client handler
* @param key
- * @return
+ * @param force if not set forbids cache use
+ *
+ * @return 0 if permission forbidden, 1 if permission granted
+ * or if error a negative -errno value
*
* @see cynagora_check
*/
@@ -243,7 +250,8 @@ extern
int
cynagora_test(
cynagora_t *cynagora,
- const cynagora_key_t *key
+ const cynagora_key_t *key,
+ int force
);
/**
@@ -251,6 +259,7 @@ cynagora_test(
*
* @param cynagora the handler of the client
* @param key the key to query
+ * @param force if not set forbids cache use
* @param simple if zero allows agent process else if not 0 forbids it
* @param callback the callback to call on reply
* @param closure a closure for the callback
@@ -262,6 +271,7 @@ int
cynagora_async_check(
cynagora_t *cynagora,
const cynagora_key_t *key,
+ int force,
int simple,
cynagora_async_check_cb_t *callback,
void *closure
diff --git a/src/main-cynagora-admin.c b/src/main-cynagora-admin.c
index c748b4b..210084c 100644
--- a/src/main-cynagora-admin.c
+++ b/src/main-cynagora-admin.c
@@ -91,7 +91,7 @@ static
const char
help__text[] =
"\n"
- "Commands are: list, set, drop, check, test, cache, clear, quit, log, help\n"
+ "Commands are: list, set, drop, acheck, check, atest, test, cache, clear, quit, log, help\n"
"Type 'help command' to get help on the command\n"
"Type 'help expiration' to get help on expirations\n"
"\n"
@@ -518,19 +518,17 @@ int do_drop(int ac, char **av)
return uc;
}
-int do_check(int ac, char **av, int (*f)(cynagora_t*,const cynagora_key_t*))
+int do_check(int ac, char **av, int (*f)(cynagora_t*,const cynagora_key_t*,int))
{
int uc, rc;
rc = get_csup(ac, av, &uc, NULL);
if (rc == 0) {
- rc = f(cynagora, &key);
+ rc = f(cynagora, &key, 0);
if (rc > 0)
fprintf(stdout, "allowed\n");
else if (rc == 0)
fprintf(stdout, "denied\n");
- else if (rc == -ENOENT && f == cynagora_cache_check)
- fprintf(stdout, "not in cache!\n");
else if (rc == -EEXIST)
fprintf(stderr, "denied but an entry exist\n");
else
@@ -539,6 +537,25 @@ int do_check(int ac, char **av, int (*f)(cynagora_t*,const cynagora_key_t*))
return uc;
}
+int do_cache_check(int ac, char **av)
+{
+ int uc, rc;
+
+ rc = get_csup(ac, av, &uc, NULL);
+ if (rc == 0) {
+ rc = cynagora_cache_check(cynagora, &key);
+ if (rc > 0)
+ fprintf(stdout, "allowed\n");
+ else if (rc == 0)
+ fprintf(stdout, "denied\n");
+ else if (rc == -ENOENT)
+ fprintf(stdout, "not in cache!\n");
+ else
+ fprintf(stderr, "error %s\n", strerror(-rc));
+ }
+ return uc;
+}
+
void acheck_cb(void *closure, int status)
{
if (status > 0)
@@ -557,7 +574,7 @@ int do_acheck(int ac, char **av, bool simple)
rc = get_csup(ac, av, &uc, NULL);
if (rc == 0) {
pending++;
- rc = cynagora_async_check(cynagora, &key, simple, acheck_cb, NULL);
+ rc = cynagora_async_check(cynagora, &key, 0, simple, acheck_cb, NULL);
if (rc < 0) {
fprintf(stderr, "error %s\n", strerror(-rc));
pending--;
@@ -650,7 +667,7 @@ int do_any(int ac, char **av)
return do_acheck(ac, av, 1);
if (!strcmp(av[0], "cache"))
- return do_check(ac, av, cynagora_cache_check);
+ return do_cache_check(ac, av);
if (!strcmp(av[0], "log"))
return do_log(ac, av);