Added alter tag...
authorJeroen van der Heijden <jeroen@transceptor.technology>
Fri, 25 Sep 2020 11:03:13 +0000 (13:03 +0200)
committerJeroen van der Heijden <jeroen@transceptor.technology>
Fri, 25 Sep 2020 11:03:13 +0000 (13:03 +0200)
18 files changed:
grammar/grammar.py
include/siri/db/group.h
include/siri/db/groups.h
include/siri/db/queries.h
include/siri/db/tag.h
include/siri/grammar/grammar.h
include/siri/version.h
itest/test_list.py
itest/test_parentheses.py
itest/test_tags.py
src/siri/db/db.c
src/siri/db/group.c
src/siri/db/groups.c
src/siri/db/listener.c
src/siri/db/queries.c
src/siri/db/tag.c
src/siri/db/tags.c
src/siri/grammar/grammar.c

index d03c8da5c6091a042c6a878821cce62ebe4b4f28..2b689c23ef6bc04362369df45f0541fff1d0f9cc 100644 (file)
@@ -649,6 +649,10 @@ class SiriGrammar(Grammar):
         set_name,
         most_greedy=False))
 
+    alter_tag = Sequence(k_tag, tag_name, Choice(
+        set_name,
+        most_greedy=False))
+
     alter_server = Sequence(k_server, uuid, Choice(
         set_log_level,
         set_backup_mode,
@@ -751,6 +755,7 @@ class SiriGrammar(Grammar):
         alter_series,
         alter_user,
         alter_group,
+        alter_tag,
         alter_server,
         alter_servers,
         alter_database,
index 6a902ec4d7cbbd4307cdb40f8126f2ffd36124c7..d1d38606186cd606ed9511e1cc27f931c319bc9f 100644 (file)
@@ -16,6 +16,7 @@ typedef struct siridb_group_s siridb_group_t;
 
 #include <vec/vec.h>
 #include <siri/db/series.h>
+#include <siri/db/db.h>
 #include <pcre2.h>
 
 siridb_group_t * siridb_group_new(
@@ -23,7 +24,7 @@ siridb_group_t * siridb_group_new(
         size_t source_len,
         char * err_msg);
 int siridb_group_set_name(
-        siridb_groups_t * groups,
+        siridb_t * siridb,
         siridb_group_t * group,
         const char * name,
         char * err_msg);
index 5e5a90d78dd4a93baa9d4128875c27407c59de65..900cdd3b8a3ce3f370ee64229a92d9e99789f3d2 100644 (file)
@@ -43,7 +43,7 @@ enum
 #include <siri/db/db.h>
 #include <siri/net/pkg.h>
 
-siridb_groups_t * siridb_groups_new(siridb_t * siridb);
+int siridb_groups_init(siridb_t * siridb);
 void siridb_groups_start(siridb_t * siridb);
 int siridb_groups_save(siridb_groups_t * groups);
 ssize_t siridb_groups_get_file(char ** buffer, siridb_t * siridb);
@@ -57,7 +57,7 @@ void siridb_groups_destroy(siridb_groups_t * groups);
 void siridb_groups_incref(siridb_groups_t * groups);
 void siridb_groups_decref(siridb_groups_t * groups);
 int siridb_groups_add_group(
-        siridb_groups_t * groups,
+        siridb_t * siridb,
         const char * name,
         const char * source,
         size_t source_len,
index d6f8d0824e83d260000b10b30d2a98a171322d54..8e57111dcbf31c142089e70dc1acdb346e65108d 100644 (file)
 #include <cexpr/cexpr.h>
 #include <cleri/cleri.h>
 #include <ctree/ctree.h>
-#include <siri/db/presuf.h>
 #include <siri/db/group.h>
+#include <siri/db/presuf.h>
 #include <siri/db/series.h>
+#include <siri/db/tag.h>
 #include <siri/db/user.h>
 #include <pcre2.h>
 
@@ -34,6 +35,7 @@ typedef enum
     QUERY_ALTER_NONE,
     QUERY_ALTER_DATABASE,
     QUERY_ALTER_GROUP,
+    QUERY_ALTER_TAG,
     QUERY_ALTER_SERVER,
     QUERY_ALTER_SERVERS,
     QUERY_ALTER_USER,
@@ -88,6 +90,7 @@ struct query_wrapper_s
 union query_alter_u
 {
     siridb_group_t * group;
+    siridb_tag_t * tag;
     siridb_server_t * server;
     siridb_user_t * user;
     void * dummy;
index 960cc5712f8efb4ac54ed058b9c374f79fd08a49..a5f340d2479140f24ab2e41aa104943b07fef013 100644 (file)
@@ -26,7 +26,12 @@ char * siridb_tag_fn(siridb_tag_t * tag);
 int siridb_tag_is_remote_prop(uint32_t prop);
 void siridb_tag_prop(siridb_tag_t * tag, qp_packer_t * packer, int prop);
 int siridb_tag_cexpr_cb(siridb_tag_t * tag, cexpr_condition_t * cond);
-
+int siridb_tag_check_name(const char * name, char * err_msg);
+int siridb_tag_set_name(
+        siridb_t * siridb,
+        siridb_tag_t * tag,
+        const char * name,
+        char * err_msg);
 
 #define siridb_tag_incref(tag__) (tag__)->ref++
 #define siridb_tag_decref(tag__) \
index d52177cc975b76468d766b3a4fc4c37afb25d221..6a696e81e5561a727c9be41efec7b6e8903cd327 100644 (file)
@@ -5,7 +5,7 @@
  * should be used with the libcleri module.
  *
  * Source class: SiriGrammar
- * Created at: 2020-09-17 11:38:57
+ * Created at: 2020-09-25 10:57:26
  */
 #ifndef CLERI_EXPORT_SIRI_GRAMMAR_GRAMMAR_H_
 #define CLERI_EXPORT_SIRI_GRAMMAR_GRAMMAR_H_
@@ -26,6 +26,7 @@ enum cleri_grammar_ids {
     CLERI_GID_ALTER_SERVER,
     CLERI_GID_ALTER_SERVERS,
     CLERI_GID_ALTER_STMT,
+    CLERI_GID_ALTER_TAG,
     CLERI_GID_ALTER_USER,
     CLERI_GID_BEFORE_EXPR,
     CLERI_GID_BETWEEN_EXPR,
index 6d48a38071b8e77e8294f02fdba0c502b4e6204c..37ccd5739bea92923e8f7abc53467484117bea1b 100644 (file)
@@ -15,7 +15,7 @@
  * Note that debian alpha packages should use versions like this:
  *   2.0.34-0alpha0
  */
-#define SIRIDB_VERSION_PRE_RELEASE "-alpha-2"
+#define SIRIDB_VERSION_PRE_RELEASE "-alpha-3"
 
 #ifndef NDEBUG
 #define SIRIDB_VERSION_BUILD_RELEASE "+debug"
index 023c02a124f11f9a70283ee95836606d87db8afc..66b0e0ffd15d3a4cb792338e3a6b507f12bcc43a 100644 (file)
@@ -98,7 +98,7 @@ class TestList(TestBase):
         await self.client0.query('alter database set list_limit 5000')
         with self.assertRaisesRegex(
                 QueryError,
-                'Limit must be a value between 0 and 5000 '
+                'Limit must be a value between 1 and 5000 '
                 'but received: 6000.*'):
             await self.client0.query(
                 'list series limit 6000')
index 22035f10ec1ff4e611e2bec755b02ad8af00726d..3d66657fbb229825b6a7a0913721e735a20264d8 100644 (file)
@@ -288,7 +288,7 @@ class TestParenth(TestBase):
         await self.client0.query('alter database set list_limit 5000')
         with self.assertRaisesRegex(
                 QueryError,
-                'Limit must be a value between 0 and 5000 '
+                'Limit must be a value between 1 and 5000 '
                 'but received: 6000.*'):
             await self.client0.query(
                 'list series limit 6000')
index 47980c75949c798c7b0c0da903c05bab0cc40fa0..43e113600fd21df9eb1cb04ed560124e2bf62882 100644 (file)
@@ -244,10 +244,10 @@ class TestTags(TestBase):
                 drop tag `{0}`
             '''.format(tag))
 
-        await asyncio.sleep(3.0)
+        await asyncio.sleep(1.5)
 
         for client in (self.client0, self.client1, self.client2):
-            res = await self.client0.query('''
+            res = await client.query('''
                 list tags name, series
             ''')
             tags = sorted(res['tags'])
@@ -256,6 +256,22 @@ class TestTags(TestBase):
                 ["I", 4],
             ])
 
+        await self.client0.query('''
+            alter tag `F` set name 'Float'
+        ''')
+
+        await asyncio.sleep(1.5)
+
+        for client in (self.client0, self.client1, self.client2):
+            res = await client.query('''
+                list tags name, series
+            ''')
+            tags = sorted(res['tags'])
+            self.assertEqual(tags, [
+                ["Float", 5],
+                ["I", 4],
+            ])
+
         self.client2.close()
         self.client1.close()
         self.client0.close()
index b43f764724a80b925f18e303989524d0b5e3446d..72749f1be0b35cb87ca19a6bb662f337f4a2f234 100644 (file)
@@ -210,7 +210,7 @@ siridb_t * siridb_new(const char * dbpath, int lock_flags)
     }
 
     /* load groups */
-    if ((siridb->groups = siridb_groups_new(siridb)) == NULL)
+    if (siridb_groups_init(siridb))
     {
         log_error("Cannot read groups for database '%s'", siridb->dbname);
         siridb_decref(siridb);
@@ -901,7 +901,8 @@ static siridb_t * siridb__new(void)
     siridb->replicate = NULL;
     siridb->reindex = NULL;
     siridb->groups = NULL;
-    siridb->dropped_fp = NULL;
+    siridb->groups = NULL;
+    siridb->tags = NULL;
     siridb->store = NULL;
     siridb->exp_at_log = 0;
     siridb->exp_at_num = 0;
index ae277bb424f8015a8f999e6f1b38c5d528ab9724..45b370d65c379a82f259944dcc201011e61eef60 100644 (file)
@@ -73,7 +73,7 @@ siridb_group_t * siridb_group_new(
  * (err_msg is set in case of all errors)
  */
 int siridb_group_set_name(
-        siridb_groups_t * groups,
+        siridb_t * siridb,
         siridb_group_t * group,
         const char * name,
         char * err_msg)
@@ -92,7 +92,7 @@ int siridb_group_set_name(
         return 1;
     }
 
-    if (ct_get(groups->groups, name) != NULL)
+    if (ct_get(siridb->groups->groups, name) != NULL)
     {
         snprintf(err_msg,
                 SIRIDB_MAX_SIZE_ERR_MSG,
@@ -101,17 +101,26 @@ int siridb_group_set_name(
         return 1;
     }
 
+    if (siridb->tags && ct_get(siridb->tags->tags, name) != NULL)
+    {
+        snprintf(err_msg,
+                SIRIDB_MAX_SIZE_ERR_MSG,
+                "Tag '%s' already exists.",
+                name);
+        return 1;
+    }
+
     if (group->name != NULL)
     {
         int rc;
 
         /* group already exists */
-        uv_mutex_lock(&groups->mutex);
+        uv_mutex_lock(&siridb->groups->mutex);
 
-        rc  = ( ct_pop(groups->groups, group->name) == NULL ||
-                ct_add(groups->groups, name, group));
+        rc  = ( ct_pop(siridb->groups->groups, group->name) == NULL ||
+                ct_add(siridb->groups->groups, name, group));
 
-        uv_mutex_unlock(&groups->mutex);
+        uv_mutex_unlock(&siridb->groups->mutex);
 
         if (rc)
         {
index 274667c550cff49a92d11e481f98db2d1ce2d60d..7a270b9323ce488ed74de6e24ba973da9be8cd26 100644 (file)
@@ -45,7 +45,7 @@
 #define GROUPS_RE_BATCH_SZ 1000
 #define CALC_BATCH_SIZE(sz) GROUPS_RE_BATCH_SZ /((sz / 5 ) + 1) + 1;
 
-static int GROUPS_load(siridb_groups_t * groups);
+static int GROUPS_load(siridb_t * siridb);
 static void GROUPS_free(siridb_groups_t * groups);
 static int GROUPS_pkg(siridb_group_t * group, qp_packer_t * packer);
 static int GROUPS_nseries(siridb_group_t * group, void * data);
@@ -58,49 +58,50 @@ static void GROUPS_cleanup(siridb_groups_t * groups);
 /*
  * In case of an error the return value is NULL and a SIGNAL is raised.
  */
-siridb_groups_t * siridb_groups_new(siridb_t * siridb)
+int siridb_groups_init(siridb_t * siridb)
 {
     log_info("Loading groups");
 
-    siridb_groups_t * groups = malloc(sizeof(siridb_groups_t));
-    if (groups == NULL)
+    siridb->groups = malloc(sizeof(siridb_groups_t));
+    if (siridb->groups == NULL)
     {
         ERR_ALLOC
+        return -1;
     }
-    else
+
+    siridb->groups->ref = 1;
+    siridb->groups->fn = NULL;
+    siridb->groups->groups = ct_new();
+    siridb->groups->nseries = vec_new(VEC_DEFAULT_SIZE);
+    siridb->groups->ngroups = vec_new(VEC_DEFAULT_SIZE);
+
+    uv_mutex_init(&siridb->groups->mutex);
+
+    if (    !siridb->groups->groups ||
+            !siridb->groups->nseries ||
+            !siridb->groups->ngroups)
     {
-        groups->ref = 1;
-        groups->fn = NULL;
-        groups->groups = ct_new();
-        groups->nseries = vec_new(VEC_DEFAULT_SIZE);
-        groups->ngroups = vec_new(VEC_DEFAULT_SIZE);
-        uv_mutex_init(&groups->mutex);
-
-        if (!groups->groups || !groups->nseries || !groups->ngroups)
-        {
-            ERR_ALLOC
-            GROUPS_free(groups);
-            groups = NULL;
-        }
-        else if (asprintf(
-                    &groups->fn,
-                    "%s%s",
-                    siridb->dbpath,
-                    SIRIDB_GROUPS_FN) < 0 || GROUPS_load(groups))
-        {
-            ERR_ALLOC
-            GROUPS_free(groups);
-            groups = NULL;
-        }
-        else
-        {
-            groups->status = GROUPS_RUNNING;
-            groups->flags = 0;
+        ERR_ALLOC
+        GROUPS_free(siridb->groups);
+        siridb->groups = NULL;
+        return -1;
+    }
 
-        }
+    if (asprintf(
+                &siridb->groups->fn,
+                "%s%s",
+                siridb->dbpath,
+                SIRIDB_GROUPS_FN) < 0 || GROUPS_load(siridb))
+    {
+        ERR_ALLOC
+        GROUPS_free(siridb->groups);
+        siridb->groups = NULL;
+        return -1;
     }
 
-    return groups;
+    siridb->groups->status = GROUPS_RUNNING;
+    siridb->groups->flags = 0;
+    return 0;
 }
 
 /*
@@ -143,7 +144,7 @@ int siridb_groups_add_series(
  * (a signal might be raised)
  */
 int siridb_groups_add_group(
-        siridb_groups_t * groups,
+        siridb_t * siridb,
         const char * name,
         const char * source,
         size_t source_len,
@@ -161,15 +162,15 @@ int siridb_groups_add_group(
         return -1; /* err_msg is set and a SIGNAL is possibly raised */
     }
 
-    if (siridb_group_set_name(groups, group, name, err_msg))
+    if (siridb_group_set_name(siridb, group, name, err_msg))
     {
         siridb_group_decref(group);
         return -1;  /* err_msg is set and a SIGNAL is possibly raised */
     }
 
-    uv_mutex_lock(&groups->mutex);
+    uv_mutex_lock(&siridb->groups->mutex);
 
-    rc = ct_add(groups->groups, name, group);
+    rc = ct_add(siridb->groups->groups, name, group);
 
     switch (rc)
     {
@@ -187,7 +188,7 @@ int siridb_groups_add_group(
         break;
 
     case CT_OK:
-        if (vec_append_safe(&groups->ngroups, group))
+        if (vec_append_safe(&siridb->groups->ngroups, group))
         {
             siridb_group_decref(group);
             sprintf(err_msg, "Memory allocation error.");
@@ -204,7 +205,7 @@ int siridb_groups_add_group(
         break;
     }
 
-    uv_mutex_unlock(&groups->mutex);
+    uv_mutex_unlock(&siridb->groups->mutex);
 
     return rc;
 }
@@ -484,19 +485,19 @@ static void GROUPS_loop(void * arg)
     siridb_groups_decref(siridb->groups);
 }
 
-static int GROUPS_load(siridb_groups_t * groups)
+static int GROUPS_load(siridb_t * siridb)
 {
     int rc = 0;
 
-    if (!xpath_file_exist(groups->fn))
+    if (!xpath_file_exist(siridb->groups->fn))
     {
         /* no groups file, create a new one */
-        return siridb_groups_save(groups);
+        return siridb_groups_save(siridb->groups);
     }
 
     qp_unpacker_t * unpacker = siridb_misc_open_schema_file(
             SIRIDB_GROUPS_SCHEMA,
-            groups->fn);
+            siridb->groups->fn);
 
     if (unpacker == NULL)
     {
@@ -514,7 +515,7 @@ static int GROUPS_load(siridb_groups_t * groups)
                 qp_next(unpacker, &qp_source) == QP_RAW)
         {
             rc = siridb_groups_add_group(
-                    groups,
+                    siridb,
                     (const char *) qp_name.via.raw,
                     (const char *) qp_source.via.raw,
                     qp_source.len,
index 2223e22f04be576d1af3798a9afc17b21f8eb61e..2a03fd5d3e31663ccee5d28794339371e503f518 100644 (file)
@@ -161,6 +161,8 @@ if (IS_MASTER && siridb_is_reindexing(siridb))                              \
     "Successfully dropped group '%s'."
 #define MSG_SUCCESS_ALTER_GROUP \
     "Successfully updated group '%s'."
+#define MSG_SUCCESS_ALTER_TAG \
+    "Successfully updated tag '%s'."
 #define MSG_SUCCESS_SET_DROP_THRESHOLD \
     "Successfully changed drop_threshold from %g to %g."
 #define MSG_SUCCESS_SET_LIST_LIMIT \
@@ -206,6 +208,7 @@ static void enter_alter_series(uv_async_t * handle);
 static void enter_alter_server(uv_async_t * handle);
 static void enter_alter_servers(uv_async_t * handle);
 static void enter_alter_stmt(uv_async_t * handle);
+static void enter_alter_tag(uv_async_t * handle);
 static void enter_alter_user(uv_async_t * handle);
 static void enter_count_stmt(uv_async_t * handle);
 static void enter_create_stmt(uv_async_t * handle);
@@ -237,6 +240,7 @@ static void enter_xxx_columns(uv_async_t * handle);
 
 static void exit_after_expr(uv_async_t * handle);
 static void exit_alter_group(uv_async_t * handle);
+static void exit_alter_tag(uv_async_t * handle);
 static void exit_alter_user(uv_async_t * handle);
 static void exit_before_expr(uv_async_t * handle);
 static void exit_between_expr(uv_async_t * handle);
@@ -448,6 +452,7 @@ void siridb_init_listener(void)
     SIRIDB_NODE_ENTER[CLERI_GID_ALTER_SERVER] = enter_alter_server;
     SIRIDB_NODE_ENTER[CLERI_GID_ALTER_SERVERS] = enter_alter_servers;
     SIRIDB_NODE_ENTER[CLERI_GID_ALTER_STMT] = enter_alter_stmt;
+    SIRIDB_NODE_ENTER[CLERI_GID_ALTER_TAG] = enter_alter_tag;
     SIRIDB_NODE_ENTER[CLERI_GID_ALTER_USER] = enter_alter_user;
     SIRIDB_NODE_ENTER[CLERI_GID_COUNT_STMT] = enter_count_stmt;
     SIRIDB_NODE_ENTER[CLERI_GID_CREATE_STMT] = enter_create_stmt;
@@ -492,6 +497,7 @@ void siridb_init_listener(void)
 
     SIRIDB_NODE_EXIT[CLERI_GID_AFTER_EXPR] = exit_after_expr;
     SIRIDB_NODE_EXIT[CLERI_GID_ALTER_GROUP] = exit_alter_group;
+    SIRIDB_NODE_EXIT[CLERI_GID_ALTER_TAG] = exit_alter_tag;
     SIRIDB_NODE_EXIT[CLERI_GID_ALTER_USER] = exit_alter_user;
     SIRIDB_NODE_EXIT[CLERI_GID_BEFORE_EXPR] = exit_before_expr;
     SIRIDB_NODE_EXIT[CLERI_GID_BETWEEN_EXPR] = exit_between_expr;
@@ -597,6 +603,38 @@ static void enter_alter_group(uv_async_t * handle)
     }
 }
 
+static void enter_alter_tag(uv_async_t * handle)
+{
+    siridb_query_t * query = handle->data;
+    siridb_t * siridb = query->client->siridb;
+    query_alter_t * q_alter = (query_alter_t *) query->data;
+
+    MASTER_CHECK_ACCESSIBLE(siridb)
+
+    cleri_node_t * tag_node = query->nodes->node->children->next->node;
+    siridb_tag_t * tag;
+
+    char name[tag_node->len - 1];
+    xstr_extract_string(name, tag_node->str, tag_node->len);
+
+    if ((tag = ct_get(siridb->tags->tags, name)) == NULL)
+    {
+        snprintf(query->err_msg,
+                SIRIDB_MAX_SIZE_ERR_MSG,
+                "Cannot find tag: '%s'",
+                name);
+        siridb_query_send_error(handle, CPROTO_ERR_QUERY);
+    }
+    else
+    {
+        q_alter->alter_tp = QUERY_ALTER_TAG;
+        q_alter->via.tag = tag;
+        siridb_tag_incref(tag);
+
+        SIRIPARSER_NEXT_NODE
+    }
+}
+
 static void enter_alter_series(uv_async_t * handle)
 {
     siridb_query_t * query = handle->data;
@@ -970,7 +1008,7 @@ static void enter_limit_expr(uv_async_t * handle)
     if (limit <= 0 || limit > siridb->list_limit)
     {
         snprintf(query->err_msg, SIRIDB_MAX_SIZE_ERR_MSG,
-                "Limit must be a value between 0 and %" PRIu32
+                "Limit must be a value between 1 and %" PRIu32
                 " but received: %" PRId64
                 " (optionally the limit can be changed, "
                 "see 'help alter database')",
@@ -1212,7 +1250,7 @@ static void enter_set_name(uv_async_t * handle)
         break;
     case QUERY_ALTER_GROUP:
         if (siridb_group_set_name(
-                    siridb->groups,
+                    siridb,
                     q_alter->via.group,
                     name,
                     query->err_msg))
@@ -1221,6 +1259,17 @@ static void enter_set_name(uv_async_t * handle)
             return;
         }
         break;
+    case QUERY_ALTER_TAG:
+        if (siridb_tag_set_name(
+                    siridb,
+                    q_alter->via.tag,
+                    name,
+                    query->err_msg))
+        {
+            siridb_query_send_error(handle, CPROTO_ERR_QUERY);
+            return;
+        }
+        break;
     case QUERY_ALTER_NONE:
     case QUERY_ALTER_DATABASE:
     case QUERY_ALTER_SERVER:
@@ -1670,6 +1719,12 @@ static void enter_tag_series(uv_async_t * handle)
             return;
         }
 
+        if (siridb_tag_check_name(name, query->err_msg) != 0)
+        {
+            siridb_query_send_error(handle, CPROTO_ERR_QUERY);
+            return;
+        }
+
         uv_mutex_lock(&siridb->tags->mutex);
 
         tag = siridb_tags_add(siridb->tags, name);
@@ -1929,6 +1984,33 @@ static void exit_alter_group(uv_async_t * handle)
     }
 }
 
+static void exit_alter_tag(uv_async_t * handle)
+{
+    siridb_query_t * query = handle->data;
+    siridb_t * siridb = query->client->siridb;
+    siridb_tag_t * tag = ((query_alter_t *) query->data)->via.tag;
+
+    siridb_tags_set_require_save(siridb->tags, tag);
+
+    QP_ADD_SUCCESS
+
+    log_info(MSG_SUCCESS_ALTER_TAG, tag->name);
+    qp_add_fmt_safe(query->packer, MSG_SUCCESS_ALTER_TAG, tag->name);
+
+    if (IS_MASTER)
+    {
+        siridb_query_forward(
+                handle,
+                SIRIDB_QUERY_FWD_UPDATE,
+                (sirinet_promises_cb) on_update_xxx_response,
+                0);
+    }
+    else
+    {
+        SIRIPARSER_ASYNC_NEXT_NODE
+    }
+}
+
 static void exit_alter_user(uv_async_t * handle)
 {
     siridb_query_t * query = handle->data;
@@ -2587,7 +2669,7 @@ static void exit_create_group(uv_async_t * handle)
     xstr_extract_string(group_name, name_nd->str, name_nd->len);
 
     if (siridb_groups_add_group(
-            siridb->groups,
+            siridb,
             group_name,
             for_nd->str,
             for_nd->len,
index 5f8341f84492fe8b91c5d40216e0058623c62593..1b3d4855298ef06bfd3759db3cecf3f88f8cb4f4 100644 (file)
@@ -184,6 +184,9 @@ void query_alter_free(uv_handle_t * handle)
     case QUERY_ALTER_GROUP:
         siridb_group_decref(q_alter->via.group);
         break;
+    case QUERY_ALTER_TAG:
+        siridb_tag_decref(q_alter->via.tag);
+        break;
     case QUERY_ALTER_SERVER:
         siridb_server_decref(q_alter->via.server);
         break;
index bc9dfd6ac18732a46081f8cd8769640c1a8f0f3a..486b88114f82054475d4237230a41cd85ca90f7b 100644 (file)
@@ -21,6 +21,8 @@
 #include <siri/grammar/grammar.h>
 
 #define TAGFN_NUMBERS 9
+#define SIRIDB_MIN_TAG_LEN 1
+#define SIRIDB_MAX_TAG_LEN 255
 
 /*
  * Returns tag when successful or NULL in case of an error.
@@ -50,6 +52,25 @@ char * siridb_tag_fn(siridb_tag_t * tag)
     return fn;
 }
 
+int siridb_tag_check_name(const char * name, char * err_msg)
+{
+    if (strlen(name) < SIRIDB_MIN_TAG_LEN)
+    {
+        sprintf(err_msg, "Tag name should be at least %d characters.",
+                SIRIDB_MIN_TAG_LEN);
+        return 1;
+    }
+
+    if (strlen(name) > SIRIDB_MAX_TAG_LEN)
+    {
+        sprintf(err_msg, "Tag name should be at most %d characters.",
+                SIRIDB_MAX_TAG_LEN);
+        return 1;
+    }
+
+    return 0;
+}
+
 /*
  * Returns tag when successful or NULL in case of an error.
  */
@@ -221,6 +242,73 @@ int siridb_tag_cexpr_cb(siridb_tag_t * tag, cexpr_condition_t * cond)
     return -1;
 }
 
+int siridb_tag_set_name(
+        siridb_t * siridb,
+        siridb_tag_t * tag,
+        const char * name,
+        char * err_msg)
+{
+    if (siridb_tag_check_name(name, err_msg) != 0)
+    {
+        return 1;
+    }
+
+    if (ct_get(siridb->tags->tags, name) != NULL)
+    {
+        snprintf(err_msg,
+                SIRIDB_MAX_SIZE_ERR_MSG,
+                "Tag '%s' already exists.",
+                name);
+        return 1;
+    }
+
+    if (siridb->groups && ct_get(siridb->groups->groups, name) != NULL)
+    {
+        snprintf(err_msg,
+                SIRIDB_MAX_SIZE_ERR_MSG,
+                "Group '%s' already exists.",
+                name);
+        return 1;
+    }
+
+    if (tag->name != NULL)
+    {
+        int rc;
+
+        /* group already exists */
+        uv_mutex_lock(&siridb->tags->mutex);
+
+        rc  = ( ct_pop(siridb->tags->tags, tag->name) == NULL ||
+                ct_add(siridb->tags->tags, name, tag));
+
+        uv_mutex_unlock(&siridb->tags->mutex);
+
+        if (rc)
+        {
+            ERR_C
+            snprintf(err_msg,
+                    SIRIDB_MAX_SIZE_ERR_MSG,
+                    "Critical error while replacing tag name '%s' with '%s' "
+                    "in tree.",
+                    tag->name,
+                    name);
+            return -1;
+        }
+    }
+
+    free(tag->name);
+    tag->name = strdup(name);
+
+    if (tag->name == NULL)
+    {
+        ERR_ALLOC
+        sprintf(err_msg, "Memory allocation error.");
+        return -1;
+    }
+
+    return 0;
+}
+
 /*
  * Can be used as a callback, in other cases go for the macro.
  */
index 492629f22dabc95bbc743f2b94bea8fdb686a1b3..995abbce3a852ee8aae59509f0b8e600086c9956 100644 (file)
@@ -165,20 +165,23 @@ static int TAGS__save_cb(
         siridb_tag_t * tag,
         void * data __attribute__((unused)))
 {
-    siridb_tag_save(tag);
-    tag->flags &= ~ TAG_FLAG_REQUIRE_SAVE;
-
-    usleep(10000);  // 10ms
-    return 0;
+    if (siridb_tag_save(tag) == 0)
+    {
+        tag->flags &= ~ TAG_FLAG_REQUIRE_SAVE;
+        usleep(10000);  // 10ms
+        return 0;
+    }
+    return 1;
 }
 
 void siridb_tags_save(siridb_tags_t * tags)
 {
     uv_mutex_lock(&tags->mutex);
 
-    ct_values(tags->tags, (ct_val_cb) TAGS__save_cb, NULL);
-
-    tags->flags &= ~TAGS_FLAG_REQUIRE_SAVE;
+    if (ct_values(tags->tags, (ct_val_cb) TAGS__save_cb, NULL) == 0)
+    {
+        tags->flags &= ~TAGS_FLAG_REQUIRE_SAVE;
+    }
 
     uv_mutex_unlock(&tags->mutex);
 }
@@ -428,12 +431,18 @@ static int TAGS_load(siridb_t * siridb)
 
 static void TAGS_free(siridb_tags_t * tags)
 {
+    if (tags->flags & TAGS_FLAG_REQUIRE_SAVE)
+    {
+        siridb_tags_save(tags);
+    }
+
     uv_mutex_lock(&tags->mutex);
 
     if (tags->tags != NULL)
     {
         ct_free(tags->tags, (ct_free_cb) siridb__tag_decref);
     }
+
     uv_mutex_unlock(&tags->mutex);
     uv_mutex_destroy(&tags->mutex);
 
index 90d57f09a106c03633329bdb6a871c791ec7b406..c533570e4772e4a29e931320845848d91ee5f0b2 100644 (file)
@@ -5,7 +5,7 @@
  * should be used with the libcleri module.
  *
  * Source class: SiriGrammar
- * Created at: 2020-09-17 11:38:57
+ * Created at: 2020-09-25 10:57:26
  */
 
 #include "siri/grammar/grammar.h"
@@ -1300,6 +1300,18 @@ cleri_grammar_t * compile_siri_grammar_grammar(void)
             set_name
         )
     );
+    cleri_t * alter_tag = cleri_sequence(
+        CLERI_GID_ALTER_TAG,
+        3,
+        k_tag,
+        tag_name,
+        cleri_choice(
+            CLERI_NONE,
+            CLERI_FIRST_MATCH,
+            1,
+            set_name
+        )
+    );
     cleri_t * alter_server = cleri_sequence(
         CLERI_GID_ALTER_SERVER,
         3,
@@ -1552,10 +1564,11 @@ cleri_grammar_t * compile_siri_grammar_grammar(void)
         cleri_choice(
             CLERI_NONE,
             CLERI_FIRST_MATCH,
-            6,
+            7,
             alter_series,
             alter_user,
             alter_group,
+            alter_tag,
             alter_server,
             alter_servers,
             alter_database