Improve comments
authorJose Bollo <jose.bollo@iot.bzh>
Mon, 30 Sep 2019 15:40:04 +0000 (17:40 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Thu, 3 Oct 2019 10:35:01 +0000 (12:35 +0200)
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
38 files changed:
src/agent-at.c
src/agent-at.h
src/anydb.c
src/anydb.h
src/cache.c
src/cache.h
src/cyn.c
src/cyn.h
src/data.h
src/db.c
src/db.h
src/dbinit.c
src/dbinit.h
src/expire.c
src/expire.h
src/fbuf.c
src/fbuf.h
src/filedb.c
src/filedb.h
src/lib-compat.c
src/main-cynadm.c
src/main-cynarad.c
src/memdb.c
src/memdb.h
src/pollitem.c
src/pollitem.h
src/prot.c
src/prot.h
src/queue.c
src/queue.h
src/rcyn-client.c
src/rcyn-client.h
src/rcyn-protocol.c
src/rcyn-protocol.h
src/rcyn-server.c
src/rcyn-server.h
src/socket.c
src/socket.h

index e646ab7..21193f1 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF AGENT AT (@)                                             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <stdint.h>
 /**
  * Parse the spec to extract the derived key to ask.
  *
- * @param spec   The specification of the derived key
- * @param rkey   The originally requested key
- * @param key    The derived key or NULL for computing length
- * @param buffer The buffer that handles texts or NULL for computing length
- * @param szbuf  The size of the buffer or 0 for computing length
+ * @param spec           The specification of the derived key
+ * @param reference_key  The originally requested key of reference
+ * @param derived_key    The derived key or NULL for computing length
+ * @param buffer         The buffer that handles texts or NULL for computing length
+ * @param szbuf          The size of the buffer or 0 for computing length
  * @return the total length of buffer used
  */
 static
 size_t
 parse(
        const char *spec,
-       const data_key_t *rkey,
-       data_key_t *key,
+       const data_key_t *reference_key,
+       data_key_t *derived_key,
        char *buffer,
        size_t szbuf
 ) {
@@ -47,8 +52,10 @@ parse(
        const char *val;
        int sub;
 
+       /* iterate through the fields of the key */
        iout = 0;
        for (ikey = 0 ; ikey < KeyIdx_Count ; ikey++) {
+               /* compute value of the derived field */
                inf = iout;
                while(*spec) {
                        if (*spec == ':' && ikey < 3) {
@@ -66,19 +73,19 @@ parse(
                                /* what % substitution is it? */
                                switch(spec[1]) {
                                case 'c':
-                                       val = rkey->client;
+                                       val = reference_key->client;
                                        sub = 1;
                                        break;
                                case 's':
-                                       val = rkey->session;
+                                       val = reference_key->session;
                                        sub = 1;
                                        break;
                                case 'u':
-                                       val = rkey->user;
+                                       val = reference_key->user;
                                        sub = 1;
                                        break;
                                case 'p':
-                                       val = rkey->permission;
+                                       val = reference_key->permission;
                                        sub = 1;
                                        break;
                                default:
@@ -97,7 +104,7 @@ parse(
                                        if (iout < szbuf)
                                                buffer[iout] = spec[1];
                                        iout++;
-                               } else if (val) {
+                               } else if (val != NULL) {
                                        /* substitution of the value */
                                        while (*val) {
                                                if (iout < szbuf)
@@ -109,8 +116,9 @@ parse(
                                spec += 2;
                        }
                }
+               /* standardize the found item*/
                if (inf == iout)
-                       val = 0; /* empty key item */
+                       val = NULL; /* empty key item */
                else {
                        /* set zero ended key */
                        val = &buffer[inf];
@@ -118,8 +126,9 @@ parse(
                                buffer[iout] = 0;
                        iout++;
                }
-               if (key)
-                       key->keys[ikey] = val;
+               /* record the value */
+               if (derived_key)
+                       derived_key->keys[ikey] = val;
        }
        return iout;
 }
@@ -131,9 +140,8 @@ parse(
  * @param agent_closure      closure of the agent (not used)
  * @param key                the original searched key
  * @param value              the value found (string after @:)
- * @param on_result_cb       callback that will asynchronously handle the result
- * @param on_result_closure  closure for 'on_result_cb'
- * @return
+ * @param query              the query identifer for replying or subquerying
+ * @return 0 in case of success or -errno like negative error code
  */
 static
 int
@@ -149,13 +157,16 @@ agent_at_cb(
        size_t size;
 
        /* compute the length */
-       size = parse(value, key, 0, 0, 0);
+       size = parse(value, key, NULL, NULL, 0);
+
        /* alloc the length locally */
        block = alloca(size);
+
        /* initialize the derived key */
        parse(value, key, &atkey, block, size);
+
        /* ask for the derived key */
-       return cyn_subquery_async(query, (on_result_cb_t*)cyn_reply_query, query, &atkey);
+       return cyn_query_subquery_async(query, (on_result_cb_t*)cyn_query_reply, query, &atkey);
 }
 
 /* see agent-at.h */
index 60dd168..68f1d3a 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF AGENT AT (@)                                             */
+/******************************************************************************/
+/******************************************************************************/
 
 /**
  * Activate the AT-agent
index d522c96..9196e5c 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* HIGH LEVEL ABSTRACTION OF THE DATABASES                                    */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <stdint.h>
 #define USER_MATCH_SCORE       1
 #define PERMISSION_MATCH_SCORE 1
 
+/**
+ * helper for searching items
+ */
+union searchkey {
+       struct {
+               /** client id */
+               anydb_idx_t idxcli;
+
+               /** session id */
+               anydb_idx_t idxses;
+
+               /** user id */
+               anydb_idx_t idxusr;
+
+               /** permission string */
+               const char *strperm;
+       };
+       anydb_key_t key;
+};
+typedef union searchkey searchkey_t;
+
 /******************************************************************************/
 /******************************************************************************/
 /*** UTILITIES                                                              ***/
 /******************************************************************************/
 /******************************************************************************/
 
-/** check whether the 'text' fit String_Any, NULL or ""  */
+/**
+ * Check whether the 'text' fit String_Any, NULL or ""
+ * @param text the text to check
+ * @return true if text matches ANY possible values
+ */
 static
 bool
 is_any(
@@ -46,7 +76,11 @@ is_any(
        return text == NULL || text[0] == 0 || (!text[1] && text[0] == Data_Any_Char);
 }
 
-/** check whether the 'text' fit String_Any, String_Wide, NULL or ""  */
+/**
+ * check whether the 'text' fit String_Any, String_Wide, NULL or ""
+ * @param text the text to check
+ * @return true if text matches ANY or WIDE possible values
+ */
 static
 bool
 is_any_or_wide(
@@ -56,7 +90,12 @@ is_any_or_wide(
                || (!text[1] && (text[0] == Data_Any_Char || text[0] == Data_Wide_Char));
 }
 
-/** return the name of 'index' */
+/**
+ * Get the name stored for index
+ * @param db the anydb database to query
+ * @param idx the index of the string to get
+ * @return the name or NULL if doesn't exist
+ */
 static
 const char*
 string(
@@ -70,7 +109,14 @@ string(
        return db->itf.string(db->clodb, idx);
 }
 
-/** search the index of 'name' and create it if 'create' */
+/**
+ * Search the index of 'name' and create it if 'create'
+ * @param db the anydb database to query
+ * @param idx where to store the result if needed
+ * @param name name to search and/or create
+ * @param create if not nul, the name is created if it doesn't exist
+ * @return 0 in case of success of -errno
+ */
 static
 int
 idx(
@@ -79,27 +125,39 @@ idx(
        const char *name,
        bool create
 ) {
-       /* special names */
+       /* handle special names */
        if (!name || !name[0]) {
+               /* no name or empty name means ANY */
                *idx = AnyIdx_Any;
                return 0;
        }
+       /* handle special names of one character  */
        if (!name[1]) {
                if (name[0] == Data_Any_Char) {
+                       /* Single char for ANY */
                        *idx = AnyIdx_Any;
                        return 0;
                }
                if (name[0] == Data_Wide_Char) {
+                       /* Single char for WIDE */
                        *idx = AnyIdx_Wide;
                        return 0;
                }
        }
 
-       /* other case */
+       /* other case: ask the database backend */
        return db->itf.index(db->clodb, idx, name, create);
 }
 
-/** search the index of 'name' and create it if 'create' */
+/**
+ * Search the index of 'name' and create it if 'create'
+ * Return the index for WIDE if name matches ANY or WIDE
+ * @param db the backend database
+ * @param idx where to store the found index
+ * @param name the name to search or create
+ * @param create not nul for authorizing creation of the index for name
+ * @return 0 on success
+ */
 static
 int
 idx_but_any(
@@ -117,7 +175,14 @@ idx_but_any(
        return db->itf.index(db->clodb, idx, name, create);
 }
 
-/** search the index of 'name' and create it if 'create' */
+/**
+ * Return the index of 'name' in the database 'db'. In option 'create' it.
+ * If the name encode ANY or WIDE returns WIDE.
+ * @param db the backend database
+ * @param name the name to search or create
+ * @param create not nul for authorizing creation of the index for name
+ * @return the found index or AnyIdx_None if not found.
+ */
 static
 anydb_idx_t
 idx_or_none_but_any(
@@ -132,13 +197,126 @@ idx_or_none_but_any(
        return idx;
 }
 
+/******************************************************************************/
+/******************************************************************************/
+/*** SEARCH KEYS                                                            ***/
+/******************************************************************************/
+/******************************************************************************/
+
+static
+bool
+searchkey_prepare_match(anydb_t *db,
+       const data_key_t *key,
+       searchkey_t *skey,
+       bool create
+) {
+       if (idx(db, &skey->idxcli, key->client, create)
+        || idx(db, &skey->idxses, key->session, create)
+        || idx(db, &skey->idxusr, key->user, create))
+               return false; /* one of the idx doesn't exist */
+       skey->strperm = is_any(key->permission) ? NULL : key->permission;
+
+       return true;
+}
+
+static
+bool
+searchkey_match(
+       anydb_t *db,
+       const anydb_key_t *key,
+       const searchkey_t *skey
+) {
+       return (skey->idxcli == AnyIdx_Any || skey->idxcli == key->client)
+           && (skey->idxses == AnyIdx_Any || skey->idxses == key->session)
+           && (skey->idxusr == AnyIdx_Any || skey->idxusr == key->user)
+           && (!skey->strperm || !strcasecmp(skey->strperm, string(db, key->permission)));
+}
+
+static
+int
+searchkey_prepare_is(
+       anydb_t *db,
+       const data_key_t *key,
+       searchkey_t *skey,
+       bool create
+) {
+       int rc;
+
+       rc = idx_but_any(db, &skey->idxcli, key->client, create);
+       if (!rc) {
+               rc = idx_but_any(db, &skey->idxses, key->session, create);
+               if (!rc) {
+                       rc = idx_but_any(db, &skey->idxusr, key->user, create);
+                       if (!rc)
+                               skey->strperm = key->permission;
+               }
+       }
+       return rc;
+}
+
+static
+bool
+searchkey_is(
+       anydb_t *db,
+       const anydb_key_t *key,
+       const searchkey_t *skey
+) {
+       return skey->idxcli == key->client
+           && skey->idxses == key->session
+           && skey->idxusr == key->user
+           && !strcasecmp(skey->strperm, string(db, key->permission));
+}
+
+static
+void
+searchkey_prepare_test(
+       anydb_t *db,
+       const data_key_t *key,
+       searchkey_t *skey,
+       bool create
+) {
+       skey->idxcli = idx_or_none_but_any(db, key->client, create);
+       skey->idxses = idx_or_none_but_any(db, key->session, create);
+       skey->idxusr = idx_or_none_but_any(db, key->user, create);
+       skey->strperm = key->permission;
+}
+
+static
+unsigned
+searchkey_test(
+       anydb_t *db,
+       const anydb_key_t *key,
+       const searchkey_t *skey
+) {
+       unsigned sc;
+
+       if ((key->client  != AnyIdx_Wide && skey->idxcli != key->client)
+        || (key->session != AnyIdx_Wide && skey->idxses != key->session)
+        || (key->user    != AnyIdx_Wide && skey->idxusr != key->user)
+        || (key->permission != AnyIdx_Wide
+               && strcasecmp(skey->strperm, string(db, key->permission)))) {
+               sc = 0;
+       } else {
+               sc = 1;
+               if (key->client != AnyIdx_Wide)
+                       sc += CLIENT_MATCH_SCORE;
+               if (key->session != AnyIdx_Wide)
+                       sc += SESSION_MATCH_SCORE;
+               if (key->user != AnyIdx_Wide)
+                       sc += USER_MATCH_SCORE;
+               if (key->permission != AnyIdx_Wide)
+                       sc += PERMISSION_MATCH_SCORE;
+       }
+       return sc;
+}
+
 /******************************************************************************/
 /******************************************************************************/
 /*** FOR ALL                                                                ***/
 /******************************************************************************/
 /******************************************************************************/
 
-/** manage atomicity of operations */
+/* see anydb.h */
 int
 anydb_transaction(
        anydb_t *db,
@@ -157,17 +335,14 @@ anydb_transaction(
 
 struct for_all_s
 {
-       anydb_t *db;
+       anydb_t *db;          /* targeted database */
+       time_t now;           /* also drop expired items */
+       searchkey_t skey;
        void *closure;
        void (*callback)(
                void *closure,
                const data_key_t *key,
                const data_value_t *value);
-       anydb_idx_t idxcli;
-       anydb_idx_t idxses;
-       anydb_idx_t idxusr;
-       const char *strperm;
-       time_t now;
 };
 
 static
@@ -181,48 +356,41 @@ for_all_cb(
        data_key_t k;
        data_value_t v;
 
+       /* drop expired items */
        if (value->expire && value->expire <= s->now)
                return Anydb_Action_Remove_And_Continue;
 
-       if ((s->idxcli == AnyIdx_Any || s->idxcli == key->client)
-        && (s->idxses == AnyIdx_Any || s->idxses == key->session)
-        && (s->idxusr == AnyIdx_Any || s->idxusr == key->user)) {
+       if (searchkey_match(s->db, key, &s->skey)) {
+               k.client = string(s->db, key->client);
+               k.session = string(s->db, key->session);
+               k.user = string(s->db, key->user);
                k.permission = string(s->db, key->permission);
-               if (!s->strperm || !strcasecmp(s->strperm, k.permission)) {
-                       k.client = string(s->db, key->client);
-                       k.session = string(s->db, key->session);
-                       k.user = string(s->db, key->user);
-                       v.value = string(s->db, value->value);
-                       v.expire = value->expire;
-                       s->callback(s->closure, &k, &v);
-               }
+               v.value = string(s->db, value->value);
+               v.expire = value->expire;
+               s->callback(s->closure, &k, &v);
        }
        return Anydb_Action_Continue;
 }
 
-/** enumerate */
+/* see anydb.h */
 void
 anydb_for_all(
        anydb_t *db,
-       void *closure,
        void (*callback)(
                void *closure,
                const data_key_t *key,
                const data_value_t *value),
+       void *closure,
        const data_key_t *key
 ) {
        struct for_all_s s;
 
+       if (!searchkey_prepare_match(db, key, &s.skey, false))
+               return; /* nothing to do! because one of the idx doesn't exist */
+
        s.db = db;
        s.closure = closure;
        s.callback = callback;
-
-       if (idx(db, &s.idxcli, key->client, false)
-        || idx(db, &s.idxses, key->session, false)
-        || idx(db, &s.idxusr, key->user, false))
-               return; /* nothing to do! because one of the idx doesn't exist */
-       s.strperm = is_any(key->permission) ? NULL : key->permission;
-
        s.now = time(NULL);
        db->itf.apply(db->clodb, for_all_cb, &s);
 }
@@ -233,16 +401,15 @@ anydb_for_all(
 /******************************************************************************/
 /******************************************************************************/
 
+/* structure for dropping items */
 struct drop_s
 {
-       anydb_t *db;
-       anydb_idx_t idxcli;
-       anydb_idx_t idxses;
-       anydb_idx_t idxusr;
-       const char *strperm;
-       time_t now;
+       anydb_t *db;          /* targeted database */
+       time_t now;           /* also drop expired items */
+       searchkey_t skey;     /* the search key */
 };
 
+/* callback for dropping items */
 static
 anydb_action_t
 drop_cb(
@@ -252,57 +419,50 @@ drop_cb(
 ) {
        struct drop_s *s = closure;
 
+       /* drop expired items */
        if (value->expire && value->expire <= s->now)
                return Anydb_Action_Remove_And_Continue;
 
-       if ((s->idxcli == AnyIdx_Any || s->idxcli == key->client)
-        && (s->idxses == AnyIdx_Any || s->idxses == key->session)
-        && (s->idxusr == AnyIdx_Any || s->idxusr == key->user)
-        && (!s->strperm || !strcasecmp(s->strperm, string(s->db, key->permission))))
+       /* remove if matches the key */
+       if (searchkey_match(s->db, key, &s->skey))
                return Anydb_Action_Remove_And_Continue;
 
+       /* continue to next */
        return Anydb_Action_Continue;
 }
 
-/** drop rules */
-int
+/* see anydb.h */
+void
 anydb_drop(
        anydb_t *db,
        const data_key_t *key
 ) {
        struct drop_s s;
 
-       s.db = db;
-
-       if (idx(db, &s.idxcli, key->client, false)
-        || idx(db, &s.idxses, key->session, false)
-        || idx(db, &s.idxusr, key->user, false))
-               return 0; /* nothing to do! because one of the idx doesn't exist */
-       s.strperm = is_any(key->permission) ? NULL : key->permission;
+       if (!searchkey_prepare_match(db, key, &s.skey, false))
+               return; /* nothing to do! because one of the idx doesn't exist */
 
+       s.db = db;
        s.now = time(NULL);
        db->itf.apply(db->clodb, drop_cb, &s);
-       return 0;
 }
 
 /******************************************************************************/
 /******************************************************************************/
-/*** ADD                                                                    ***/
+/*** SET                                                                    ***/
 /******************************************************************************/
 /******************************************************************************/
 
+/* structure for setting values */
 struct set_s
 {
-       anydb_t *db;
-       anydb_idx_t idxcli;
-       anydb_idx_t idxses;
-       anydb_idx_t idxusr;
-       anydb_idx_t idxval;
-       time_t expire;
-       const char *strperm;
-       time_t now;
+       anydb_t *db;          /* targeted database */
+       time_t now;           /* also drop expired items */
+       searchkey_t skey;     /* searching key */
+       anydb_value_t value;  /* value to set */
 };
 
+/* callback for setting values */
 static
 anydb_action_t
 set_cb(
@@ -312,22 +472,21 @@ set_cb(
 ) {
        struct set_s *s = closure;
 
+       /* drop expired items */
        if (value->expire && value->expire <= s->now)
                return Anydb_Action_Remove_And_Continue;
 
-       if (s->idxcli == key->client
-        && s->idxses == key->session
-        && s->idxusr == key->user
-        && !strcasecmp(s->strperm, string(s->db, key->permission))) {
-               value->value = s->idxval;
-               value->expire = s->expire;
-               s->db = NULL;
+       if (searchkey_is(s->db, key, &s->skey)) {
+               value->value = s->value.value;
+               value->expire = s->value.expire;
+               s->db = NULL; /* indicates that is found */
                return Anydb_Action_Update_And_Stop;
        }
 
        return Anydb_Action_Continue;
 }
 
+/* see anydb.h */
 int
 anydb_set(
        anydb_t *db,
@@ -336,41 +495,25 @@ anydb_set(
 ) {
        int rc;
        struct set_s s;
-       anydb_key_t k;
-       anydb_value_t v;
-
-       s.db = db;
-       s.strperm = key->permission;
-       s.expire = value->expire;
 
-       rc = idx_but_any(db, &s.idxcli, key->client, true);
-       if (rc)
-               goto error;
-       rc = idx_but_any(db, &s.idxses, key->session, true);
-       if (rc)
-               goto error;
-       rc = idx_but_any(db, &s.idxusr, key->user, true);
+       rc = searchkey_prepare_is(db, key, &s.skey, true);
        if (rc)
                goto error;
-       rc = idx(db, &s.idxval, value->value, true);
+
+       rc = idx(db, &s.value.value, value->value, true);
        if (rc)
                goto error;
 
+       s.db = db;
+       s.value.expire = value->expire;
        s.now = time(NULL);
        db->itf.apply(db->clodb, set_cb, &s);
        if (s.db) {
-               if (idx(db, &k.permission, s.strperm, true))
-                       goto error;
-               k.client = s.idxcli;
-               k.user = s.idxusr;
-               k.session = s.idxses;
-               v.value = s.idxval;
-               v.expire = s.expire;
-               rc = db->itf.add(db->clodb, &k, &v);
-               if (rc)
-                       goto error;
+               /* no item to alter so must be added */
+               rc = idx(db, &s.skey.key.permission, key->permission, true);
+               if (!rc)
+                       rc = db->itf.add(db->clodb, &s.skey.key, &s.value);
        }
-       return 0;
 error:
        return rc;
 }
@@ -381,19 +524,17 @@ error:
 /******************************************************************************/
 /******************************************************************************/
 
+/* structure for testing rule */
 struct test_s
 {
-       anydb_t *db;
-       anydb_idx_t idxcli;
-       anydb_idx_t idxses;
-       anydb_idx_t idxusr;
-       const char *strperm;
-       int score;
-       anydb_idx_t idxval;
-       time_t expire;
+       anydb_t *db;          /* targeted database */
        time_t now;
+       unsigned score;
+       searchkey_t skey;
+       anydb_value_t value;
 };
 
+/* callback for testing rule */
 static
 anydb_action_t
 test_cb(
@@ -402,35 +543,22 @@ test_cb(
        anydb_value_t *value
 ) {
        struct test_s *s = closure;
-       int sc;
+       unsigned sc;
 
+       /* drop expired items */
        if (value->expire && value->expire <= s->now)
                return Anydb_Action_Remove_And_Continue;
 
-       if ((s->idxcli == key->client || key->client == AnyIdx_Wide)
-        && (s->idxses == key->session || key->session == AnyIdx_Wide)
-        && (s->idxusr == key->user || key->user == AnyIdx_Wide)
-        && (AnyIdx_Wide == key->permission
-            || !strcasecmp(s->strperm, string(s->db, key->permission)))) {
-               sc = 1;
-               if (key->client != AnyIdx_Wide)
-                       sc += CLIENT_MATCH_SCORE;
-               if (key->session != AnyIdx_Wide)
-                       sc += SESSION_MATCH_SCORE;
-               if (key->user != AnyIdx_Wide)
-                       sc += USER_MATCH_SCORE;
-               if (key->permission != AnyIdx_Wide)
-                       sc += PERMISSION_MATCH_SCORE;
-               if (sc > s->score) {
-                       s->score = sc;
-                       s->idxval = value->value;
-                       s->expire = value->expire;
-               }
+       sc = searchkey_test(s->db, key, &s->skey);
+       if (sc > s->score) {
+               s->score = sc;
+               s->value = *value;
        }
        return Anydb_Action_Continue;
 }
 
-int
+/* see anydb.h */
+unsigned
 anydb_test(
        anydb_t *db,
        const data_key_t *key,
@@ -438,34 +566,27 @@ anydb_test(
 ) {
        struct test_s s;
 
+       searchkey_prepare_test(db, key, &s.skey, true);
+
        s.db = db;
        s.now = time(NULL);
-       s.strperm = key->permission;
-       s.expire = value->expire;
-
-       s.idxcli = idx_or_none_but_any(db, key->client, true);
-       s.idxses = idx_or_none_but_any(db, key->session, true);
-       s.idxusr = idx_or_none_but_any(db, key->user, true);
-
-       s.expire = -1;
-       s.idxval = AnyIdx_Invalid;
        s.score = 0;
-
        db->itf.apply(db->clodb, test_cb, &s);
-
        if (s.score) {
-               value->value = string(db, s.idxval);
-               value->expire = s.expire;
+               value->value = string(db, s.value.value);
+               value->expire = s.value.expire;
        }
        return s.score;
 }
 
+
 /******************************************************************************/
 /******************************************************************************/
 /*** IS EMPTY                                                               ***/
 /******************************************************************************/
 /******************************************************************************/
 
+/* callback for computing if empty */
 static
 anydb_action_t
 is_empty_cb(
@@ -473,18 +594,23 @@ is_empty_cb(
        const anydb_key_t *key,
        anydb_value_t *value
 ) {
-       bool *result = closure;
-       *result = false;
+       time_t *t = closure;
+       if (value->expire && value->expire <= *t)
+               return Anydb_Action_Remove_And_Continue;
+       *t = 0;
        return Anydb_Action_Stop;
 }
 
+/* see anydb.h */
 bool
 anydb_is_empty(
        anydb_t *db
 ) {
-       bool result = true;
-       db->itf.apply(db->clodb, is_empty_cb, &result);
-       return result;
+       time_t t;
+
+       t = time(NULL);
+       db->itf.apply(db->clodb, is_empty_cb, &t);
+       return !t;
 }
 
 /******************************************************************************/
@@ -493,6 +619,7 @@ anydb_is_empty(
 /******************************************************************************/
 /******************************************************************************/
 
+/* cleanup callback */
 static
 anydb_action_t
 cleanup_cb(
@@ -500,12 +627,11 @@ cleanup_cb(
        const anydb_key_t *key,
        anydb_value_t *value
 ) {
-       if (value->expire && value->expire <= *(time_t*)closure)
-               return Anydb_Action_Remove_And_Continue;
-
-       return Anydb_Action_Continue;
+       return value->expire && value->expire <= *(time_t*)closure
+               ? Anydb_Action_Remove_And_Continue : Anydb_Action_Continue;
 }
 
+/* see anydb.h */
 void
 anydb_cleanup(
        anydb_t *db
@@ -517,12 +643,27 @@ anydb_cleanup(
        db->itf.gc(db->clodb);
 }
 
+/******************************************************************************/
+/******************************************************************************/
+/*** SYNCHRONIZE                                                            ***/
+/******************************************************************************/
+/******************************************************************************/
+
+/* see anydb.h */
+int
+anydb_sync(
+       anydb_t *db
+) {
+       return db->itf.sync ? db->itf.sync(db->clodb) : 0;
+}
+
 /******************************************************************************/
 /******************************************************************************/
 /*** DESTROY                                                                ***/
 /******************************************************************************/
 /******************************************************************************/
 
+/* see anydb.h */
 void
 anydb_destroy(
        anydb_t *db
index 843ef29..64f86bd 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* HIGH LEVEL ABSTRACTION OF THE DATABASES                                    */
+/******************************************************************************/
+/******************************************************************************/
 
 /**
  * An index is an integer
@@ -29,10 +33,16 @@ typedef uint32_t anydb_idx_t;
 /** The invalid index */
 #define AnyIdx_Invalid ((anydb_idx_t)0xffffffffu)
 
-/**  */
+/** The index for ANY */
 #define AnyIdx_Any     ((anydb_idx_t)0xfffffffeu)
+
+/** The index for WIDE */
 #define AnyIdx_Wide    ((anydb_idx_t)0xfffffffdu)
+
+/** The index for NONE */
 #define AnyIdx_None    ((anydb_idx_t)0xfffffffcu)
+
+/** The maximum value for indexes */
 #define AnyIdx_Max     ((anydb_idx_t)0xfffffff7u)
 
 /**
@@ -67,45 +77,155 @@ struct anydb_value
 typedef struct anydb_value anydb_value_t;
 
 /**
+ * Operation of the transaction
  */
-enum anydb_action
-{
-       Anydb_Action_Stop,
-       Anydb_Action_Continue,
-       Anydb_Action_Update_And_Stop,
-       Anydb_Action_Remove_And_Continue
-};
-typedef enum anydb_action anydb_action_t;
-
 enum anydb_transaction
 {
+       /**
+        * Operation: Start a cancelable transaction
+        */
        Anydb_Transaction_Start = 0,
+
+       /**
+        * Operation: Terminate the started transaction and commit its changes
+        */
        Anydb_Transaction_Commit = 1,
+
+       /**
+        * Operation: Terminate the started transaction and cancel its changes
+        */
        Anydb_Transaction_Cancel = 2
 };
 typedef enum anydb_transaction anydb_transaction_t;
 
+/**
+ * Actions to perform in response to anydb_applycb_t callbacks.
+ */
+enum anydb_action
+{
+       /** Continue to apply with the next element of the database */
+       Anydb_Action_Continue = 0,
+
+       /** Stop to apply */
+       Anydb_Action_Stop = 1,
+
+       /** Update the current element (implicitly, also continue) */
+       Anydb_Action_Update = 2,
+
+       /** Remove the current element (implicitly, also continue) */
+       Anydb_Action_Remove = 4,
+
+       /** Update the current element and stop to apply */
+       Anydb_Action_Update_And_Stop = Anydb_Action_Update | Anydb_Action_Stop,
+
+       /** Update the current element and continue to apply */
+       Anydb_Action_Update_And_Continue = Anydb_Action_Update | Anydb_Action_Continue,
+
+       /** Remove the current element and stop to apply */
+       Anydb_Action_Remove_And_Stop = Anydb_Action_Remove | Anydb_Action_Stop,
+
+       /** Remove the current element and continue to apply */
+       Anydb_Action_Remove_And_Continue = Anydb_Action_Remove | Anydb_Action_Continue
+};
+typedef enum anydb_action anydb_action_t;
+
+/**
+ * Callback of apply method. This callback is called for any item of
+ * the database and it tells through its return what the anydb has
+ * to do: see anydb_action_t.
+ * The 'closure' is the closure given by the caller of 'apply' method.
+ * 'key' is the iterated key of the anydb. It can not be changed.
+ * 'value' is the value stored in the database for the key.
+ */
+typedef anydb_action_t anydb_applycb_t(void *closure, const anydb_key_t *key, anydb_value_t *value);
+
+/**
+ * Interface to any database implementation
+ */
 struct anydb_itf
 {
+       /**
+        * Get the index of the 'name' in 'idx'. If the name is found
+        * then its index is returned. If the name is not found, the
+        * database backend has to create it if 'create' is not zero.
+        * 'clodb' is the database's closure.
+        * Returns 0 in case of success (*idx filled with the index)
+        * or return a negative error code in -errno like form.
+        */
        int (*index)(void *clodb, anydb_idx_t *idx, const char *name, bool create);
+
+       /**
+        * Get the string for the index 'idx'. idx MUST be valid.
+        * 'clodb' is the database's closure.
+        */
        const char *(*string)(void *clodb, anydb_idx_t idx);
+
+       /**
+        * Start, Commit or Cancel a cancellable transaction. The operation
+        * to perform is given by 'op'.
+        * 'clodb' is the database's closure.
+        * Returns 0 in case of success or return a negative error code
+        * in -errno like form.
+        */
        int (*transaction)(void *clodb, anydb_transaction_t atomic_op);
-       void (*apply)(void *clodb, anydb_action_t (*oper)(void *closure, const anydb_key_t *key, anydb_value_t *value), void *closure);
+
+       /**
+        * Iterate over the database items and apply the operator 'oper'.
+        * The callback operator 'oper' is called with the given 'closure'
+        * and the key and value for the item. It can modify or delete the item.
+        * 'clodb' is the database's closure.
+        */
+       void (*apply)(void *clodb, anydb_applycb_t *oper, void *closure);
+
+       /**
+        * Add the item of 'key' and 'value'.
+        * 'clodb' is the database's closure.
+        * Returns 0 in case of success or return a negative error code
+        * in -errno like form.
+        */
        int (*add)(void *clodb, const anydb_key_t *key, const anydb_value_t *value);
+
+       /**
+        * Garbage collection of unused items.
+        * 'clodb' is the database's closure.
+        */
        void (*gc)(void *clodb);
+
+       /**
+        * Synchronize the database and its longterm support (file)
+        * 'clodb' is the database's closure.
+        * Returns 0 in case of success or return a negative error code
+        * in -errno like form.
+        */
        int (*sync)(void *clodb);
+
+       /**
+        * Destroys the database
+        * 'clodb' is the database's closure.
+        */
        void (*destroy)(void *clodb);
 };
 typedef struct anydb_itf anydb_itf_t;
 
+/**
+ * The structure for abstracting backend databases
+ */
 struct anydb
 {
+       /** the closure */
        void *clodb;
+
+       /** the implementation methods */
        anydb_itf_t itf;
 };
 typedef struct anydb anydb_t;
 
-/** manage atomicity of operations */
+/**
+ * Manage atomicity of modifications by enabling cancellation
+ * @param db database to manage
+ * @param oper operation to perform
+ * @return 0 in case of success or a negative error code in -errno like form.
+ */
 extern
 int
 anydb_transaction(
@@ -113,28 +233,44 @@ anydb_transaction(
        anydb_transaction_t oper
 );
 
-/** enumerate */
+/**
+ * Enumerate items of the database matching the given key
+ * @param db database to enumerate
+ * @param callback callback function receiving the item that matches the key
+ * @param closure closure for the callback
+ * @param key key to restrict enumeration can't be NULL
+ */
 extern
 void
 anydb_for_all(
        anydb_t *db,
-       void *closure,
        void (*callback)(
                void *closure,
                const data_key_t *key,
                const data_value_t *value),
+       void *closure,
        const data_key_t *key
 );
 
-/** drop rules */
+/**
+ * Drop any rule that matches the key
+ * @param db database to modify
+ * @param key the key that select items to be dropped
+ */
 extern
-int
+void
 anydb_drop(
        anydb_t *db,
        const data_key_t *key
 );
 
-/** set a rules */
+/**
+ * Set the rule described by key and value
+ * @param db the database to set
+ * @param key the key of the rule
+ * @param value the value of the rule
+ * @return 0 on success or a negative error code
+ */
 extern
 int
 anydb_set(
@@ -143,39 +279,60 @@ anydb_set(
        const data_value_t *value
 );
 
-/** test a rule, returns 0 or the score: count of exact keys */
+/**
+ * Test a rule and return its score and the value
+ * @param db the database
+ * @param key key to be matched by rules
+ * @param value value found for the key, filled only if a key matched
+ * @return 0 if no rule matched or a positive integer when the rule matched
+ * The higher the integer is, the more accurate is the rule found.
+ */
 extern
-int
+unsigned
 anydb_test(
        anydb_t *db,
        const data_key_t *key,
        data_value_t *value
 );
 
-/** drop rules */
+/**
+ * Drop any expired rule
+ * @param db the database to clean
+ */
 extern
 void
 anydb_cleanup(
        anydb_t *db
 );
 
-/** is the database empty? */
+/**
+ * Is the database empty?
+ * @param db the database to test
+ * @return true if the database is empty or otherwise false
+ */
 extern
 bool
 anydb_is_empty(
        anydb_t *db
 );
 
-/** destroy the database */
+/**
+ * Synchronize the database if needed
+ * @param db the database to
+ * @return 0 on success or a negative -errno like code
+ */
 extern
-void
-anydb_destroy(
+int
+anydb_sync(
        anydb_t *db
 );
 
-/** synchronize database */
+/**
+ * Destroy the database
+ * @param db the database to destroy
+ */
 extern
-int
-anydb_sync(
+void
+anydb_destroy(
        anydb_t *db
 );
index ca4234a..bed0b49 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF CACHE IN CLIENTS                                         */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <stdbool.h>
@@ -64,12 +68,25 @@ typedef struct item item_t;
  */
 struct cache
 {
+       /** used for clearing */
        uint32_t cacheid;
+
+       /** count of bytes used */
        uint32_t used;
+
+       /** count of bytes allocated */
        uint32_t count;
+
+       /** content of the cache */
        uint8_t content[];
 };
 
+/**
+ * return the item at a given position
+ * @param cache the cache
+ * @param pos the position of the item
+ * @return the item
+ */
 static
 inline
 item_t *
@@ -80,6 +97,11 @@ itemat(
        return (item_t*)(&cache->content[pos]);
 }
 
+/**
+ * Removes the item at position pos
+ * @param cache the cache
+ * @param pos the position of the item to remove
+ */
 static
 void
 drop_at(
@@ -95,6 +117,10 @@ drop_at(
                memmove(&cache->content[pos], &cache->content[e], cache->used - pos);
 }
 
+/**
+ * Removes the oldest hit target
+ * @param cache the cache
+ */
 static
 void
 drop_lre(
@@ -117,6 +143,11 @@ drop_lre(
                drop_at(cache, found);
 }
 
+/**
+ * tells the target is used
+ * @param cache the cache
+ * @param target the target to hit
+ */
 static
 void
 hit(
@@ -141,34 +172,55 @@ hit(
        }
 }
 
+/**
+ * Compare the head with a string and either return NULL if it doesn't match or
+ * otherwise return the pointer to the next string for heading.
+ * @param head head of scan
+ * @param other string to compare
+ * @return NULL if no match or pointer to the strings that follows head if match
+ */
 static
 const char*
-cmpi(
+cmp(
        const char *head,
        const char *other
 ) {
        char c;
-       while(toupper(c = *head++) == toupper(*other++))
+       while((c = *head++) == *other++)
                if (!c)
                        return head;
-       return 0;
+       return NULL;
 }
 
+/**
+ * Compare in a case independant method the head with a string and either
+ * return NULL if it doesn't match or otherwise return the pointer to the
+ * next string for heading.
+ * @param head head of scan
+ * @param other string to compare
+ * @return NULL if no match or pointer to the strings that follows head if match
+ */
 static
 const char*
-cmp(
+cmpi(
        const char *head,
        const char *other
 ) {
        char c;
-       while((c = *head++) == *other++)
+       while(toupper(c = *head++) == toupper(*other++))
                if (!c)
                        return head;
        return 0;
 }
 
+/**
+ * Check if a head of strings matche the key
+ * @param head the head of strings
+ * @param key the key
+ * @return true if matches or false other wise
+ */
 static
-int
+bool
 match(
        const char *head,
        const rcyn_key_t *key
@@ -181,13 +233,19 @@ match(
                        if (head) {
                                head = cmpi(head, key->permission);
                                if (head)
-                                       return 1;
+                                       return true;
                        }
                }
        }
-       return 0;
+       return false;
 }
 
+/**
+ * Search the item matching key and return it. Also remove expired entries
+ * @param cache the cache
+ * @param key the key to search
+ * @return the found item or NULL if not found
+ */
 static
 item_t*
 search(
@@ -214,6 +272,7 @@ search(
        return found;
 }
 
+/* see cache.h */
 int
 cache_put(
        cache_t *cache,
@@ -255,6 +314,7 @@ cache_put(
        return 0;
 }
 
+/* see cache.h */
 int
 cache_search(
        cache_t *cache,
@@ -272,6 +332,7 @@ cache_search(
        return -ENOENT;
 }
 
+/* see cache.h */
 void
 cache_clear(
        cache_t *cache,
@@ -283,35 +344,43 @@ cache_clear(
        }
 }
 
+/* see cache.h */
 int
 cache_resize(
        cache_t **cache,
        uint32_t newsize
 ) {
-       cache_t *c = *cache, *nc;
+       cache_t *oldcache = *cache, *newcache;
 
        if (newsize == 0) {
-               free(c);
-               nc = NULL;
+               /* erase all */
+               free(oldcache);
+               newcache = NULL;
        } else {
-               if (c)
-                       while (c->used > newsize)
-                               drop_lre(c);
+               /* coerce cache values if downsizing */
+               if (oldcache) {
+                       while (oldcache->used > newsize)
+                               drop_lre(oldcache);
+               }
 
-               nc = realloc(c, newsize + sizeof *c);
-               if (nc == NULL)
+               /* reallocate the cache */
+               newcache = realloc(oldcache, newsize + sizeof *oldcache);
+               if (newcache == NULL)
                        return -ENOMEM;
 
-               nc->count = newsize;
-               if (!c) {
-                       nc->cacheid = 0;
-                       nc->used = 0;
+               /* init */
+               newcache->count = newsize;
+               if (!oldcache) {
+                       newcache->cacheid = 0;
+                       newcache->used = 0;
                }
        }
-       *cache = nc;
+       /* update cache */
+       *cache = newcache;
        return 0;
 }
 
+/* see cache.h */
 int
 cache_create(
        cache_t **cache,
index dd37d92..d694e9b 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF CACHE IN CLIENTS                                         */
+/******************************************************************************/
+/******************************************************************************/
 
-struct cache;
+/** opaque structure for cache */
 typedef struct cache cache_t;
 
+/**
+ * Search the stored value for the key
+ * @param cache the cache handler
+ * @param key the key to search
+ * @return the stored value or -ENOENT if not found
+ */
 extern
 int
 cache_search(
@@ -27,6 +37,16 @@ cache_search(
        const rcyn_key_t *key
 );
 
+/**
+ * Add the value for the key in the cache
+ * @param cache the cache handler
+ * @param key the key to cache
+ * @param value the value (must be an integer from -128 to 127)
+ * @param expire expiration date
+ * @return 0 on success
+ *         -EINVAL invalid argument
+ *         -ENOMEM too big for the cache size
+ */
 extern
 int
 cache_put(
@@ -36,6 +56,11 @@ cache_put(
        time_t expire
 );
 
+/**
+ * Clear the content of the cache if the cacheid doesn't match the current one
+ * @param cache the cache handler
+ * @param cacheid the cacheid to set or zero to force clearing
+ */
 extern
 void
 cache_clear(
@@ -43,6 +68,13 @@ cache_clear(
        uint32_t cacheid
 );
 
+/**
+ *
+ * @param cache pointer to the cache handler
+ * @param newsize new size to set to the cache
+ * @return 0 on success
+ *         -ENOMEM not enough memory
+ */
 extern
 int
 cache_resize(
@@ -50,6 +82,13 @@ cache_resize(
        uint32_t newsize
 );
 
+/**
+ *
+ * @param cache pointer to the cache handler
+ * @param size size to set to the cache
+ * @return 0 on success
+ *         -ENOMEM not enough memory
+ */
 extern
 int
 cache_create(
index 6978251..f82e3cd 100644 (file)
--- a/src/cyn.c
+++ b/src/cyn.c
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF LOCAL CYNARA API                                         */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <assert.h>
 #include <stdlib.h>
@@ -31,6 +36,9 @@
 #if !CYN_SEARCH_DEEP_MAX
 # define CYN_SEARCH_DEEP_MAX 10
 #endif
+#if !defined(AGENT_SEPARATOR_CHARACTER)
+# define AGENT_SEPARATOR_CHARACTER ':'
+#endif
 
 /**
  * items of the list of observers or awaiters
@@ -39,14 +47,19 @@ struct callback
 {
        /** link to the next item of the list */
        struct callback *next;
+
+       /** recording of callback function */
        union {
                /** any callback value */
                void *any_cb;
+
                /** awaiter callback */
                on_enter_cb_t *on_enter_cb;
+
                /** observer callback */
                on_change_cb_t *on_change_cb;
        };
+
        /** closure of the callback */
        void *closure;
 };
@@ -65,7 +78,7 @@ struct agent
        /** closure of the callback */
        void *closure;
 
-       /** length of the name */
+       /** length of the name (without terminating zero) */
        uint8_t len;
 
        /** name of the agent */
@@ -73,7 +86,7 @@ struct agent
 };
 
 /**
- * structure handling an asynchronous check
+ * structure handling an asynchronous requests
  */
 struct cyn_query
 {
@@ -86,15 +99,12 @@ struct cyn_query
        /** key of the check */
        data_key_t key;
 
-       /** value of the check */
-       data_value_t value;
-
        /** down counter for recursivity limitation */
        int decount;
 };
 
-/** locking critical section */
-static const void *lock;
+/** for locking critical section with magic */
+static const void *magic_locker;
 
 /** head of the list of critical section awaiters */
 static struct callback *awaiters;
@@ -102,17 +112,24 @@ static struct callback *awaiters;
 /** head of the list of change observers */
 static struct callback *observers;
 
-/** head of the list of agents */
+/** head of the list of recorded agents */
 static struct agent *agents;
 
-/** last changeid */
-static uint32_t last_changeid;
+/** holding of changeid */
+static struct {
+       /** current changeid */
+       uint32_t current;
 
-/** changeid of the current 'changeid_string' */
-static uint32_t last_changeid_string;
+       /** changeid set in string */
+       uint32_t instring;
 
-/** string buffer for changeid */
-static char changeid_string[12];
+       /** string value for a changeid */
+       char string[12];
+} changeid = {
+       .current = 1,
+       .instring = 0,
+       .string = { 0 }
+};
 
 /**
  * Delete from the list represented by 'head' the entry for
@@ -179,7 +196,7 @@ changed(
 ) {
        struct callback *c;
 
-       ++last_changeid;
+       changeid.current = changeid.current + 1 ?: 1;
        for (c = observers; c ; c = c->next)
                c->on_change_cb(c->closure);
 }
@@ -191,9 +208,9 @@ cyn_enter(
 ) {
        if (!magic)
                return -EINVAL;
-       if (lock)
+       if (magic_locker)
                return -EBUSY;
-       lock = magic;
+       magic_locker = magic;
        return 0;
 }
 
@@ -205,10 +222,10 @@ cyn_enter_async(
 ) {
        if (!magic)
                return -EINVAL;
-       if (lock)
+       if (magic_locker)
                return addcb(enter_cb, magic, &awaiters);
 
-       lock = magic;
+       magic_locker = magic;
        enter_cb(magic);
        return 0;
 }
@@ -251,12 +268,12 @@ cyn_leave(
 
        if (!magic)
                return -EINVAL;
-       if (!lock)
+       if (!magic_locker)
                return -EALREADY;
-       if (lock != magic)
+       if (magic_locker != magic)
                return -EPERM;
 
-       lock = &lock;
+       magic_locker = &magic_locker;
        if (!commit)
                rc = 0;
        else {
@@ -273,7 +290,7 @@ cyn_leave(
        /* wake up awaiting client */
        e = awaiters;
        if (!e)
-               lock = 0;
+               magic_locker = 0;
        else {
                /* the one to awake is at the end of the list */
                p = &awaiters;
@@ -282,7 +299,7 @@ cyn_leave(
                        e = *p;
                }
                *p = NULL;
-               lock = e->closure;
+               magic_locker = e->closure;
                e->on_enter_cb(e->closure);
                free(e);
        }
@@ -296,7 +313,7 @@ cyn_set(
        const data_key_t *key,
        const data_value_t *value
 ) {
-       if (!lock)
+       if (!magic_locker)
                return -EPERM;
        return queue_set(key, value);
 }
@@ -306,7 +323,7 @@ int
 cyn_drop(
        const data_key_t *key
 ) {
-       if (!lock)
+       if (!magic_locker)
                return -EPERM;
        return queue_drop(key);
 }
@@ -314,15 +331,16 @@ cyn_drop(
 /* see cyn.h */
 void
 cyn_list(
-       void *closure,
        list_cb_t *callback,
+       void *closure,
        const data_key_t *key
 ) {
-       db_for_all(closure, callback, key);
+       db_for_all(callback, closure, key);
 }
 
 /**
  * initialize value to its default
+ *
  * @param value to initialize
  * @return the initialized value
  */
@@ -338,8 +356,9 @@ default_value(
 
 /**
  * Search the agent of name and return its item in the list
+ *
  * @param name of the agent to find (optionally zero terminated)
- * @param len length of the name
+ * @param len length of the name (without terminating zero)
  * @param ppprev for catching the pointer referencing the return item
  * @return 0 if not found or the pointer to the item of the found agent
  */
@@ -347,56 +366,51 @@ static
 struct agent *
 search_agent(
        const char *name,
-       uint8_t len,
+       size_t length,
        struct agent ***ppprev
 ) {
        struct agent *it, **pprev;
 
        pprev = &agents;
        while((it = *pprev)
-         &&  (len != it->len || memcmp(it->name, name, (size_t)len)))
+         &&  ((uint8_t)length != it->len || memcmp(it->name, name, length)))
                pprev = &it->next;
        *ppprev = pprev;
        return it;
 }
 
 /**
- * Return the agent required by the value or 0 if no agent is required
+ * Return the agent required by the value or NULL if no agent is required
  * or if the agent is not found.
+ *
  * @param value string where agent is the prefix followed by one colon
- * @return the item of the required agent or 0 when no agent is required
+ * @return the item of the required agent or NULL when no agent is required
  */
 static
-struct agent *
+struct agent*
 required_agent(
        const char *value
 ) {
        struct agent **pprev;
-       uint8_t len;
-
-       for (len = 0 ; len < UINT8_MAX && value[len] ; len++)
-               if (value[len] == ':')
-                       return search_agent(value, len, &pprev);
-       return 0;
-}
+       size_t length;
 
-static
-void
-async_call_agent(
-       struct agent *agent,
-       cyn_query_t *query,
-       const data_value_t *value
-) {
-       int rc = agent->agent_cb(
-                       agent->name,
-                       agent->closure,
-                       &query->key,
-                       &value->value[agent->len + 1],
-                       query);
-       if (rc < 0)
-               cyn_reply_query(query, value);
+       for (length = 0 ; length <= UINT8_MAX && value[length] ; length++)
+               if (value[length] == AGENT_SEPARATOR_CHARACTER)
+                       return search_agent(value, length, &pprev);
+       return NULL;
 }
 
+/**
+ * Allocates the query structure for handling the given parameters
+ * and return it. The query structure copies the key data to be compatible
+ * with asynchronous processing.
+ *
+ * @param on_result_cb the result callback to record
+ * @param closure the closure for the result callback
+ * @param key the key of the query
+ * @param maxdepth maximum depth of the agent subrequests
+ * @return the allocated structure or NULL in case of memory depletion
+ */
 static
 cyn_query_t *
 alloc_query(
@@ -420,6 +434,9 @@ alloc_query(
                ptr = &query[1];
                query->on_result_cb = on_result_cb;
                query->closure = closure;
+               query->decount = maxdepth;
+
+               /* copy strings of the key */
                if (!key->client)
                        query->key.client = 0;
                else {
@@ -442,19 +459,13 @@ alloc_query(
                        query->key.permission = 0;
                else {
                        query->key.permission = ptr;
-                       ptr = mempcpy(ptr, key->permission, szper);
+                       mempcpy(ptr, key->permission, szper);
                }
-               query->decount = maxdepth;
        }
        return query;
 }
 
-
-
-
-
-
-
+/* see cyn.h */
 int
 cyn_query_async(
        on_result_cb_t *on_result_cb,
@@ -463,25 +474,26 @@ cyn_query_async(
        int maxdepth
 ) {
        int rc;
+       unsigned score;
        data_value_t value;
        cyn_query_t *query;
        struct agent *agent;
 
        /* get the direct value */
-       rc = db_test(key, &value);
+       score = db_test(key, &value);
 
-       /* on error or missing result */
-       if (rc <= 0) {
+       /* missing value */
+       if (score == 0) {
                default_value(&value);
                on_result_cb(closure, &value);
-               return rc;
+               return 0;
        }
 
        /* if not an agent or agent not required */
        agent = required_agent(value.value);
        if (!agent || maxdepth <= 0) {
                on_result_cb(closure, &value);
-               return rc;
+               return 0;
        }
 
        /* allocate asynchronous query */
@@ -492,8 +504,15 @@ cyn_query_async(
        }
 
        /* call the agent */
-       async_call_agent(agent, query, &value);
-       return 0;
+       rc = agent->agent_cb(
+                       agent->name,
+                       agent->closure,
+                       &query->key,
+                       &value.value[agent->len + 1],
+                       query);
+       if (rc < 0)
+               cyn_query_reply(query, &value);
+       return rc;
 }
 
 /* see cyn.h */
@@ -516,8 +535,9 @@ cyn_check_async(
        return cyn_query_async(on_result_cb, closure, key, CYN_SEARCH_DEEP_MAX);
 }
 
+/* see cyn.h */
 int
-cyn_subquery_async(
+cyn_query_subquery_async(
        cyn_query_t *query,
        on_result_cb_t *on_result_cb,
        void *closure,
@@ -526,8 +546,9 @@ cyn_subquery_async(
        return cyn_query_async(on_result_cb, closure, key, query->decount - 1);
 }
 
+/* see cyn.h */
 void
-cyn_reply_query(
+cyn_query_reply(
        cyn_query_t *query,
        const data_value_t *value
 ) {
@@ -535,9 +556,28 @@ cyn_reply_query(
        free(query);
 }
 
-
-
-
+/**
+ * Check the name and compute its length. Returns 0 in case of invalid name
+ * @param name the name to check
+ * @return the length of the name or zero if invalid
+ */
+static
+size_t
+check_agent_name(
+       const char *name
+) {
+       size_t length = 0;
+       if (name) {
+               while (name[length]) {
+                       if (length > UINT8_MAX || name[length] == AGENT_SEPARATOR_CHARACTER) {
+                               length = 0;
+                               break;
+                       }
+                       length++;
+               }
+       }
+       return length;
+}
 
 /* see cyn.h */
 int
@@ -548,26 +588,28 @@ cyn_agent_add(
 ) {
        struct agent *agent, **pprev;
        size_t length;
-       uint8_t len;
 
-       length = strlen(name);
-       if (length <= 0 || length > UINT8_MAX)
+       /* compute and check name length */
+       length = check_agent_name(name);
+       if (!length)
                return -EINVAL;
-       len = (uint8_t)length++;
 
-       agent = search_agent(name, len, &pprev);
+       /* search the agent */
+       agent = search_agent(name, length, &pprev);
        if (agent)
                return -EEXIST;
 
-       agent = malloc(sizeof *agent + length);
+       /* allocates the memory */
+       agent = malloc(sizeof *agent + 1 + length);
        if (!agent)
                return -ENOMEM;
 
+       /* initialize the agent */
        agent->next = 0;
        agent->agent_cb = agent_cb;
        agent->closure = closure;
-       agent->len = len;
-       memcpy(agent->name, name, length);
+       agent->len = (uint8_t)length;
+       memcpy(agent->name, name, length + 1);
        *pprev = agent;
 
        return 0;
@@ -580,17 +622,18 @@ cyn_agent_remove(
 ) {
        struct agent *agent, **pprev;
        size_t length;
-       uint8_t len;
 
-       length = strlen(name);
-       if (length <= 0 || length > UINT8_MAX)
+       /* compute and check name length */
+       length = check_agent_name(name);
+       if (!length)
                return -EINVAL;
-       len = (uint8_t)length;
 
-       agent = search_agent(name, len, &pprev);
+       /* search the agent */
+       agent = search_agent(name, length, &pprev);
        if (!agent)
                return -ENOENT;
 
+       /* remove the found agent */
        *pprev = agent->next;
        free(agent);
        return 0;
@@ -600,14 +643,15 @@ cyn_agent_remove(
 void
 cyn_changeid_reset(
 ) {
-       last_changeid = 1;
+       changeid.current = 1;
+       changeid.instring = 0;
 }
 
 /* see cyn.h */
 uint32_t
 cyn_changeid(
 ) {
-       return last_changeid;
+       return changeid.current;
 }
 
 /* see cyn.h */
@@ -615,9 +659,10 @@ const char *
 cyn_changeid_string(
 ) {
        /* regenerate the string on need */
-       if (last_changeid != last_changeid_string) {
-               last_changeid_string = last_changeid;
-               snprintf(changeid_string, sizeof changeid_string, "%u", last_changeid);
+       if (changeid.current != changeid.instring) {
+               changeid.instring = changeid.current;
+               snprintf(changeid.string, sizeof changeid.string, "%u", changeid.current);
        }
-       return changeid_string;
+       /* return the string */
+       return changeid.string;
 }
index 5772608..fa361f6 100644 (file)
--- a/src/cyn.h
+++ b/src/cyn.h
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF LOCAL CYNARA API                                         */
+/******************************************************************************/
+/******************************************************************************/
 
-#define CYN_VERSION 99
+#define CYN_VERSION 100
 
 /**
  * Callback for entering asynchronousely the critical section
@@ -120,7 +123,7 @@ cyn_leave(
  *         -ENOMEM critical section already locked but request can't be queued
  *         -EINVAL magic == NULL
  *
- * @see cyn_leave, cyn_enter
+ * @see cyn_leave, cyn_enter, cyn_enter_async_cancel
  */
 extern
 int
@@ -131,9 +134,12 @@ cyn_enter_async(
 
 /**
  * Cancel a an asynchonous waiter to enter
+ *
  * @param enter_cb the enter callback of the waiter
  * @param magic the closure of the waiter
  * @return 0 if entry found and removed, -ENOENT if not found
+ *
+ * @see cyn_enter_async
  */
 extern
 int
@@ -149,6 +155,8 @@ cyn_enter_async_cancel(
  * @param closure closure of the callback
  * @return 0 success
  *         -ENOMEM can't queue the observer
+ *
+ * @see cyn_on_change_remove
  */
 extern
 int
@@ -159,9 +167,12 @@ cyn_on_change_add(
 
 /**
  * Removes an on change observer
+ *
  * @param on_change_cb the callback of the observer
  * @param closure the closure of the observer
  * @return 0 if entry found and removed, -ENOENT if not found
+ *
+ * @see cyn_on_change_add
  */
 extern
 int
@@ -172,6 +183,7 @@ cyn_on_change_remove(
 
 /**
  * Set or add the rule key/value to the change list to commit
+ *
  * @param key the key of the rule
  * @param value the value of the rule for the key
  * @return 0 on success
@@ -187,6 +199,7 @@ cyn_set(
 
 /**
  * Drop any rule matching the key
+ *
  * @param key the key of the rule
  * @return 0 on success
  *         -EPERM if not locked in critical recoverable section
@@ -198,14 +211,37 @@ cyn_drop(
        const data_key_t *key
 );
 
+/**
+ * Enumerate all items matching the key
+ *
+ * @param callback callback function called for each found item
+ * @param closure the closure to the callback
+ * @param key the key to select items
+ */
 extern
 void
 cyn_list(
-       void *closure,
        list_cb_t *callback,
+       void *closure,
        const data_key_t *key
 );
 
+/**
+ * Query the value for the given key.
+ *
+ * Note that the callback can be called during the call to that function.
+ *
+ * Note also that the callback will always be called either before the
+ * function returns or else later.
+ *
+ * @param on_result_cb callback function receiving the result
+ * @param closure closure for the callback
+ * @param key key to be queried
+ * @param maxdepth maximum imbrication of agent resolution
+ * @return 0 if there was no error or return the error code
+ *
+ * @see cyn_test_async, cyn_check_async
+ */
 extern
 int
 cyn_query_async(
@@ -215,6 +251,21 @@ cyn_query_async(
        int maxdepth
 );
 
+/**
+ * Same as cyn_query_async but with a maxdepth of 0
+ *
+ * Note that the callback can be called during the call to that function.
+ *
+ * Note also that the callback will always be called either before the
+ * function returns or else later.
+ *
+ * @param on_result_cb callback function receiving the result
+ * @param closure closure for the callback
+ * @param key key to be queried
+ * @return
+ *
+ * @see cyn_query_async, cyn_check_async
+ */
 extern
 int
 cyn_test_async(
@@ -223,6 +274,21 @@ cyn_test_async(
        const data_key_t *key
 );
 
+/**
+ * Same as cyn_query_async but with a default maxdepth for agent subqueries
+ *
+ * Note that the callback can be called during the call to that function.
+ *
+ * Note also that the callback will always be called either before the
+ * function returns or else later.
+ *
+ * @param on_result_cb callback function receiving the result
+ * @param closure closure for the callback
+ * @param key key to be queried
+ * @return 0 or -ENOMEM if some error occured
+ *
+ * @see cyn_query_async, cyn_test_async
+ */
 extern
 int
 cyn_check_async(
@@ -231,22 +297,53 @@ cyn_check_async(
        const data_key_t *key
 );
 
+/**
+ * Makes a recursive query asynchronous
+ *
+ * Note that the callback can be called during the call to that function.
+ *
+ * Note also that the callback will always be called either before the
+ * function returns or else later.
+ *
+ * @param query the query
+ * @param on_result_cb callback function receiving the result
+ * @param closure closure for the callback
+ * @param key key to be queried
+ * @return
+ */
 extern
 int
-cyn_subquery_async(
+cyn_query_subquery_async(
        cyn_query_t *query,
        on_result_cb_t *on_result_cb,
        void *closure,
        const data_key_t *key
 );
 
+/**
+ * Send the reply to a query
+ *
+ * @param query the query to reply
+ * @param value the reply value
+ */
 extern
 void
-cyn_reply_query(
+cyn_query_reply(
        cyn_query_t *query,
        const data_value_t *value
 );
 
+/**
+ * Add the agent of name
+ *
+ * @param name name of the agent to add
+ * @param agent_cb callback of the agent
+ * @param closure closure of the callback of the agent
+ * @return 0 in case of success
+ *         -EINVAL if the name is too long
+ *         -EEXIST if an agent of the same name is already recorded
+ *         -ENOMEM if out of memory
+ */
 extern
 int
 cyn_agent_add(
@@ -255,22 +352,47 @@ cyn_agent_add(
        void *closure
 );
 
+/**
+ * Remove the agent of 'name'
+ *
+ * @param name name of the agent to remove
+ * @return 0 in case of successful removal
+ *         -EINVAL if the name is too long
+ *         -ENOENT if the agent isn't recorded
+ */
 extern
 int
 cyn_agent_remove(
        const char *name
 );
 
+/**
+ * Reset the changeid
+ *
+ * @see cyn_changeid, cyn_changeid_string
+ */
 extern
 void
 cyn_changeid_reset(
 );
 
+/**
+ * Get the current changeid
+ * @return the current changeid
+ *
+ * @see cyn_changeid_rest, cyn_changeid_string
+ */
 extern
 uint32_t
 cyn_changeid(
 );
 
+/**
+ * Get the current changeid as a string
+ * @return the string of the current change id
+ *
+ * @see cyn_changeid_rest, cyn_changeid
+ */
 extern
 const char *
 cyn_changeid_string(
index 0e1a3b0..3c87ac3 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* GENERIC COMMON DATA TYPES FOR CLIENTS                                      */
+/******************************************************************************/
+/******************************************************************************/
+
+/** Maximum length of any string */
+#define MAX_NAME_LENGTH 8000
 
+/** string for deniying access */
 #define DENY    "no"
+
+/** string for allowing access */
 #define ALLOW   "yes"
-#define ASK     "ask"
+
+/** default is denying */
 #define DEFAULT DENY
 
+/**
+ * ANY string, made of one single character, is used to match
+ * rules and keys that can contain WIDE or other value.
+ * This allow to search specifically to WIDE when WIDE is specified in the
+ * search key or to any value (including WIDE) when any is used.
+ */
 #define Data_Any_Char '#'
-#define Data_Wide_Char '*'
-
 #define Data_Any_String "#"
-#define Data_Wide_String "*"
 
-typedef enum data_keyidx data_keyidx_t;
-typedef union data_key data_key_t;
-typedef struct data_value data_value_t;
+/**
+ * WIDE string, made of one character, is used in rules to match any
+ * queried value.
+ */
+#define Data_Wide_Char '*'
+#define Data_Wide_String "*"
 
+/**
+ * Name of the index on keys
+ */
 enum data_keyidx {
        KeyIdx_Client,
        KeyIdx_Session,
@@ -39,21 +59,39 @@ enum data_keyidx {
        KeyIdx_Permission,
        KeyIdx_Count
 };
+typedef enum data_keyidx data_keyidx_t;
 
+/**
+ * A key is made of 4 strings that can be accessed by index or by name
+ */
 union data_key {
        /* name access */
        struct {
+               /** the client */
                const char *client;
+
+               /** the session */
                const char *session;
+
+               /** the user */
                const char *user;
+
+               /** the permission */
                const char *permission;
        };
-       /* arrayed access, see data_keyidx_t */
+       /** Array for index access, see data_keyidx_t */
        const char *keys[KeyIdx_Count];
 };
+typedef union data_key data_key_t;
 
+/**
+ * A value is made of a string (mainly ALLOW or DENY) and an expiration.
+ */
 struct data_value {
+       /** judgment of the rule: ALLOW, DENY or agent description */
        const char *value;
+
+       /** expiration time of the rule */
        time_t expire;
 };
-
+typedef struct data_value data_value_t;
index aebead2..09151a1 100644 (file)
--- a/src/db.c
+++ b/src/db.c
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* INTERNAL DATABASE IMPLEMENTATION                                           */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <assert.h>
 #include <stdlib.h>
 
 static anydb_t *memdb;
 static anydb_t *filedb;
+static bool modifiable;
 
-/** check whether the 'text' fit String_Any, String_Wide, NULL or ""  */
+/**
+ * check whether the 'text' fit String_Any, String_Wide, NULL or ""
+ * @param text the text to check
+ * @return true if ANY or WIDE
+ */
 static
 bool
 is_any_or_wide(
@@ -46,7 +56,7 @@ is_any_or_wide(
 }
 
 
-/** open the database for files 'names' and 'rules' (can be NULL) */
+/* see db.h */
 int
 db_open(
        const char *directory
@@ -62,7 +72,7 @@ db_open(
        return rc;
 }
 
-/** close the database */
+/* see db.h */
 void
 db_close(
 ) {
@@ -70,32 +80,41 @@ db_close(
        anydb_destroy(memdb);
 }
 
-/** is the database empty */
+/* see db.h */
 bool
 db_is_empty(
 ) {
        return anydb_is_empty(filedb);
 }
 
-/** enter atomic mode */
+/* see db.h */
 int
 db_transaction_begin(
 ) {
-       int rc1, rc2;
+       int rc1, rc2, rc;
+
+       if (modifiable)
+               return -EALREADY;
 
        rc1 = anydb_transaction(filedb, Anydb_Transaction_Start);
        rc2 = anydb_transaction(memdb, Anydb_Transaction_Start);
 
-       return rc1 ?: rc2;
+       rc = rc1 ?: rc2;
+       modifiable = !rc;
+
+       return rc;
 }
 
-/** leave atomic mode */
+/* see db.h */
 int
 db_transaction_end(
        bool commit
 ) {
        int rc1, rc2, rc3, rc4;
 
+       if (!modifiable)
+               return -EALREADY;
+
        if (commit) {
                rc1 = anydb_transaction(filedb, Anydb_Transaction_Commit);
                rc2 = anydb_transaction(memdb, Anydb_Transaction_Commit);
@@ -106,54 +125,61 @@ db_transaction_end(
                rc3 = 0;
        }
        rc4 = db_sync();
+       modifiable = false;
 
        return rc1 ?: rc2 ?: rc3 ?: rc4;
 }
 
 
-/** enumerate */
+/* see db.h */
 void
 db_for_all(
-       void *closure,
        void (*callback)(
                void *closure,
                const data_key_t *key,
                const data_value_t *value),
+       void *closure,
        const data_key_t *key
 ) {
-       anydb_for_all(filedb, closure, callback, key);
-       anydb_for_all(memdb, closure, callback, key);
+       anydb_for_all(filedb, callback, closure, key);
+       anydb_for_all(memdb, callback, closure, key);
 }
 
-/** drop rules */
+/* see db.h */
 int
 db_drop(
        const data_key_t *key
 ) {
+       if (!modifiable)
+               return -EACCES;
+
        anydb_drop(filedb, key);
        anydb_drop(memdb, key);
        return 0;
 }
 
-/** set rules */
+/* see db.h */
 int
 db_set(
        const data_key_t *key,
        const data_value_t *value
 ) {
-       if (is_any_or_wide(key->session))
-               return anydb_set(filedb, key, value);
-       else
-               return anydb_set(memdb, key, value);
+       anydb_t *db;
+
+       if (!modifiable)
+               return -EACCES;
+
+       db = is_any_or_wide(key->session) ? filedb : memdb;
+       return anydb_set(db, key, value);
 }
 
-/** check rules */
-int
+/* see db.h */
+unsigned
 db_test(
        const data_key_t *key,
        data_value_t *value
 ) {
-       int s1, s2;
+       unsigned s1, s2;
        data_value_t v1, v2;
 
        s1 = anydb_test(memdb, key, &v1);
@@ -161,12 +187,13 @@ db_test(
        if (s2 > s1) {
                *value = v2;
                return s2;
-       } else {
-               *value = v1;
-               return s1;
        }
+       if (s1)
+               *value = v1;
+       return s1;
 }
 
+/* see db.h */
 int
 db_cleanup(
 ) {
@@ -175,6 +202,7 @@ db_cleanup(
        return 0;
 }
 
+/* see db.h */
 int
 db_sync(
 ) {
index edb4f29..0171c02 100644 (file)
--- a/src/db.h
+++ b/src/db.h
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* INTERNAL DATABASE IMPLEMENTATION                                           */
+/******************************************************************************/
+/******************************************************************************/
 
-#define MAX_NAME_LENGTH 32767
-
-/** open the database for files 'names' and 'rules' (can be NULL) */
+/**
+ * Open the database in the directory
+ *
+ * @param directory the directory containing the database
+ * @return 0 in case of success or a negative error code
+ *
+ * @see db_close
+ */
 extern
 int
 db_open(
        const char *directory
 );
 
-/** close the database */
+/**
+ * close the database
+ */
 extern
 void
 db_close(
 );
 
-/** is the database empty */
+/**
+ * Is the database empty?
+ *
+ * @return true if empty or else false
+ */
 extern
 bool
 db_is_empty(
 );
 
-/** enter atomic mode */
+/**
+ * Enter atomic mode or cancelable mode
+ *
+ * @return 0 in case of success or a negative -errno like value
+ *
+ * @see db_transaction_end, db_drop, db_set
+ */
 extern
 int
 db_transaction_begin(
 );
 
-/** leave atomic mode */
+/**
+ * Leave atomic mode commiting or not the changes
+ *
+ * @param commit if true changes are commited otherwise, if false cancel them
+ * @return 0 in case of success or a negative -errno like value
+ *
+ * @see db_transaction_begin, db_drop, db_set
+ */
 extern
 int
 db_transaction_end(
        bool commit
 );
 
-/** enumerate */
-extern
-void
-db_for_all(
-       void *closure,
-       void (*callback)(
-               void *closure,
-               const data_key_t *key,
-               const data_value_t *value),
-       const data_key_t *key
-);
-
-/** erase rules */
+/**
+ * Erase rules matching the key
+ *
+ * @param key the search key for the rules to remove
+ * @return 0 in case of success or a negative -errno like value
+ *
+ * @see db_transaction_begin, db_transaction_end, db_set
+ */
 extern
 int
 db_drop(
        const data_key_t *key
 );
 
-/** set rules */
+/**
+ * Add the rule of key and value
+ *
+ * @param key the key of the rule to add
+ * @param value the value of the rule
+ * @return 0 in case of success or a negative -errno like value
+ *
+ * @see db_transaction_begin, db_transaction_end, db_drop
+ */
 extern
 int
 db_set(
@@ -78,21 +109,54 @@ db_set(
        const data_value_t *value
 );
 
-/** check rules */
+/**
+ * Iterate over rules matching the key: call the callback for each found item
+ *
+ * @param callback the callback function to be call for each rule matching key
+ * @param closure the closure of the callback
+ * @param key the searching key
+ */
 extern
-int
+void
+db_for_all(
+       void (*callback)(
+               void *closure,
+               const data_key_t *key,
+               const data_value_t *value),
+       void *closure,
+       const data_key_t *key
+);
+
+/**
+ * Get the rule value for the key
+ *
+ * @param key The key to query
+ * @param value Where to store the result if any
+ * @return 0 if no rule matched (value unchanged then) or a positive integer
+ *  when a value was found for the key
+ */
+extern
+unsigned
 db_test(
        const data_key_t *key,
        data_value_t *value
 );
 
-/** cleanup the base */
+/**
+ * Cleanup the database by removing expired items
+ *
+ * @return 0 in case of success or a negative -errno like value
+ */
 extern
 int
 db_cleanup(
 );
 
-/** cleanup the base */
+/**
+ * Write the database to the file system (synchrnize it)
+ *
+ * @return 0 in case of success or a negative -errno like value
+ */
 extern
 int
 db_sync(
index b1b3c54..e2366ad 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* READING DATABASE RULE FILES FOR INITIALISATION                             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <time.h>
@@ -28,7 +33,7 @@
 #include "expire.h"
 #include "dbinit.h"
 
-/** initialize the database from file of 'path' */
+/* see dbinit.h */
 int dbinit_add_file(const char *path)
 {
        int rc, lino;
@@ -115,8 +120,10 @@ error2:
        fclose(f);
 error:
        if (rc)
+               /* cancel changes if error occured */
                cyn_leave(dbinit_add_file, 0);
        else {
+               /* commit the changes */
                rc = cyn_leave(dbinit_add_file, 1);
                if (rc < 0)
                        fprintf(stderr, "unable to commit content of file %s\n", path);
index bca4afc..a546575 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* READING DATABASE RULE FILES FOR INITIALISATION                             */
+/******************************************************************************/
+/******************************************************************************/
 
-extern int dbinit_add_file(const char *path);
+/**
+ * Add to the database the data from file of 'path'
+ *
+ * ---------------------------------------------------------------------------
+ * The file must be made of lines being either empty, comment or rule
+ *
+ * Empty lines or comment lines are ignored.
+ *
+ * An empty line only contains spaces and/or tabs
+ *
+ * A comment line start with the character #. It can be preceded by any count
+ * of spaces and/or tabs.
+ *
+ * Other lines are rules. They must be made of 6 fields separated by any count
+ * of space and/or tabs. Spaces and tabs at the begining of the line are
+ * ignored.
+ *
+ * The 6 fields of a rule are:
+ *
+ *       CLIENT SESSION USER PERMISSION VALUE EXPIRATION
+ *
+ * CLIENT, SESSION, USER, PERMISSION are arbitrary strings. The single star
+ * mean 'any value'.
+ *
+ * Value must be a string of some meaning. Known values are:
+ *
+ *   - yes:   grant the permission
+ *   - no:    forbid the permission
+ *   - @:...: agent at (@)
+ *
+ * Expiration can be expressed
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * @param path path of the initialization file
+ * @return 0 in case of success or a negative -errno like code
+ */
+extern
+int
+dbinit_add_file(
+       const char *path
+);
 
index 68278ca..cfa5dff 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* CONVERTION OF EXPIRATIONS TO AND FROM TEXT                                 */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <time.h>
 #include <string.h>
 #include <stdio.h>
 
+#include "expire.h"
+
 static const int SEC = 1;
 static const int MIN = 60;
 static const int HOUR = 60*60;
 static const int DAY = 24*60*60;
 static const int WEEK = 7*24*60*60;
-static const int YEAR = 365*24*60*60;
+static const int YEAR = 365*24*60*60 + 24*60*60/4;
 
+/* see expire.h */
 time_t txt2exp(const char *txt)
 {
        time_t r, x;
@@ -39,7 +47,7 @@ time_t txt2exp(const char *txt)
        while(*txt) {
                x = 0;
                while('0' <= *txt && *txt <= '9')
-                       x = 10 * x + (time_t)(*txt++ - '0');
+                       x = (x << 3) + (x << 1) + (time_t)(*txt++ - '0');
                switch(*txt) {
                case 'y': r += x * YEAR; txt++; break;
                case 'w': r += x * WEEK; txt++; break;
@@ -54,6 +62,7 @@ time_t txt2exp(const char *txt)
        return r;
 }
 
+/* see expire.h */
 size_t exp2txt(time_t expire, char *buffer, size_t buflen)
 {
        char b[100];
index c9e46bc..1de82c2 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* CONVERTION OF EXPIRATIONS TO AND FROM TEXT                                 */
+/******************************************************************************/
+/******************************************************************************/
+
+/**
+ * Converts the time of the string to an expiration
+ *
+ * The string code a time relative to now using the format
+ * XXXyXXXwXXXdXXXhXXXmXXXs where XXX are numbers.
+ *
+ * Examples:
+ *  - 15 means 15 seconds
+ *  - 4h15m30s means 4 hours 15 minutes 30 seconds
+ *  - forever means forever
+ *  - 2m2w means two months and 2 weeks
+ *
+ * @param txt the text to convert
+ * @return the value for the text
+ */
+extern
+time_t
+txt2exp(
+       const char *txt
+);
 
-extern time_t txt2exp(const char *txt);
-extern size_t exp2txt(time_t expire, char *buffer, size_t buflen);
+/**
+ * Converts the expiration in to its relative string representation
+ *
+ * @param expire the epiration to convert
+ * @param buffer the buffer where to store the converted string
+ * @param buflen length of the buffer
+ * @return the length of the resulting string, can be greater than buflen but
+ * in that case, no more than buflen characters are copied to buffer
+ */
+extern
+size_t
+exp2txt(
+       time_t expire,
+       char *buffer,
+       size_t buflen
+);
index c4243e6..0c88fcb 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF BUFFERED FILES                                           */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <assert.h>
 #include <stdlib.h>
 
 #include "fbuf.h"
 
-/** compute the size to allocate for ensuring 'sz' bytes */
+/**
+ * compute the size to allocate for ensuring 'sz' bytes
+ * @param sz the expected size
+ * @return a size greater than sz
+ */
 static
 uint32_t
 get_asz(
        uint32_t sz
 ) {
-       return (sz & 0xfffffc00) + 0x000004cf;
+       uint32_t r = (sz & 0xfffffc00) + 0x000004cf;
+       return r > sz ? r : UINT32_MAX;
 }
 
-/** open in 'fb' the file of 'name' */
+/**
+ * Open in 'fb' the file of 'name'
+ * @param fb the fbuf
+ * @param name the name of the file to read
+ * @return 0 on success
+ *         -EFBIG if the file is too big
+ *         -errno system error
+ */
 static
 int
 read_file(
@@ -91,7 +108,7 @@ error:
        return rc;
 }
 
-/** open in 'fb' the file of 'name' */
+/* see fbuf.h */
 int
 fbuf_open(
        fbuf_t  *fb,
@@ -105,18 +122,19 @@ fbuf_open(
        memset(fb, 0, sizeof *fb);
 
        /* save name */
-       fb->name = strdup(name);
+       sz = strlen(name);
+       fb->name = malloc(sz + 1);
        if (fb->name == NULL)
                goto error;
+       mempcpy(fb->name, name, sz + 1);
 
        /* open the backup */
        if (backup != NULL)
                fb->backup = strdup(backup);
        else {
-               sz = strlen(name);
                fb->backup = malloc(sz + 2);
                if (fb->backup != NULL) {
-                       memcpy(fb->backup, name, sz);
+                       mempcpy(fb->backup, name, sz);
                        fb->backup[sz] = '~';
                        fb->backup[sz + 1] = 0;
                }
@@ -129,6 +147,7 @@ fbuf_open(
        if (rc < 0)
                goto error;
 
+       /* any read data is already saved */
        fb->saved = fb->used;
        return 0;
 
@@ -139,7 +158,7 @@ error:
        return rc;
 }
 
-/** close the file 'fb' */
+/* see fbuf.h */
 void
 fbuf_close(
        fbuf_t  *fb
@@ -150,7 +169,7 @@ fbuf_close(
        memset(fb, 0, sizeof *fb);
 }
 
-/** write to file 'fb' the unsaved bytes and flush the content to the file */
+/* see fbuf.h */
 int
 fbuf_sync(
        fbuf_t  *fb
@@ -173,6 +192,8 @@ fbuf_sync(
        close(fd);
        if (rcs < 0)
                goto error;
+       if ((uint32_t)rcs != fb->used)
+               goto error; /* TODO: set some errno? */
 
        fb->size = fb->saved = fb->used;
        return 0;
@@ -183,29 +204,29 @@ error:
        return rc;
 }
 
-/** allocate enough memory in 'fb' to store 'count' bytes */
+/* see fbuf.h */
 int
 fbuf_ensure_capacity(
        fbuf_t  *fb,
-       uint32_t count
+       uint32_t capacity
 ) {
-       uint32_t capacity;
+       uint32_t asz;
        void *buffer;
 
-       if (count > fb->capacity) {
-               capacity = get_asz(count);
-               buffer = realloc(fb->buffer, capacity);
+       if (capacity > fb->capacity) {
+               asz = get_asz(capacity);
+               buffer = realloc(fb->buffer, asz);
                if (buffer == NULL) {
-                       fprintf(stderr, "alloc %u for file %s failed: %m\n", capacity, fb->name);
+                       fprintf(stderr, "alloc %u for file %s failed: %m\n", asz, fb->name);
                        return -ENOMEM;
                }
                fb->buffer = buffer;
-               fb->capacity = capacity;
+               fb->capacity = asz;
        }
        return 0;
 }
 
-/** put at 'offset' in the memory of 'fb' the 'count' bytes pointed by 'buffer' */
+/* see fbuf.h */
 int
 fbuf_put(
        fbuf_t  *fb,
@@ -214,12 +235,13 @@ fbuf_put(
        uint32_t offset
 ) {
        int rc;
-       uint32_t end = offset + count;
+       uint32_t end;
 
        /* don't call me for nothing */
        assert(count);
 
        /* grow as necessary */
+       end = offset + count;
        if (end > fb->used) {
                rc = fbuf_ensure_capacity(fb, end);
                if (rc < 0)
@@ -236,7 +258,7 @@ fbuf_put(
        return 0;
 }
 
-/** append at end in the memory of 'fb' the 'count' bytes pointed by 'buffer' */
+/* see fbuf.h */
 int
 fbuf_append(
        fbuf_t  *fb,
@@ -249,7 +271,7 @@ fbuf_append(
        return fbuf_put(fb, buffer, count, fb->used);
 }
 
-/** check or make identification of file 'fb' by 'id' of 'len' */
+/* see fbuf.h */
 int
 fbuf_identify(
        fbuf_t  *fb,
@@ -265,12 +287,11 @@ fbuf_identify(
                return 0;
 
        /* bad identification */
-       errno = ENOKEY;
        fprintf(stderr, "identification of file %s failed: %m\n", fb->name);
        return -ENOKEY;
 }
 
-/** check or make identification by 'uuid' of file 'fb' */
+/* see fbuf.h */
 int
 fbuf_open_identify(
        fbuf_t  *fb,
@@ -281,16 +302,18 @@ fbuf_open_identify(
 ) {
        int rc;
 
+       /* open the files */
        rc = fbuf_open(fb, name, backup);
        if (rc == 0) {
+               /* check identifier */
                rc = fbuf_identify(fb, id, idlen);
                if (rc < 0)
-                       fbuf_close(fb);
+                       fbuf_close(fb); /* close if error */
        }
        return rc;
 }
 
-/** make a backup */
+/* see fbuf.h */
 int
 fbuf_backup(
        fbuf_t  *fb
@@ -299,7 +322,7 @@ fbuf_backup(
        return link(fb->name, fb->backup);
 }
 
-/** recover from latest backup */
+/* see fbuf.h */
 int
 fbuf_recover(
        fbuf_t  *fb
index 43909fa..ee9ac25 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF BUFFERED FILES                                           */
+/******************************************************************************/
+/******************************************************************************/
 
 /**
  * A fbuf records file data and access
@@ -48,7 +52,14 @@ struct fbuf
 typedef struct fbuf fbuf_t;
 
 
-/** open in 'fb' the file of 'name' and optionnal 'backup' name */
+/**
+ * open in 'fb' the file of 'name'
+ * @param fb the fbuf
+ * @param name name of the filename to read
+ * @param backup name of the backup to use (can be NULL)
+ * @return 0 on success
+ *         a negative -errno code
+ */
 extern
 int
 fbuf_open(
@@ -57,21 +68,35 @@ fbuf_open(
        const char *backup
 );
 
-/** close the file 'fb' */
+/**
+ * close the fbuf 'fb'
+ * @param fb the fbuf to close
+ */
 extern
 void
 fbuf_close(
        fbuf_t  *fb
 );
 
-/** write to file 'fb' the unsaved bytes and flush the content to the file */
+/**
+ * write to fbuf 'fb' the unsaved bytes and flush the content to the file
+ * @param fb the fbuf
+ * @return 0 on success
+ *         a negative -errno code
+ */
 extern
 int
 fbuf_sync(
        fbuf_t  *fb
 );
 
-/** allocate enough memory in 'fb' to store 'count' bytes */
+/**
+ * allocate enough memory in 'fb' to store 'count' bytes
+ * @param fb the fbuf
+ * @param capacity expected capacity
+ * @return 0 on success
+ *         -ENOMEM if out of memory
+ */
 extern
 int
 fbuf_ensure_capacity(
@@ -79,7 +104,15 @@ fbuf_ensure_capacity(
        uint32_t count
 );
 
-/** put at 'offset' in the memory of 'fb' the 'count' bytes pointed by 'buffer' */
+/**
+ * put at 'offset' in the memory of 'fb' the 'count' bytes pointed by 'buffer'
+ * @param fb the fbuf
+ * @param buffer pointer to the data
+ * @param count size of data MUST BE GREATER THAN ZERO
+ * @param offset where to put the data
+ * @return 0 on success
+ *         -ENOMEM if out of memory
+ */
 extern
 int
 fbuf_put(
@@ -89,7 +122,14 @@ fbuf_put(
        uint32_t offset
 );
 
-/** append at end in the memory of 'fb' the 'count' bytes pointed by 'buffer' */
+/**
+ * append at end in the memory of 'fb' the 'count' bytes pointed by 'buffer'
+ * @param fb the fbuf
+ * @param buffer pointer to the data
+ * @param count size of data MUST BE GREATER THAN ZERO
+ * @return 0 on success
+ *         -ENOMEM if out of memory
+ */
 extern
 int
 fbuf_append(
@@ -98,7 +138,16 @@ fbuf_append(
        uint32_t count
 );
 
-/** check or make identification of file 'fb' by 'id' of 'len' */
+/**
+ * Check or make identification of file 'fb' by 'id' of 'idlen'
+ * If the content is empty, it initialize the identification prefix.
+ * Otherwise, not empty, the check is performed.
+ * @param fb the fbuf to check
+ * @param id the prefix identifier to check
+ * @param idlen the length of the identifier
+ * @return 0 on success
+ *         -ENOKEY if identification failed
+ */
 extern
 int
 fbuf_identify(
@@ -107,7 +156,19 @@ fbuf_identify(
        uint32_t idlen
 );
 
-/** check or make identification by 'uuid' of file 'fb' */
+/**
+ * Open the fbuf 'fb' of 'name', 'backup' and check that it has the
+ * prefix identifier 'id' of length 'idlen'.
+ * @param fb the fbuf to open
+ * @param name file name to open
+ * @param backup name of the backup file
+ * @param id identifier prefix value
+ * @param idlen length of the identifier prefix
+ * @return 0 in case of success
+ *         -ENOMEM if out of memory
+ *         -ENOKEY if identification failed
+ *         a negative -errno code
+ */
 extern
 int
 fbuf_open_identify(
@@ -118,12 +179,26 @@ fbuf_open_identify(
        uint32_t idlen
 );
 
+/**
+ * Create the back-up file
+ * Backup is managed using hard links. It implies that the operating system
+ * handles hard links.
+ * @param fb the fbuf
+ * @return 0 in case of success
+ *         a negative -errno code
+ */
 extern
 int
 fbuf_backup(
        fbuf_t  *fb
 );
 
+/**
+ * recover data from latest backup
+ * @param fb the fbuf
+ * @return 0 on success
+ *         a negative -errno code
+ */
 extern
 int
 fbuf_recover(
index ce37ad1..9a57a68 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF DATABASE WITH FILE BACKEND                               */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <assert.h>
 #include <stdlib.h>
@@ -31,8 +36,6 @@
 #include "fbuf.h"
 #include "filedb.h"
 
-#define MAX_NAME_LENGTH 32768
-
 /*
  * for the first version,  save enougth time up to 4149
  * 4149 = 1970 + (4294967296 * 16) / (365 * 24 * 60 * 60)
@@ -125,11 +128,16 @@ struct filedb
        bool has_backup;
 
        /** the anydb interface */
-       anydb_t db;
+       anydb_t anydb;
 };
 typedef struct filedb filedb_t;
 
-/** return the name of 'index' */
+/**
+ * Return the name of the given index
+ * @param filedb the database handler
+ * @param index index of the string MUST be valid
+ * @return the name for the index
+ */
 static
 const char*
 name_at(
@@ -153,57 +161,62 @@ cmpnames(
        return strcmp(name_at(filedb, a), name_at(filedb, b));
 }
 
-/** initialize names */
+/**
+ * Initialize the fields 'names_sorted' and 'names_count' for the
+ * current database.
+ * @param filedb the database handler
+ * @return 0 in case of success or -ENOMEM or -ENOEXEC
+ */
 static
 int
 init_names(
        filedb_t *filedb
 ) {
-       uint32_t pos, len, *ns, *p, all, nc;
+       uint32_t pos, length, *sorted, *p, allocated, name_count;
 
-       all = 0;
-       nc = 0;
-       ns = NULL;
+       allocated = 0;
+       name_count = 0;
+       sorted = NULL;
 
        /* iterate over names */
        pos = uuidlen;
        while (pos < filedb->fnames.used) {
                /* get name length */
-               len = (uint32_t)strlen(name_at(filedb, pos));
-               if (pos + len <= pos || pos + len > filedb->fnames.used) {
-                       free(ns);
-                       goto bad_file;
+               length = (uint32_t)strlen(name_at(filedb, pos));
+               if (pos + length <= pos || pos + length > filedb->fnames.used) {
+                       /* overflow */
+                       free(sorted);
+                       fprintf(stderr, "bad file %s\n", filedb->fnames.name);
+                       return -ENOEXEC;
                }
                /* store the position */
-               if (all <= nc) {
-                       all += 1024;
-                       p = realloc(ns, all * sizeof *ns);
+               if (allocated <= name_count) {
+                       allocated += 1024;
+                       p = realloc(sorted, allocated * sizeof *sorted);
                        if (p == NULL) {
-                               free(ns);
+                               free(sorted);
                                fprintf(stderr, "out of memory\n");
-                               goto error;
+                               return -ENOMEM;
                        }
-                       ns = p;
+                       sorted = p;
                }
-               ns[nc++] = pos;
+               sorted[name_count++] = pos;
                /* next */
-               pos += len + 1;
+               pos += length + 1;
        }
 
        /* sort and record */
-       qsort_r(ns, nc, sizeof *ns, cmpnames, filedb);
-       filedb->names_sorted = ns;
-       filedb->names_count = nc;
+       qsort_r(sorted, name_count, sizeof *sorted, cmpnames, filedb);
+       filedb->names_sorted = sorted;
+       filedb->names_count = name_count;
        return 0;
-
-bad_file:
-       fprintf(stderr, "bad file %s\n", filedb->fnames.name);
-       errno = ENOEXEC;
-error:
-       return -1;
 }
 
-/** init the rules from the file */
+/**
+ * Initialize the fields 'rules' and 'rules_count' for the
+ * current database.
+ * @param filedb the database handler
+ */
 static
 void
 init_rules(
@@ -213,7 +226,21 @@ init_rules(
        filedb->rules_count = (filedb->frules.used - uuidlen) / sizeof *filedb->rules;
 }
 
-/** open a fbuf */
+/**
+ * Open the fbuf 'fb' in the directory, the name and the extension.
+ * Check that the identifier prefix matches or if the file doesn't exist
+ * create the prefix.
+ * @param fb the buffer to open
+ * @param directory the directory containing the file
+ * @param name the basename for the file
+ * @param extension the extension of the file
+ * @param id the identifier prefix
+ * @param idlen the length of the identifier prefix
+ * @return 0 in case of success
+ *         -ENOMEM if out of memory
+ *         -ENOKEY if identification failed
+ *         a negative -errno code
+ */
 static
 int
 open_identify(
@@ -224,25 +251,38 @@ open_identify(
        const char *id,
        uint32_t idlen
 ) {
-       char *file, *backup, *p;
+       char *file, *p;
        size_t ldir, lext, lname;
 
+       /* compute sizes */
        ldir = strlen(directory);
        lname = strlen(name);
        lext = strlen(extension);
-       file = alloca(((ldir + lname + lext) << 1) + 7);
+
+       /* allocate memory for file */
+       file = alloca((ldir + lname + lext) + 3);
+
+       /* make the file's name: directory/name.extension */
        p = mempcpy(file, directory, ldir);
        *p++ = '/';
        p = mempcpy(p, name, lname);
        *p++ = '.';
-       backup = mempcpy(p, extension, lext + 1);
-       p = mempcpy(backup, file, ldir + lname + lext + 2);
-       *p++ = '~';
-       *p = 0;
-       return fbuf_open_identify(fb, file, backup, id, idlen);
+       mempcpy(p, extension, lext + 1);
+
+       /* open the fbuf now */
+       return fbuf_open_identify(fb, file, NULL, id, idlen);
 }
 
-/** open the database for files 'names' and 'rules' (can be NULL) */
+/**
+ * Open the database of 'name' in 'directory'
+ * @param filedb the database handler to open
+ * @param directory the directory containing the database (or null for default)
+ * @param name the basename for the file
+ * @return 0 in case of success
+ *         -ENOMEM if out of memory
+ *         -ENOKEY if identification failed
+ *         a negative -errno code
+ */
 static
 int
 opendb(
@@ -262,26 +302,27 @@ opendb(
 
        /* open the names */
        rc = open_identify(&filedb->fnames, directory, name, "names", uuid_names_v2, uuidlen);
-       if (rc < 0)
-               goto error;
-
-       /* open the rules */
-       rc = open_identify(&filedb->frules, directory, name, "rules", uuid_rules_v2, uuidlen);
-       if (rc < 0)
-               goto error;
-
-       /* connect internals */
-       rc = init_names(filedb);
-       if (rc < 0)
-               goto error;
-
-       init_rules(filedb);
-       return 0;
-error:
-       return -1;
+       if (rc == 0) {
+               /* open the rules */
+               rc = open_identify(&filedb->frules, directory, name, "rules", uuid_rules_v2, uuidlen);
+               if (rc == 0) {
+                       /* connect internals */
+                       rc = init_names(filedb);
+                       if (rc == 0) {
+                               init_rules(filedb);
+                               return 0;
+                       }
+                       fbuf_close(&filedb->frules);
+               }
+               fbuf_close(&filedb->fnames);
+       }
+       return rc;
 }
 
-/** close the database */
+/**
+ * Close the database
+ * @param filedb database to close
+ */
 static
 void
 closedb(
@@ -292,7 +333,12 @@ closedb(
        fbuf_close(&filedb->frules);
 }
 
-/** synchronize db on files */
+/**
+ * Synchronize database and its files (write it to the filesystem)
+ * @param filedb database to synchronize
+ * @return 0 in case of success
+ *         a negative -errno code
+ */
 static
 int
 syncdb(
@@ -302,10 +348,12 @@ syncdb(
 
        assert(filedb->fnames.name && filedb->frules.name);
        if (!filedb->is_changed)
-               rc = 0;
+               rc = 0; /* unchanged */
        else {
+               /* sync the names */
                rc = fbuf_sync(&filedb->fnames);
                if (rc == 0) {
+                       /* sync the rules */
                        rc = fbuf_sync(&filedb->frules);
                        if (rc == 0) {
                                filedb->is_changed = false;
@@ -316,7 +364,12 @@ syncdb(
        return rc;
 }
 
-/** make a backup of the database */
+/**
+ * Creates backups of the database
+ * @param filedb the database to backup
+ * @return 0 in case of success
+ *         a negative -errno code
+ */
 static
 int
 backupdb(
@@ -326,21 +379,26 @@ backupdb(
 
        assert(filedb->fnames.name && filedb->frules.name);
        if (filedb->has_backup)
-               rc = 0;
+               rc = 0; /* already backuped */
        else {
+               /* backup names */
                rc = fbuf_backup(&filedb->fnames);
                if (rc == 0) {
+                       /* backup rules */
                        rc = fbuf_backup(&filedb->frules);
-                       if (rc == 0) {
+                       if (rc == 0)
                                filedb->has_backup = true;
-                               filedb->is_changed = false;
-                       }
                }
        }
        return rc;
 }
 
-/** recover the database from latest backup */
+/**
+ * recover the database from latest backup
+ * @param filedb database to recover
+ * @return 0 in case of success
+ *         a negative -errno code
+ */
 static
 int
 recoverdb(
@@ -352,14 +410,17 @@ recoverdb(
        if (!filedb->is_changed || !filedb->has_backup)
                rc = 0;
        else {
+               /* recover names */
                rc = fbuf_recover(&filedb->fnames);
                if (rc < 0)
                        goto error;
 
+               /* recover rules */
                rc = fbuf_recover(&filedb->frules);
                if (rc < 0)
                        goto error;
 
+               /* init names */
                rc = init_names(filedb);
                if (rc < 0)
                        goto error;
@@ -375,6 +436,7 @@ error:
        return rc;
 }
 
+/** implementation of anydb_itf.index */
 static
 int
 index_itf(
@@ -446,6 +508,7 @@ index_itf(
        return 0;
 }
 
+/** implementation of anydb_itf.string */
 static
 const char *
 string_itf(
@@ -454,14 +517,16 @@ string_itf(
 ) {
        filedb_t *filedb = clodb;
 
+       assert(idx < filedb->fnames.used);
        return name_at(filedb, idx);
 }
 
+/** implementation of anydb_itf.apply */
 static
 void
 apply_itf(
        void *clodb,
-       anydb_action_t (*oper)(void *closure, const anydb_key_t *key, anydb_value_t *value),
+       anydb_applycb_t *oper,
        void *closure
 ) {
        filedb_t *filedb = clodb;
@@ -469,7 +534,7 @@ apply_itf(
        rule_t *rule;
        anydb_key_t key;
        anydb_value_t value;
-       uint32_t i;
+       uint32_t i, saved;
 
        key.session = AnyIdx_Wide;
        i = 0;
@@ -481,29 +546,30 @@ apply_itf(
                value.value = rule->value;
                value.expire = exp2time(rule->expire);
                a = oper(closure, &key, &value);
-               switch (a) {
-               case Anydb_Action_Stop:
-                       return;
-               case Anydb_Action_Continue:
-                       i++;
-                       break;
-               case Anydb_Action_Update_And_Stop:
-                       rule->value = value.value;
-                       rule->expire = time2exp(value.expire);
-                       filedb->need_cleanup = true;
-                       filedb->is_changed = true;
-                       filedb->frules.saved = (uint32_t)((void*)rule - filedb->frules.buffer);
-                       return;
-               case Anydb_Action_Remove_And_Continue:
+               if (a & Anydb_Action_Remove) {
                        *rule = filedb->rules[--filedb->rules_count];
                        filedb->is_changed = true;
                        filedb->need_cleanup = true;
+                       saved = (uint32_t)((void*)rule - filedb->frules.buffer);
+                       if (saved < filedb->frules.saved)
+                               filedb->frules.saved = saved;
                        filedb->frules.used -= (uint32_t)sizeof *rule;
-                       break;
+               } else if (a & Anydb_Action_Update) {
+                       rule->value = value.value;
+                       rule->expire = time2exp(value.expire);
+                       filedb->need_cleanup = true;
+                       filedb->is_changed = true;
+                       saved = (uint32_t)((void*)rule - filedb->frules.buffer);
+                       if (saved < filedb->frules.saved)
+                               filedb->frules.saved = saved;
                }
+               if (a & Anydb_Action_Stop)
+                       return;
+               i += !(a & Anydb_Action_Remove);
        }
 }
 
+/** implementation of anydb_itf.transaction */
 static
 int
 transaction_itf(
@@ -531,6 +597,7 @@ transaction_itf(
        return rc;
 }
 
+/** implementation of anydb_itf.add */
 static
 int
 add_itf(
@@ -562,6 +629,16 @@ add_itf(
        return 0;
 }
 
+/**
+ * Search (dig) dichotomically in 'array' of 'count' elements the index of
+ * 'item'. Store '*index' either the index of the found item or the index
+ * where inserting the item. Return true if found of false otherwise.
+ * @param array array to dig
+ * @param count count of elements in array
+ * @param item item to dig
+ * @param index where to store the found index
+ * @return true if found of false otherwise.
+ */
 static
 bool
 gc_dig(
@@ -593,6 +670,13 @@ gc_dig(
        return false;
 }
 
+/**
+ * Add dichotomically the 'item' in the 'array' of 'count' elements
+ * @param array array to alter
+ * @param count count of element in the input array
+ * @param item the item to add
+ * @return the new count of elements
+ */
 static
 uint32_t
 gc_add(
@@ -602,18 +686,29 @@ gc_add(
 ) {
        uint32_t index, i;
 
+       /* search the item */
        if (gc_dig(array, count, item, &index))
-               return count;
+               return count; /* already in */
 
+       /* shift the elemetns above index */
        i = count;
        while (i > index) {
                array[i] = array[i - 1];
                i = i - 1;
        }
+
+       /* add the item */
        array[i] = item;
        return count + 1;
 }
 
+/**
+ * Mark in 'array' of 'count' elements the 'item'
+ * @param array the sorted array of marked items
+ * @param count the count of marked items
+ * @param item the item to mark
+ * @return the new count of marked items
+ */
 static
 uint32_t
 gc_mark(
@@ -624,30 +719,60 @@ gc_mark(
        return item > AnyIdx_Max ? count : gc_add(array, count, item);
 }
 
+/**
+ * Test if 'item' is marked in 'array' of 'count' marked elements
+ * @param array the sorted array of marked items
+ * @param count the count of marked items
+ * @param item the item to search
+ * @param index where to store the index of the item if found
+ * @return true is found (marked) or false otherwise (not marked)
+ */
 static
 bool
-gc_new(
+gc_is_marked(
        uint32_t *array,
        uint32_t count,
        uint32_t item,
        uint32_t *index
 ) {
-       return item > AnyIdx_Max ? false : gc_dig(array, count, item, index);
+       return item <= AnyIdx_Max && gc_dig(array, count, item, index);
+}
+
+/**
+ * Translate the item pointed by 'item' to its new value after renumeration
+ * @param marked the sorted array of marked items
+ * @param renum the renumerotation of the marked items
+ * @param count the count of marked items
+ * @param item the pointer to the item to modify
+ */
+static
+void
+gc_renum(
+       uint32_t *marked,
+       uint32_t *renum,
+       uint32_t count,
+       uint32_t *item
+) {
+       uint32_t index;
+
+       if (gc_is_marked(marked, count, *item, &index))
+               *item = renum[index];
 }
 
+/** implementation of anydb_itf.gc */
 static
 void
 gc_itf(
        void *clodb
 ) {
        filedb_t *filedb = clodb;
-       uint32_t nr;
-       uint32_t nn;
+       uint32_t rule_count;
+       uint32_t name_count;
        struct rule *rules;
-       uint32_t *used;
-       uint32_t *sorted;
+       uint32_t *marked;
+       uint32_t *renum;
        char *strings;
-       uint32_t ir, nu, idx, is, ios, lenz;
+       uint32_t irule, new_count, imarked, istr_before, istr_after, lenz;
 
        /* check cleanup required */
        if (!filedb->need_cleanup)
@@ -655,60 +780,57 @@ gc_itf(
        filedb->need_cleanup = false;
 
        /* mark items */
-       nr = filedb->rules_count;
-       nn = filedb->names_count;
+       rule_count = filedb->rules_count;
+       name_count = filedb->names_count;
        rules = filedb->rules;
-       used = alloca(nn * sizeof *used);
-       nu = 0;
-       for (ir = 0 ; ir < nr ; ir++) {
-               nu = gc_mark(used, nu, rules[ir].client);
-               nu = gc_mark(used, nu, rules[ir].user);
-               nu = gc_mark(used, nu, rules[ir].permission);
-               nu = gc_mark(used, nu, rules[ir].value);
+       marked = alloca(name_count * sizeof *marked);
+       new_count = 0;
+       for (irule = 0 ; irule < rule_count ; irule++) {
+               new_count = gc_mark(marked, new_count, rules[irule].client);
+               new_count = gc_mark(marked, new_count, rules[irule].user);
+               new_count = gc_mark(marked, new_count, rules[irule].permission);
+               new_count = gc_mark(marked, new_count, rules[irule].value);
        }
 
        /* pack if too much unused */
-       if (nu + (nu >> 2) <= nn)
+       if (new_count + (new_count >> 2) >= name_count)
                return;
 
-       /* pack the names */
+       /* pack the names by removing the unused strings */
        strings = (char*)filedb->fnames.buffer;
-       sorted = filedb->names_sorted;
-       is = ios = uuidlen;
-       while (is < filedb->fnames.used) {
+       renum = filedb->names_sorted;
+       istr_before = istr_after = uuidlen;
+       while (istr_before < filedb->fnames.used) {
                /* get name length */
-               lenz = 1 + (uint32_t)strlen(strings + is);
-               if (gc_dig(used, nu, is, &idx)) {
-                       sorted[idx] = ios;
-                       if (is != ios)
-                               memcpy(strings + ios, strings + is, lenz);
-                       ios += lenz;
+               lenz = 1 + (uint32_t)strlen(strings + istr_before);
+               if (gc_is_marked(marked, new_count, istr_before, &imarked)) {
+                       renum[imarked] = istr_after;
+                       if (istr_before != istr_after)
+                               memcpy(strings + istr_after, strings + istr_before, lenz);
+                       istr_after += lenz;
                }
                /* next */
-               is += lenz;
+               istr_before += lenz;
        }
 
        /* renum the rules */
-       for (ir = 0 ; ir < nr ; ir++) {
-               if (gc_new(used, nu, rules[ir].client, &idx))
-                       rules[ir].client = sorted[idx];
-               if (gc_new(used, nu, rules[ir].user, &idx))
-                       rules[ir].user = sorted[idx];
-               if (gc_new(used, nu, rules[ir].permission, &idx))
-                       rules[ir].permission = sorted[idx];
-               if (gc_new(used, nu, rules[ir].value, &idx))
-                       rules[ir].value = sorted[idx];
+       for (irule = 0 ; irule < rule_count ; irule++) {
+               gc_renum(marked, renum, new_count, &rules[irule].client);
+               gc_renum(marked, renum, new_count, &rules[irule].user);
+               gc_renum(marked, renum, new_count, &rules[irule].permission);
+               gc_renum(marked, renum, new_count, &rules[irule].value);
        }
 
        /* record and sort */
-       filedb->names_count = nu;
-       filedb->fnames.used = ios;
-       qsort_r(sorted, nu, sizeof *sorted, cmpnames, filedb);
+       filedb->names_count = new_count;
+       filedb->fnames.used = istr_after;
+       qsort_r(renum, new_count, sizeof *renum, cmpnames, filedb);
 
        /* set as changed */
        filedb->is_changed = true;
 }
 
+/** implementation of anydb_itf.sync */
 static
 int
 sync_itf(
@@ -718,6 +840,7 @@ sync_itf(
        return syncdb(filedb);
 }
 
+/** implementation of anydb_itf.destroy */
 static
 void
 destroy_itf(
@@ -731,23 +854,28 @@ destroy_itf(
        }
 }
 
+/**
+ * Initialize the anydb interface of filedb
+ * @param filedb the structure to initialize
+ */
 static
 void
-init(
+init_anydb_itf(
        filedb_t *filedb
 ) {
-       filedb->db.clodb = filedb;
-
-       filedb->db.itf.index = index_itf;
-       filedb->db.itf.string = string_itf;
-       filedb->db.itf.transaction = transaction_itf;
-       filedb->db.itf.apply = apply_itf;
-       filedb->db.itf.add = add_itf;
-       filedb->db.itf.gc = gc_itf;
-       filedb->db.itf.sync = sync_itf;
-       filedb->db.itf.destroy = destroy_itf;
+       filedb->anydb.clodb = filedb;
+
+       filedb->anydb.itf.index = index_itf;
+       filedb->anydb.itf.string = string_itf;
+       filedb->anydb.itf.transaction = transaction_itf;
+       filedb->anydb.itf.apply = apply_itf;
+       filedb->anydb.itf.add = add_itf;
+       filedb->anydb.itf.gc = gc_itf;
+       filedb->anydb.itf.sync = sync_itf;
+       filedb->anydb.itf.destroy = destroy_itf;
 }
 
+/* see filedb.h */
 int
 filedb_create(
        anydb_t **adb,
@@ -757,25 +885,21 @@ filedb_create(
        int rc;
        filedb_t *filedb;
 
+       /* allocates */
        *adb = NULL;
        filedb = calloc(1, sizeof *filedb);
        if (!filedb)
                return -ENOMEM;
 
-       init(filedb);
+       /* init anydb interface */
+       init_anydb_itf(filedb);
 
+       /* open the database file */
        rc = opendb(filedb, directory, basename);
        if (rc)
                free(filedb);
        else
-               *adb = &filedb->db;
+               *adb = &filedb->anydb;
        return rc;
 }
 
-/** synchronize database */
-int
-anydb_sync(
-       anydb_t *db
-) {
-       return db->itf.sync ? db->itf.sync(db->clodb) : 0;
-}
index d575e50..85d6c26 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF DATABASE WITH FILE BACKEND                               */
+/******************************************************************************/
+/******************************************************************************/
 
-
-/** is the database empty */
+/**
+ * Create the object handling the file database
+ * @param filedb pointer to the handling object to return
+ * @param directory the directory of the database
+ * @param basename the basename of the database
+ * @return 0 in case of success with *filedb fulfilled or negative -errno error
+ */
 int
 filedb_create(
        anydb_t **filedb,
index eb98895..63696fe 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+/******************************************************************************/
+/******************************************************************************/
+/* COMPATIBILITY LAYER TO PREVIOUS CYNARA                                     */
+/******************************************************************************/
+/******************************************************************************/
 /*
 cynara_admin_initialize(&m_CynaraAdmin),
 cynara_admin_finish(m_CynaraAdmin);
index e099d64..9f3a179 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF CYNARA ADMINISTRATION TOOL                               */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdint.h>
 #include <stdbool.h>
index 2b8b0d3..6ed1878 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF CYNARA SERVER                                            */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <stdint.h>
index 285d7a4..a67d1ef 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF IN MEMORY DATABASE WITHOUT FILE BACKEND                  */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <stdint.h>
 #include <time.h>
 #include <string.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "data.h"
 #include "anydb.h"
+#include "memdb.h"
 
-#define RBS 20 /**< rule block size */
-#define SBS 30 /**< string bloc size */
+#define RULE_BLOC_SIZE   20 /**< rule block size */
+#define STRING_BLOC_SIZE 30 /**< string bloc size */
 
-#define TCLE 0 /**< tag for clean */
-#define TDEL 1 /**< tag for deleted */
-#define TMOD 2 /**< tag for modified */
+#define TAG_CLEAN    0 /**< tag for clean */
+#define TAG_DELETED  1 /**< tag for deleted */
+#define TAG_CHANGED  2 /**< tag for modified */
 
+/**
+ * structure for rules of memory database
+ */
 struct rule
 {
+       /** the key */
        anydb_key_t key;
+
+       /** the current value */
        anydb_value_t value;
+
+       /** the next value (depends on tag) */
        anydb_value_t saved;
+
+       /** tag for the value saved */
        uint8_t tag;
 };
 
+/**
+ * Structure for the memory database
+ */
 struct memdb
 {
-       /* first for the fun */
+       /** first for the fun */
        anydb_t db;
 
-       /* strings */
+       /** strings */
        struct {
+               /** allocated count for strings */
                uint32_t alloc;
+               /** used count for strings */
                uint32_t count;
+               /** array of strings */
                char **values;
        } strings;
 
-       /* rules */
+       /** rules */
        struct {
+               /** allocated count for rules */
                uint32_t alloc;
+               /** used count for rules */
                uint32_t count;
+               /** array of rules */
                struct rule *values;
        } rules;
 
+       /** transaction */
        struct {
+               /** rule count at the beginning of the transaction */
                uint32_t count;
+               /** indicator for an active transaction */
                bool active;
        } transaction;
 };
 typedef struct memdb memdb_t;
 
+/** implementation of anydb_itf.index */
 static
 int
 index_itf(
@@ -99,13 +129,14 @@ index_itf(
        if (s == NULL)
                return -ENOMEM;
        if (memdb->strings.count == memdb->strings.alloc) {
-               strings = realloc(strings, (memdb->strings.alloc + SBS) * sizeof *strings);
+               strings = realloc(strings, (memdb->strings.alloc
+                                       + STRING_BLOC_SIZE) * sizeof *strings);
                if (!strings) {
                        free(s);
                        return -ENOMEM;
                }
                memdb->strings.values = strings;
-               memdb->strings.alloc += SBS;
+               memdb->strings.alloc += STRING_BLOC_SIZE;
        }
        i = memdb->strings.count;
        *idx = i;
@@ -114,6 +145,7 @@ index_itf(
        return 0;
 }
 
+/** implementation of anydb_itf.string */
 static
 const char *
 string_itf(
@@ -122,14 +154,16 @@ string_itf(
 ) {
        memdb_t *memdb = clodb;
 
+       assert(idx < memdb->strings.count);
        return memdb->strings.values[idx];
 }
 
+/** implementation of anydb_itf.apply */
 static
 void
 apply_itf(
        void *clodb,
-       anydb_action_t (*oper)(void *closure, const anydb_key_t *key, anydb_value_t *value),
+       anydb_applycb_t *oper,
        void *closure
 ) {
        memdb_t *memdb = clodb;
@@ -139,32 +173,29 @@ apply_itf(
 
        ir = 0;
        while (ir < memdb->rules.count) {
-               if (memdb->transaction.active && rules[ir].tag == TDEL)
-                       a = Anydb_Action_Continue;
-               else
-                       a = oper(closure, &rules[ir].key, &rules[ir].value);
-               switch (a) {
-               case Anydb_Action_Stop:
-                       return;
-               case Anydb_Action_Continue:
+               if (memdb->transaction.active && rules[ir].tag == TAG_DELETED)
                        ir++;
-                       break;
-               case Anydb_Action_Update_And_Stop:
-                       if (memdb->transaction.active)
-                               rules[ir].tag = TMOD;
-                       else
-                               rules[ir].saved = rules[ir].value;
-                       return;
-               case Anydb_Action_Remove_And_Continue:
-                       if (memdb->transaction.active)
-                               rules[ir++].tag = TDEL;
-                       else
-                               rules[ir] = rules[--memdb->rules.count];
-                       break;
+               else {
+                       a = oper(closure, &rules[ir].key, &rules[ir].value);
+                       if (a & Anydb_Action_Remove) {
+                               if (memdb->transaction.active)
+                                       rules[ir++].tag = TAG_DELETED;
+                               else
+                                       rules[ir] = rules[--memdb->rules.count];
+                       } else if (a & Anydb_Action_Update) {
+                               if (memdb->transaction.active)
+                                       rules[ir].tag = TAG_CHANGED;
+                               else
+                                       rules[ir].saved = rules[ir].value;
+                       }
+                       if (a & Anydb_Action_Stop)
+                               return;
+                       ir += !(a & Anydb_Action_Remove);
                }
        }
 }
 
+/** implementation of anydb_itf.transaction */
 static
 int
 transaction_itf(
@@ -191,14 +222,14 @@ transaction_itf(
                ir = 0;
                while(ir < count) {
                        switch (rules[ir].tag) {
-                       case TCLE:
+                       case TAG_CLEAN:
                                ir++;
                                break;
-                       case TDEL:
+                       case TAG_DELETED:
                                rules[ir] = rules[--count];
                                break;
-                       case TMOD:
-                               rules[ir++].tag = TCLE;
+                       case TAG_CHANGED:
+                               rules[ir++].tag = TAG_CLEAN;
                                break;
                        }
                }
@@ -211,9 +242,9 @@ transaction_itf(
                rules = memdb->rules.values;
                count = memdb->rules.count = memdb->transaction.count;
                for (ir = 0 ; ir < count ; ir++) {
-                       if (rules[ir].tag != TCLE) {
+                       if (rules[ir].tag != TAG_CLEAN) {
                                rules[ir].value = rules[ir].saved;
-                               rules[ir].tag = TCLE;
+                               rules[ir].tag = TAG_CLEAN;
                        }
                }
                memdb->transaction.active = false;
@@ -222,6 +253,7 @@ transaction_itf(
        return 0;
 }
 
+/** implementation of anydb_itf.add */
 static
 int
 add_itf(
@@ -238,7 +270,7 @@ add_itf(
        count = memdb->rules.count;
        alloc = memdb->rules.alloc;
        if (count == alloc) {
-               alloc += RBS;
+               alloc += RULE_BLOC_SIZE;
                rules = realloc(rules, alloc * sizeof *rules);
                if (!rules)
                        return -ENOMEM;
@@ -248,11 +280,16 @@ add_itf(
        rules = &rules[count];
        rules->key = *key;
        rules->saved = rules->value = *value;
-       rules->tag = TCLE;
+       rules->tag = TAG_CLEAN;
        memdb->rules.count = count + 1;
        return 0;
 }
 
+/**
+ * Mark the 'item' as being used
+ * @param renum array handling marked items
+ * @param item the item to check
+ */
 static
 void
 gc_mark(
@@ -263,32 +300,38 @@ gc_mark(
                renum[item] = 1;
 }
 
+/**
+ * return the renumring of 'item' within 'renum'
+ * @param renum the renumbering array
+ * @param item the item to renumber
+ * @return the renumbered item
+ */
 static
 anydb_idx_t
-gc_new(
+gc_renum(
        anydb_idx_t *renum,
        anydb_idx_t item
 ) {
        return item > AnyIdx_Max ? item : renum[item];
 }
-#include <stdio.h>
+
+/** implementation of anydb_itf.gc */
 static
 void
 gc_itf(
        void *clodb
 ) {
        memdb_t *memdb = clodb;
-       uint32_t nr = memdb->rules.count;
-       uint32_t ns = memdb->strings.count;
+       uint32_t i, j;
+       uint32_t rule_count = memdb->rules.count;
+       uint32_t name_count = memdb->strings.count;
        char **strings = memdb->strings.values;
        struct rule *rules = memdb->rules.values;
-       anydb_idx_t *renum = alloca(ns * sizeof *renum);
-       uint32_t i, j;
-
-       for (i = 0 ; i < ns ; i++)
-               renum[i] = 0;
+       anydb_idx_t *renum = alloca(name_count * sizeof *renum);
 
-       for (i = 0 ; i < nr ; i++) {
+       /* mark used strings */
+       memset(renum, 0, name_count * sizeof *renum);
+       for (i = 0 ; i < rule_count ; i++) {
                gc_mark(renum, rules[i].key.client);
                gc_mark(renum, rules[i].key.session);
                gc_mark(renum, rules[i].key.user);
@@ -296,7 +339,8 @@ gc_itf(
                gc_mark(renum, rules[i].value.value);
        }
 
-       for (i = j = 0 ; i < ns ; i++) {
+       /* pack the used strings */
+       for (i = j = 0 ; i < name_count ; i++) {
                if (renum[i]) {
                        strings[j] = strings[i];
                        renum[i] = j++;
@@ -305,34 +349,38 @@ gc_itf(
                        renum[i] = AnyIdx_Invalid;
                }
        }
-       if (ns != j) {
-               memdb->strings.count = ns = j;
-               for (i = 0 ; i < nr ; i++) {
-                       rules[i].key.client = gc_new(renum, rules[i].key.client);
-                       rules[i].key.session = gc_new(renum, rules[i].key.session);
-                       rules[i].key.user = gc_new(renum, rules[i].key.user);
-                       rules[i].key.permission = gc_new(renum, rules[i].key.permission);
-                       rules[i].value.value = gc_new(renum, rules[i].value.value);
+       if (name_count != j) {
+               /* renumber the items of the database */
+               memdb->strings.count = name_count = j;
+               for (i = 0 ; i < rule_count ; i++) {
+                       rules[i].key.client = gc_renum(renum, rules[i].key.client);
+                       rules[i].key.session = gc_renum(renum, rules[i].key.session);
+                       rules[i].key.user = gc_renum(renum, rules[i].key.user);
+                       rules[i].key.permission = gc_renum(renum, rules[i].key.permission);
+                       rules[i].value.value = gc_renum(renum, rules[i].value.value);
                }
        }
 
+       /* decrease size of array for strings */
        i = memdb->strings.alloc;
-       while (ns + SBS < i)
-               i -= SBS;
+       while (name_count + STRING_BLOC_SIZE < i)
+               i -= STRING_BLOC_SIZE;
        if (i != memdb->strings.alloc) {
                memdb->strings.alloc = i;
                memdb->strings.values = realloc(strings, i * sizeof *strings);
        }
 
+       /* decrease size of array for rules */
        i = memdb->rules.alloc;
-       while (nr + RBS < i)
-               i -= RBS;
+       while (rule_count + RULE_BLOC_SIZE < i)
+               i -= RULE_BLOC_SIZE;
        if (i != memdb->rules.alloc) {
                memdb->rules.alloc = i;
-               memdb->rules.values = realloc(rules, i * sizeof *strings);
+               memdb->rules.values = realloc(rules, i * sizeof *rules);
        }
 }
 
+/** implementation of anydb_itf.destroy */
 static
 void
 destroy_itf(
@@ -346,9 +394,13 @@ destroy_itf(
        }
 }
 
+/**
+ * Initialize the structure of the memory database
+ * @param memdb the structure to initialize
+ */
 static
 void
-init(
+init_memdb(
        memdb_t *memdb
 ) {
        memdb->db.clodb = memdb;
@@ -374,18 +426,22 @@ init(
        memdb->transaction.active = false;
 }
 
+/* see memdb.h */
 int
 memdb_create(
        anydb_t **memdb
 ) {
        memdb_t *mdb;
 
+       /* allocate */
        mdb = malloc(sizeof *mdb);
        if (!mdb) {
                *memdb = NULL;
                return -ENOMEM;
        }
-       init(mdb);
+
+       /* init */
+       init_memdb(mdb);
        *memdb = &mdb->db;
        return 0;
 }
index 0f1c9e7..a947296 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF IN MEMORY DATABASE WITHOUT FILE BACKEND                  */
+/******************************************************************************/
+/******************************************************************************/
 
+/**
+ * Create the object handling the memory database
+ * @param memdb pointer to the handling object to return
+ */
 extern
 int
 memdb_create(
index d183594..22d2505 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF EPOLL HELPER                                             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdint.h>
 #include <sys/epoll.h>
 
-/*
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <poll.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-*/
-
 #include "pollitem.h"
 
+/**
+ * Wraps the call to epoll_ctl for operation 'op'
+ *
+ * @param pollitem the pollitem to process
+ * @param events the expected events
+ * @param pollfd the file descriptor for epoll
+ * @param op the operation to perform
+ * @return 0 on success or -1 with errno set accordingly to epoll_ctl
+ */
 static
 int
 pollitem_do(
@@ -47,6 +46,7 @@ pollitem_do(
        return epoll_ctl(pollfd, op, pollitem->fd, &ev);
 }
 
+/* see pollitem.h */
 int
 pollitem_add(
        pollitem_t *pollitem,
@@ -56,6 +56,7 @@ pollitem_add(
        return pollitem_do(pollitem, events, pollfd, EPOLL_CTL_ADD);
 }
 
+/* see pollitem.h */
 int
 pollitem_mod(
        pollitem_t *pollitem,
@@ -65,6 +66,7 @@ pollitem_mod(
        return pollitem_do(pollitem, events, pollfd, EPOLL_CTL_MOD);
 }
 
+/* see pollitem.h */
 int
 pollitem_del(
        pollitem_t *pollitem,
@@ -73,6 +75,7 @@ pollitem_del(
        return pollitem_do(pollitem, 0, pollfd, EPOLL_CTL_DEL);
 }
 
+/* see pollitem.h */
 int
 pollitem_wait_dispatch(
        int pollfd,
index a60b7b8..375c674 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF EPOLL HELPER                                             */
+/******************************************************************************/
+/******************************************************************************/
 
 /** structure for using epoll easily */
 typedef struct pollitem pollitem_t;
 
+/**
+ * Structure for using epoll easily
+ */
 struct pollitem
 {
        /** callback on event */
        void (*handler)(pollitem_t *pollitem, uint32_t events, int pollfd);
 
-       /** data */
+       /** data of any kind free to use */
        void *closure;
 
-       /** file */
+       /** file descriptor */
        int fd;
 };
 
+/**
+ * Add a pollitem to epoll
+ *
+ * @param pollitem the pollitem to add
+ * @param events expected events
+ * @param pollfd file descriptor of the epoll
+ * @return 0 on success or -1 with errno set accordingly to epoll_ctl
+ */
 extern
 int
 pollitem_add(
@@ -38,6 +55,14 @@ pollitem_add(
        int pollfd
 );
 
+/**
+ * Modify a pollitem of epoll
+ *
+ * @param pollitem the pollitem to modify
+ * @param events expected events
+ * @param pollfd file descriptor of the epoll
+ * @return 0 on success or -1 with errno set accordingly to epoll_ctl
+ */
 extern
 int
 pollitem_mod(
@@ -46,6 +71,13 @@ pollitem_mod(
        int pollfd
 );
 
+/**
+ * Delete a pollitem from epoll
+ *
+ * @param pollitem the pollitem to delete
+ * @param pollfd file descriptor of the epoll
+ * @return 0 on success or -1 with errno set accordingly to epoll_ctl
+ */
 extern
 int
 pollitem_del(
@@ -53,6 +85,15 @@ pollitem_del(
        int pollfd
 );
 
+/**
+ * Wait one event on epoll and dispatch it to its pollitem callback
+ *
+ * @param pollfd file descriptor of the epoll
+ * @param timeout time to wait
+ * @return 0 on timeout
+ *         1 if a callback was called
+ *         -1 with errno set accordingly to epoll_wait
+ */
 extern
 int
 pollitem_wait_dispatch(
index 06edb2f..7edcc50 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF THE PROTOCOL                                             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <limits.h>
 
 #include "prot.h"
 
-/** the structure buf is generic the meaning of pos/count is not fixed */
+#define MAX_FIELDS          20
+#define MAX_BUFFER_LENGTH   2000
+#define FIELD_SEPARATOR     ' '
+#define RECORD_SEPARATOR    '\n'
+#define ESCAPE              '\\'
+
+/**
+ * the structure buf is generic the meaning of pos/count is not fixed
+ */
 struct buf
 {
        /** a position */
@@ -38,7 +51,7 @@ struct buf
        /* TODO: add a 3rd unsigned for improving management of read and write */
 
        /** a fixed size content */
-       char content[MAXBUFLEN];
+       char content[MAX_BUFFER_LENGTH];
 };
 typedef struct buf buf_t;
 
@@ -49,11 +62,13 @@ struct fields
        int count;
 
        /** the fields as strings */
-       const char *fields[MAXARGS];
+       const char *fields[MAX_FIELDS];
 };
 typedef struct fields fields_t;
 
-/** structure for handling the protocol */
+/**
+ * structure for handling the protocol
+ */
 struct prot
 {
        /** input buf, pos is the scanning position */
@@ -65,14 +80,13 @@ struct prot
        /** count of pending output fields */
        unsigned outfields;
 
-       /** cancel index value value */
+       /** cancel index when putting values */
        unsigned cancelidx;
 
        /** the fields */
        fields_t fields;
 };
 
-
 /**
  * Put the 'car' into the 'buf'
  * returns:
@@ -88,13 +102,13 @@ buf_put_car(
        unsigned pos;
 
        pos = buf->count;
-       if (pos >= MAXBUFLEN)
+       if (pos >= MAX_BUFFER_LENGTH)
                return -ECANCELED;
 
        buf->count = pos + 1;
        pos += buf->pos;
-       if (pos >= MAXBUFLEN)
-               pos -= MAXBUFLEN;
+       if (pos >= MAX_BUFFER_LENGTH)
+               pos -= MAX_BUFFER_LENGTH;
        buf->content[pos] = car;
        return 0;
 }
@@ -116,30 +130,30 @@ buf_put_string(
 
        remain = buf->count;
        pos = buf->pos + remain;
-       if (pos >= MAXBUFLEN)
-               pos -= MAXBUFLEN;
-       remain = MAXBUFLEN - remain;
+       if (pos >= MAX_BUFFER_LENGTH)
+               pos -= MAX_BUFFER_LENGTH;
+       remain = MAX_BUFFER_LENGTH - remain;
 
        /* put all chars of the string */
        while((c = *string++)) {
                /* escape special characters */
-               if (c == FS || c == RS || c == ESC) {
+               if (c == FIELD_SEPARATOR || c == RECORD_SEPARATOR || c == ESCAPE) {
                        if (!remain--)
                                goto cancel;
-                       buf->content[pos++] = ESC;
-                       if (pos == MAXBUFLEN)
+                       buf->content[pos++] = ESCAPE;
+                       if (pos == MAX_BUFFER_LENGTH)
                                pos = 0;
                }
                /* put the char */
                if (!remain--)
                        goto cancel;
                buf->content[pos++] = c;
-               if (pos == MAXBUFLEN)
+               if (pos == MAX_BUFFER_LENGTH)
                        pos = 0;
        }
 
        /* record the new values */
-       buf->count = MAXBUFLEN - remain;
+       buf->count = MAX_BUFFER_LENGTH - remain;
        return 0;
 
 cancel:
@@ -169,11 +183,11 @@ buf_write(
 
        /* prepare the iovec */
        vec[0].iov_base = buf->content + buf->pos;
-       if (buf->pos + count <= MAXBUFLEN) {
+       if (buf->pos + count <= MAX_BUFFER_LENGTH) {
                vec[0].iov_len = count;
                n = 1;
        } else {
-               vec[0].iov_len = MAXBUFLEN - buf->pos;
+               vec[0].iov_len = MAX_BUFFER_LENGTH - buf->pos;
                vec[1].iov_base = buf->content;
                vec[1].iov_len = count - vec[0].iov_len;
                n = 2;
@@ -191,14 +205,16 @@ buf_write(
                /* update the state */
                buf->count -= (unsigned)rc;
                buf->pos += (unsigned)rc;
-               if (buf->pos >= MAXBUFLEN)
-                       buf->pos -= MAXBUFLEN;
+               if (buf->pos >= MAX_BUFFER_LENGTH)
+                       buf->pos -= MAX_BUFFER_LENGTH;
        }
 
        return (int)rc;
 }
 
-/* get the 'fields' from 'buf' */
+/**
+ * get the 'fields' from 'buf'
+ */
 static
 void
 buf_get_fields(
@@ -209,7 +225,7 @@ buf_get_fields(
        unsigned read, write;
 
        /* advance the pos after the end */
-       assert(buf->content[buf->pos] == RS);
+       assert(buf->content[buf->pos] == RECORD_SEPARATOR);
        buf->pos++;
 
        /* init first field */
@@ -218,20 +234,20 @@ buf_get_fields(
        for (;;) {
                c = buf->content[read++];
                switch(c) {
-               case FS: /* field separator */
+               case FIELD_SEPARATOR: /* field separator */
                        buf->content[write++] = 0;
-                       if (fields->count >= MAXARGS)
+                       if (fields->count >= MAX_FIELDS)
                                return;
                        fields->fields[++fields->count] = &buf->content[write];
                        break;
-               case RS: /* end of line (record separator) */
+               case RECORD_SEPARATOR: /* end of line (record separator) */
                        buf->content[write] = 0;
                        fields->count += (write > 0);
                        return;
-               case ESC: /* escaping */
+               case ESCAPE: /* escaping */
                        c = buf->content[read++];
-                       if (c != FS && c != RS && c != ESC)
-                               buf->content[write++] = ESC;
+                       if (c != FIELD_SEPARATOR && c != RECORD_SEPARATOR && c != ESCAPE)
+                               buf->content[write++] = ESCAPE;
                        buf->content[write++] = c;
                        break;
                default: /* other characters */
@@ -254,10 +270,10 @@ buf_scan_end_record(
 
        /* search the next RS */
        while(buf->pos < buf->count) {
-               if (buf->content[buf->pos] == RS) {
+               if (buf->content[buf->pos] == RECORD_SEPARATOR) {
                        /* check whether RS is escaped */
                        nesc = 0;
-                       while (buf->pos > nesc && buf->content[buf->pos - (nesc + 1)] == ESC)
+                       while (buf->pos > nesc && buf->content[buf->pos - (nesc + 1)] == ESCAPE)
                                nesc++;
                        if ((nesc & 1) == 0)
                                return 1; /* not escaped */
@@ -267,7 +283,9 @@ buf_scan_end_record(
        return 0;
 }
 
-/** remove chars of 'buf' until pos */
+/**
+ * remove chars of 'buf' until pos
+ */
 static
 void
 buf_crop(
@@ -279,7 +297,9 @@ buf_crop(
        buf->pos = 0;
 }
 
-/** read input 'buf' from 'fd' */
+/**
+ * read input 'buf' from 'fd'
+ */
 static
 int
 inbuf_read(
@@ -289,11 +309,11 @@ inbuf_read(
        ssize_t szr;
        int rc;
 
-       if (buf->count == MAXBUFLEN)
+       if (buf->count == MAX_BUFFER_LENGTH)
                return -ENOBUFS;
 
        do {
-               szr = read(fd, buf->content + buf->count, MAXBUFLEN - buf->count);
+               szr = read(fd, buf->content + buf->count, MAX_BUFFER_LENGTH - buf->count);
        } while(szr < 0 && errno == EINTR);
        if (szr >= 0)
                buf->count += (unsigned)(rc = (int)szr);
@@ -303,10 +323,7 @@ inbuf_read(
        return rc;
 }
 
-/**
- * create the prot structure  in 'prot'
- * Return 0 in case of success or -ENOMEM in case of error
- */
+/* see prot.h */
 int
 prot_create(
        prot_t **prot
@@ -325,9 +342,7 @@ prot_create(
        return 0;
 }
 
-/**
- * Destroys the protocol 'prot'
- */
+/* see prot.h */
 void
 prot_destroy(
        prot_t *prot
@@ -335,9 +350,7 @@ prot_destroy(
        free(prot);
 }
 
-/**
- * reset the protocol 'prot'
- */
+/* see prot.h */
 void
 prot_reset(
        prot_t *prot
@@ -349,6 +362,7 @@ prot_reset(
        prot->fields.count = -1;
 }
 
+/* see prot.h */
 void
 prot_put_cancel(
        prot_t *prot
@@ -357,11 +371,12 @@ prot_put_cancel(
 
        if (prot->outfields) {
                count = prot->cancelidx - prot->outbuf.pos;
-               prot->outbuf.count = count > MAXBUFLEN ? count - MAXBUFLEN : count;
+               prot->outbuf.count = count > MAX_BUFFER_LENGTH ? count - MAX_BUFFER_LENGTH : count;
                prot->outfields = 0;
        }
 }
 
+/* see prot.h */
 int
 prot_put_end(
        prot_t *prot
@@ -371,12 +386,13 @@ prot_put_end(
        if (!prot->outfields)
                rc = 0;
        else {
-               rc = buf_put_car(&prot->outbuf, RS);
+               rc = buf_put_car(&prot->outbuf, RECORD_SEPARATOR);
                prot->outfields = 0;
        }
        return rc;
 }
 
+/* see prot.h */
 int
 prot_put_field(
        prot_t *prot,
@@ -385,7 +401,7 @@ prot_put_field(
        int rc;
 
        if (prot->outfields++)
-               rc = buf_put_car(&prot->outbuf, FS);
+               rc = buf_put_car(&prot->outbuf, FIELD_SEPARATOR);
        else {
                prot->cancelidx = prot->outbuf.pos + prot->outbuf.count;
                rc = 0;
@@ -396,6 +412,7 @@ prot_put_field(
        return rc;
 }
 
+/* see prot.h */
 int
 prot_put_fields(
        prot_t *prot,
@@ -413,24 +430,16 @@ prot_put_fields(
        return rc;
 }
 
-/**
- * Put protocol encoded 'count' 'fields' to the output buffer
- * returns:
- *  - 0 on success
- *  - -EINVAL if the count of fields is too big
- *  - -ECANCELED if there is not enough space in the buffer
- */
+/* see prot.h */
 int
 prot_put(
        prot_t *prot,
        unsigned count,
        const char **fields
 ) {
-       int rc = 0;
-       unsigned index = 0;
+       int rc;
 
-       while(!rc && index < count)
-               rc = prot_put_field(prot, fields[index++]);
+       rc = prot_put_fields(prot, count, fields);
        if (rc)
                prot_put_cancel(prot);
        else
@@ -445,6 +454,7 @@ prot_put(
  *  - -EINVAL if the count of fields is too big
  *  - -ECANCELED if there is not enought space in the buffer
  */
+/* see prot.h */
 int
 prot_putx(
        prot_t *prot,
@@ -467,10 +477,7 @@ prot_putx(
        return rc;
 }
 
-/**
- * Check whether write should be done or not
- * Returns 1 if there is something to write or 0 otherwise
- */
+/* see prot.h */
 int
 prot_should_write(
        prot_t *prot
@@ -478,13 +485,7 @@ prot_should_write(
        return prot->outbuf.count > 0;
 }
 
-/**
- * Write the content to write and return either the count
- * of bytes written or an error code (negative). Note that
- * the returned value tries to be the same as those returned
- * by "man 2 write". The only exception is -ENODATA that is
- * returned if there is nothing to be written.
- */
+/* see prot.h */
 int
 prot_write(
        prot_t *prot,
@@ -493,13 +494,15 @@ prot_write(
        return buf_write(&prot->outbuf, fdout);
 }
 
+/* see prot.h */
 int
 prot_can_read(
        prot_t *prot
 ) {
-       return prot->inbuf.count < MAXBUFLEN;
+       return prot->inbuf.count < MAX_BUFFER_LENGTH;
 }
 
+/* see prot.h */
 int
 prot_read(
        prot_t *prot,
@@ -508,6 +511,7 @@ prot_read(
        return inbuf_read(&prot->inbuf, fdin);
 }
 
+/* see prot.h */
 int
 prot_get(
        prot_t *prot,
@@ -523,6 +527,7 @@ prot_get(
        return (int)prot->fields.count;
 }
 
+/* see prot.h */
 void
 prot_next(
        prot_t *prot
index b961a37..a65c4b0 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF THE PROTOCOL                                             */
+/******************************************************************************/
+/******************************************************************************/
 
-struct prot;
 typedef struct prot prot_t;
 
-#define MAXBUFLEN 2000
-#define MAXARGS   20
-#define FS        ' '
-#define RS        '\n'
-#define ESC       '\\'
-
-
+/**
+ * Create the prot handler in 'prot'
+ *
+ * @param prot where to store the protocol handler
+ * @return 0 in case of success or -ENOMEM in case of error
+ */
 extern
 int
 prot_create(
        prot_t **prot
 );
 
+/**
+ * Destroys the protocol handler 'prot'
+ *
+ * @param prot the protocol handler
+ */
+/**
+ *
+ */
 extern
 void
 prot_destroy(
        prot_t *prot
 );
 
+/**
+ * Reset the protocol handler 'prot'
+ *
+ * @param prot the protocol handler
+ */
 extern
 void
 prot_reset(
        prot_t *prot
 );
 
+/**
+ * Cancel any previous put not terminated with prot_put_end
+ *
+ * @param prot the protocol handler
+ */
 extern
 void
 prot_put_cancel(
        prot_t *prot
 );
 
+/**
+ * Terminate a protocol record
+ *
+ * @param prot the protocol handler
+ * @return 0 on success
+ *         -ECANCELED if the send buffer is full
+ */
 extern
 int
 prot_put_end(
        prot_t *prot
 );
 
+/**
+ * Add a field to a protocol record
+ *
+ * @param prot the protocol handler
+ * @param field the field to add
+ * @return 0 on success
+ *         -ECANCELED if the send buffer is full
+ */
 extern
 int
 prot_put_field(
@@ -64,6 +99,15 @@ prot_put_field(
        const char *field
 );
 
+/**
+ * Add a set of fields to a protocol record
+ *
+ * @param prot the protocol handler
+ * @param count count of fields
+ * @param fields array of the fields to add
+ * @return 0 on success
+ *         -ECANCELED if the send buffer is full
+ */
 extern
 int
 prot_put_fields(
@@ -72,6 +116,15 @@ prot_put_fields(
        const char **fields
 );
 
+/**
+ * Add a set of fields to the record of protocol and terminate it
+ *
+ * @param prot the protocol handler
+ * @param count count of fields
+ * @param fields array of the fields to add
+ * @return 0 on success
+ *         -ECANCELED if the send buffer is full
+ */
 extern
 int
 prot_put(
@@ -80,6 +133,14 @@ prot_put(
        const char **fields
 );
 
+/**
+ * Add a variable length of items in protocol and terminate it
+ *
+ * @param prot the protocol handler
+ * @param ... a NULL terminated list of strings
+ * @return 0 on success
+ *         -ECANCELED if the send buffer is full
+ */
 extern
 int
 prot_putx(
@@ -87,12 +148,29 @@ prot_putx(
        ...
 );
 
+/**
+ * Check whether write should be done or not
+ *
+ * @param prot the protocol handler
+ * @return 1 if there is something to write or 0 otherwise
+ */
 extern
 int
 prot_should_write(
        prot_t *prot
 );
 
+/**
+ * Write the content to write and return either the count
+ * of bytes written or an error code (negative). Note that
+ * the returned value tries to be the same as those returned
+ * by "man 2 write". The only exception is -ENODATA that is
+ * returned if there is nothing to be written.
+ *
+ * @param prot the protocol handler
+ * @param fdout the file to write
+ * @return the count of bytes written or a negative -errno error code
+ */
 extern
 int
 prot_write(
@@ -100,12 +178,25 @@ prot_write(
        int fdout
 );
 
+/**
+ * Is there space to receive data
+ *
+ * @param prot the protocol handler
+ * @return 0 if there is no space or 1 if read can be called
+ */
 extern
 int
 prot_can_read(
        prot_t *prot
 );
 
+/**
+ * Read data from the input file fdin
+ *
+ * @param prot the protocol handler
+ * @param fdin the file to read
+ * @return the count of bytes read or a negative -errno error code
+ */
 extern
 int
 prot_read(
@@ -113,6 +204,13 @@ prot_read(
        int fdin
 );
 
+/**
+ * Get the currently received fields and its count
+ *
+ * @param prot the protocol handler
+ * @param fields where to store the array of received fields (can be NULL)
+ * @return the count of fields or -EAGAIN if no field is available
+ */
 extern
 int
 prot_get(
@@ -120,6 +218,12 @@ prot_get(
        const char ***fields
 );
 
+/**
+ * Forgive the current received fields so that the next call to prot_get
+ * returns the next received fields
+ *
+ * @param prot the protocol handler
+ */
 extern
 void
 prot_next(
index b02d7da..9d847da 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF QUEUE OF DATABASE MODIFIERS                              */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdint.h>
 #include <stdbool.h>
  */
 struct queue
 {
-       uint32_t read, write, capacity;
+       /** read index within queue */
+       uint32_t read;
+
+       /** write index within queue */
+       uint32_t write;
+
+       /** capacity of the queue */
+       uint32_t capacity;
+
+       /** the memory of the queue */
        void *queue;
 };
 typedef struct queue queue_t;
@@ -40,6 +54,13 @@ typedef struct queue queue_t;
 /** the queue */
 static queue_t queue;
 
+/**
+ * Read data from the queue
+ *
+ * @param data where to store the data
+ * @param length length of the data to read
+ * @return true on success or false on error
+ */
 static
 bool
 qread(
@@ -54,6 +75,12 @@ qread(
        return true;
 }
 
+/**
+ * Get a time from the queue
+ *
+ * @param value where to store the time
+ * @return true on success or false on error
+ */
 static
 bool
 qget_time(
@@ -62,6 +89,12 @@ qget_time(
        return qread(value, sizeof *value);
 }
 
+/**
+ * Get a string from the queue
+ *
+ * @param text where to store the string
+ * @return true on success or false on error
+ */
 static
 bool
 qget_string(
@@ -76,6 +109,13 @@ qget_string(
        return true;
 }
 
+/**
+ * Write the data to the queue
+ *
+ * @param data data to write
+ * @param length length of the data
+ * @return true on success or false on error
+ */
 static
 bool
 qwrite(
@@ -100,6 +140,12 @@ qwrite(
        return true;
 }
 
+/**
+ * Put the time in the queue
+ *
+ * @param value the value to put
+ * @return true on success or false on error
+ */
 static
 bool
 qput_time(
@@ -108,6 +154,13 @@ qput_time(
        return qwrite(&value, sizeof value);
 }
 
+/**
+ * Put the text in the queue
+ *
+ * @param text the text to put
+ *
+ * @return true on success or false on error
+ */
 static
 bool
 qput_string(
@@ -115,13 +168,16 @@ qput_string(
 ) {
        size_t len;
        text = text ?: "";
+
        /* check length */
        len = strnlen(text, MAX_NAME_LENGTH + 1);
        if (len > MAX_NAME_LENGTH)
                return false;
+
        return qwrite(text, 1 + (uint32_t)len);
 }
 
+/* see queue.h */
 int
 queue_drop(
        const data_key_t *key
@@ -130,10 +186,11 @@ queue_drop(
                && qput_string(key->session)
                && qput_string(key->user)
                && qput_string(key->permission)
-               && qput_string(0)
+               && qput_string(NULL)
                        ? 0 : -(errno = ENOMEM);
 }
 
+/* see queue.h */
 int
 queue_set(
        const data_key_t *key,
@@ -148,13 +205,14 @@ queue_set(
                        ? 0 : -(errno = ENOMEM);
 }
 
-
+/* see queue.h */
 void
 queue_clear(
 ) {
        queue.write = 0;
 }
 
+/* see queue.h */
 int
 queue_play(
 ) {
index 7efc1f8..99aa9e2 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF QUEUE OF DATABASE MODIFIERS                              */
+/******************************************************************************/
+/******************************************************************************/
 
-
+/**
+ * Queue droping the key
+ *
+ * @param key the key for dropping
+ * @return 0 on success or -ENOMEM on memory depletion
+ */
 extern
 int
 queue_drop(
        const data_key_t *key
 );
 
+/**
+ * Queue setting of the key with the value
+ *
+ * @param key the key to set
+ * @param value the value to set to the key
+ * @return 0 on success or -ENOMEM on memory depletion
+ */
 extern
 int
 queue_set(
@@ -29,14 +47,21 @@ queue_set(
        const data_value_t *value
 );
 
+/**
+ * Clear the content of the queue
+ */
 extern
 void
 queue_clear(
 );
 
+/**
+ * Play the content of the queue to alter the database accordingly to what
+ * is recorded
+ *
+ * @return 0 in case of success or a negative error code like -errno
+ */
 extern
 int
 queue_play(
 );
-
-
index 2d9ca9b..e865888 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF CLIENT PART OF RCYN-PROTOCOL                             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdbool.h>
 #include <stdint.h>
index f0fffe9..5128c85 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF CLIENT PART OF RCYN-PROTOCOL                             */
+/******************************************************************************/
+/******************************************************************************/
+
 
 typedef struct rcyn rcyn_t;
 typedef enum rcyn_type rcyn_type_t;
index d570b04..09db418 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF COMMON PROTOCOL VALUES, CONSTANTS, PROCESSES             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 
 const char
        _agent_[] = "agent",
        _check_[] = "check",
+       _clear_[] = "clear",
+       _commit_[] = "commit",
+       _done_[] = "done",
        _drop_[] = "drop",
        _enter_[] = "enter",
+       _error_[] = "error",
        _get_[] = "get",
+       _item_[] = "item",
        _leave_[] = "leave",
        _log_[] = "log",
-       _rcyn_[] = "rcyn",
-       _set_[] = "set",
-       _test_[] = "test";
-
-const char
-       _commit_[] = "commit",
-       _rollback_[] = "rollback";
-
-const char
-       _clear_[] = "clear",
-       _done_[] = "done",
-       _error_[] = "error",
-       _item_[] = "item",
        _no_[] = "no",
-       _on_[] = "on",
        _off_[] = "off",
+       _on_[] = "on",
+       _rcyn_[] = "rcyn",
+       _rollback_[] = "rollback",
+       _set_[] = "set",
+       _test_[] = "test",
        _yes_[] = "yes";
 
+
 #if !defined(RCYN_DEFAULT_SOCKET_SCHEME)
 #    define  RCYN_DEFAULT_SOCKET_SCHEME  "unix"
 #endif
@@ -86,6 +88,7 @@ const char
        rcyn_default_admin_socket_spec[] = RCYN_DEFAULT_ADMIN_SOCKET_SPEC,
        rcyn_default_agent_socket_spec[] = RCYN_DEFAULT_AGENT_SOCKET_SPEC;
 
+/* see rcyn-protocol.h */
 const char *
 rcyn_get_socket_check(
        const char *value
@@ -95,6 +98,7 @@ rcyn_get_socket_check(
                ?: rcyn_default_check_socket_spec;
 }
 
+/* see rcyn-protocol.h */
 const char *
 rcyn_get_socket_admin(
        const char *value
@@ -104,6 +108,7 @@ rcyn_get_socket_admin(
                ?: rcyn_default_admin_socket_spec;
 }
 
+/* see rcyn-protocol.h */
 const char *
 rcyn_get_socket_agent(
        const char *value
index 8640186..553a3df 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF COMMON PROTOCOL VALUES, CONSTANTS, PROCESSES             */
+/******************************************************************************/
+/******************************************************************************/
 
+/* predefined protocol strings */
 extern const char
        _agent_[],
        _check_[],
+       _clear_[],
+       _commit_[],
+       _done_[],
        _drop_[],
        _enter_[],
+       _error_[],
        _get_[],
+       _item_[],
        _leave_[],
        _log_[],
-       _rcyn_[],
-       _set_[],
-       _test_[];
-
-extern const char
-       _commit_[],
-       _rollback_[];
-
-extern const char
-       _clear_[],
-       _done_[],
-       _error_[],
-       _item_[],
        _no_[],
        _off_[],
        _on_[],
+       _rcyn_[],
+       _rollback_[],
+       _set_[],
+       _test_[],
        _yes_[];
 
+/* predefined names */
 extern const char
        rcyn_default_socket_scheme[],
        rcyn_default_socket_dir[],
@@ -53,18 +55,36 @@ extern const char
        rcyn_default_admin_socket_spec[],
        rcyn_default_agent_socket_spec[];
 
+/**
+ * Get the socket specification for check usage
+ *
+ * @param value some value or NULL for getting default
+ * @return the socket specification for check usage
+ */
 extern
 const char *
 rcyn_get_socket_check(
        const char *value
 );
 
+/**
+ * Get the socket specification for admin usage
+ *
+ * @param value some value or NULL for getting default
+ * @return the socket specification for admin usage
+ */
 extern
 const char *
 rcyn_get_socket_admin(
        const char *value
 );
 
+/**
+ * Get the socket specification for agent usage
+ *
+ * @param value some value or NULL for getting default
+ * @return the socket specification for agent usage
+ */
 extern
 const char *
 rcyn_get_socket_agent(
index c6a0ef9..378a07d 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF SERVER PART OF RCYN-PROTOCOL                             */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdbool.h>
 #include <stdint.h>
@@ -39,6 +44,8 @@
 #include "socket.h"
 #include "pollitem.h"
 
+#define MAX_PUTX_ITEMS 15
+
 /** should log? */
 bool
 rcyn_server_log = 0;
@@ -177,7 +184,7 @@ putx(
        client_t *cli,
        ...
 ) {
-       const char *p, *fields[MAXARGS];
+       const char *p, *fields[MAX_PUTX_ITEMS];
        unsigned n;
        va_list l;
        int rc;
@@ -187,7 +194,7 @@ putx(
        va_start(l, cli);
        p = va_arg(l, const char *);
        while (p) {
-               if (n == MAXARGS)
+               if (n == MAX_PUTX_ITEMS)
                        return -EINVAL;
                fields[n++] = p;
                p = va_arg(l, const char *);
@@ -421,7 +428,7 @@ onrequest(
                        key.session = args[2];
                        key.user = args[3];
                        key.permission = args[4];
-                       cyn_list(cli, getcb, &key);
+                       cyn_list(getcb, cli, &key);
                        send_done(cli);
                        return;
                }
index 34cd46a..7982867 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF SERVER PART OF RCYN-PROTOCOL                             */
+/******************************************************************************/
+/******************************************************************************/
 
 struct rcyn_server;
 typedef struct rcyn_server rcyn_server_t;
index fc01b8f..bd6b804 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF SOCKET OPENING FOLLOWING SPECIFICATION                   */
+/******************************************************************************/
+/******************************************************************************/
 
 #include <stdlib.h>
 #include <string.h>
@@ -33,7 +38,7 @@
 
 #include "socket.h"
 
-#define BACKLOG  30
+#define BACKLOG  8
 
 /******************************************************************************/
 
index b5989e1..c0f9ddb 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #pragma once
+/******************************************************************************/
+/******************************************************************************/
+/* IMPLEMENTATION OF SOCKET OPENING FOLLOWING SPECIFICATION                   */
+/******************************************************************************/
+/******************************************************************************/
 
 extern int socket_open(const char *uri, int server);