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,
alter_series,
alter_user,
alter_group,
+ alter_tag,
alter_server,
alter_servers,
alter_database,
#include <vec/vec.h>
#include <siri/db/series.h>
+#include <siri/db/db.h>
#include <pcre2.h>
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);
#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);
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,
#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>
QUERY_ALTER_NONE,
QUERY_ALTER_DATABASE,
QUERY_ALTER_GROUP,
+ QUERY_ALTER_TAG,
QUERY_ALTER_SERVER,
QUERY_ALTER_SERVERS,
QUERY_ALTER_USER,
union query_alter_u
{
siridb_group_t * group;
+ siridb_tag_t * tag;
siridb_server_t * server;
siridb_user_t * user;
void * dummy;
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__) \
* 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_
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,
* 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"
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')
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')
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'])
["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()
}
/* 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);
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;
* (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)
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,
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)
{
#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);
/*
* 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;
}
/*
* (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,
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)
{
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.");
break;
}
- uv_mutex_unlock(&groups->mutex);
+ uv_mutex_unlock(&siridb->groups->mutex);
return rc;
}
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)
{
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,
"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 \
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);
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);
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;
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;
}
}
+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;
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')",
break;
case QUERY_ALTER_GROUP:
if (siridb_group_set_name(
- siridb->groups,
+ siridb,
q_alter->via.group,
name,
query->err_msg))
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:
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);
}
}
+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;
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,
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;
#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.
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.
*/
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.
*/
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);
}
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);
* 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"
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,
cleri_choice(
CLERI_NONE,
CLERI_FIRST_MATCH,
- 6,
+ 7,
alter_series,
alter_user,
alter_group,
+ alter_tag,
alter_server,
alter_servers,
alter_database