summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfumingwei <[email protected]>2023-03-17 23:53:11 +0800
committerfumingwei <[email protected]>2023-03-22 20:15:51 +0800
commit1b3d40eaa3db4867d71b0908f6121f1f21b8b448 (patch)
tree99f4831310ffc66d373151a4ef6cbc7ef8825e3e
parentea4c2b9c11ef8a02f745b514f4a54f07512a7e8b (diff)
feature:1.新增dynamic metric接口测试用例. 2.新增instance free接口.
-rw-r--r--inc/fieldstat.h110
-rw-r--r--src/fieldstat.cpp213
-rw-r--r--src/fieldstat_dynamic.cpp168
-rw-r--r--src/fieldstat_internal.h80
-rw-r--r--src/file_output.cpp20
-rw-r--r--src/line_protocol_output.cpp21
-rw-r--r--src/prometheus_output.cpp64
-rw-r--r--test/src/CMakeLists.txt3
-rw-r--r--test/src/gtest_dynamic_fieldstat.cpp2263
-rw-r--r--test/src/gtest_fieldstat.cpp46
10 files changed, 2873 insertions, 115 deletions
diff --git a/inc/fieldstat.h b/inc/fieldstat.h
index 4c0f7f7..64aff47 100644
--- a/inc/fieldstat.h
+++ b/inc/fieldstat.h
@@ -214,53 +214,125 @@ struct fieldstat_dynamic_instance * fieldstat_dynamic_instance_new(const char *n
*/
int fieldstat_dynamic_set_line_protocol_server(struct fieldstat_dynamic_instance *instance, const char *ip, unsigned short port);
/**
- * Disable the background thread.
+ * Disable the dynamic metric output background thread.
* The operation should be executed in single-threaded fashion.
* @param instance The fieldstat instance.
* @return -1 is failed. 0 is success.
*/
int fieldstat_dynamic_disable_background_thread(struct fieldstat_dynamic_instance *instance);
/**
- * Set the output interval in milliseconds
+ * Set the dynamic metric output interval in milliseconds
* The operation should be executed in single-threaded fashion.
* @param seconds In milliseconds.
* @return -1 is failed. 0 is success.
*/
int fieldstat_dynamic_set_output_interval(struct fieldstat_dynamic_instance *instance, int milliseconds);
/**
- * Passive output
+ * Dynamic metrics passive output
* @param instance The fieldstat instance.
*/
void fieldstat_dynamic_passive_output(struct fieldstat_dynamic_instance *instance);
/**
- * Make the fieldstat instance affect.
+ * Make the fieldstat dynamic instance affect.
* @param instance The fieldstat instance.
*/
void fieldstat_dynamic_instance_start(struct fieldstat_dynamic_instance *instance);
/**
- * Set the output interval in milliseconds
- * The operation should be executed in single-threaded fashion.
- * @param seconds In milliseconds.
- * @return -1 is failed. 0 is success.
+ * Register table. Max table num is 64. Max table columns is 64.
+ * @param instance The fieldstat dynamic instance.
+ * @param table_name The table name.
+ * @param column_name column name array.
+ * @param column_type column type array. Type in [counter, gauge]
+ * @param n_column size of column_type[] and column_name[]
+ * @param out_column_ids output metric id in table row.
+ * @return table id. -1 is failed. >=0 is success.
*/
-
int fieldstat_register_dynamic_table(struct fieldstat_dynamic_instance *instance, const char *table_name, const char *column_name[], enum field_type column_type[], size_t n_column, unsigned int out_column_ids[]);
-
+/**
+ * fieldstat dynamic instance metric value increment operate. metirc type in[gauge, counter]
+ * @param instance The fieldstat dynamic instance.
+ * @param type The metric type.
+ * @param field_name The metric field name.
+ * @param value The increment value.
+ * @param tags The tag array.
+ * @param n_tag Size of tags[]
+ * @param thread_id The thread id of the call.
+ * @return -1 is failed. 0 is success.
+ */
int fieldstat_dynamic_metric_value_incrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id);
-
+/**
+ * fieldstat dynamic instance metric value set operate. metirc type in[gauge, counter]
+ * @param instance The fieldstat dynamic instance.
+ * @param type The metric type.
+ * @param field_name The metric field name.
+ * @param value The set value.
+ * @param tags The tag array.
+ * @param n_tag Size of tags[]
+ * @param thread_id The thread id of the call.
+ * @return -1 is failed. 0 is success.
+ */
int fieldstat_dynamic_metric_value_set(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id);
-
+/**
+ * fieldstat dynamic instance metric value decrment operate. metirc type in[gauge, counter]
+ * @param instance The fieldstat dynamic instance.
+ * @param type The metric type.
+ * @param field_name The metric field name.
+ * @param value The decrment value.
+ * @param tags The tag array.
+ * @param n_tag Size of tags[]
+ * @param thread_id The thread id of the call.
+ * @return -1 is failed. 0 is success.
+ */
int fieldstat_dynamic_metric_value_decrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id);
-
-
+/**
+ * fieldstat dynamic instance table metric value incrment operate.
+ * @param instance The fieldstat dynamic instance.
+ * @param table_id The table id.
+ * @param column_id The column id.
+ * @param row_name The row name of table.
+ * @param value The incrment value.
+ * @param tags The tag array.
+ * @param n_tag Size of tags[]
+ * @param thread_id The thread id of the call.
+ * @return -1 is failed. 0 is success.
+ */
int fieldstat_dynamic_table_metric_value_incrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id);
-
+/**
+ * fieldstat dynamic instance table metric value set operate.
+ * @param instance The fieldstat dynamic instance.
+ * @param table_id The table id.
+ * @param column_id The column id.
+ * @param row_name The row name of table.
+ * @param value The set value.
+ * @param tags The tag array.
+ * @param n_tag Size of tags[]
+ * @param thread_id The thread id of the call.
+ * @return -1 is failed. 0 is success.
+ */
int fieldstat_dynamic_table_metric_value_set(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id);
-
+/**
+ * fieldstat dynamic instance table metric value decrment operate.
+ * @param instance The fieldstat dynamic instance.
+ * @param table_id The table id.
+ * @param column_id The column id.
+ * @param row_name The row name of table.
+ * @param value The decrment value.
+ * @param tags The tag array.
+ * @param n_tag Size of tags[]
+ * @param thread_id The thread id of the call.
+ * @return -1 is failed. 0 is success.
+ */
int fieldstat_dynamic_table_metric_value_decrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id);
-
-
-
+/**
+ * fieldstat instance free.
+ * @param instance The fieldstat instance need to free.
+ */
+void fieldstat_instance_free(struct fieldstat_instance *instance);
+/**
+ * fieldstat dynamic instance free.
+ * @param instance The fieldstat dynamic instance need to free.
+ */
+void fieldstat_dynamic_instance_free(struct fieldstat_dynamic_instance *instance);
#ifdef __cplusplus
}
#endif \ No newline at end of file
diff --git a/src/fieldstat.cpp b/src/fieldstat.cpp
index b67e8a5..3a8747c 100644
--- a/src/fieldstat.cpp
+++ b/src/fieldstat.cpp
@@ -48,6 +48,45 @@ int is_valid_field_name(const char* name)
return 1;
}
+int is_valid_tag_value(const char* value)
+{
+ const char* reserverd="|:\n\r \t<>[]#!@";
+ unsigned int i=0,j=0;
+ for(i=0;i<strlen(value);i++)
+ {
+ for(j=0;j<strlen(reserverd);j++)
+ if(value[i]==reserverd[j])
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+int is_valid_tags(const struct fieldstat_tag *tags, size_t n_tags)
+{
+ int i = 0;
+ struct fieldstat_tag *tag = NULL;
+
+ for(i = 0; i < (int)n_tags; i++)
+ {
+ tag = (struct fieldstat_tag *)&tags[i];
+ if (0 == is_valid_field_name(tag->key))
+ {
+ return 0;
+ }
+
+ if(tag->value_type == 2)
+ {
+ if (0 == is_valid_tag_value(tag->value_str))
+ {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
void get_current_table_line_cnt(struct fieldstat_instance *instance, int n_table, int *tables_line_cnt)
{
@@ -145,6 +184,11 @@ void metric_free(struct metric *metric)
}
metric->n_tag = 0;
+ if(metric->table)
+ {
+ metric->table = NULL;
+ }
+
free(metric);
return;
@@ -353,6 +397,11 @@ int fieldstat_register(struct fieldstat_instance *instance, enum field_type type
return -1;
}
+ if(0 == is_valid_tags(tags, n_tag))
+ {
+ return -1;
+ }
+
metric_id = atomic_inc(&instance->metric_cnt) - 1;
metric_slot = read_metric_slot(instance, metric_id);
metric = metric_new(type, field_name, tags, n_tag);
@@ -477,7 +526,7 @@ void fieldstat_instance_start(struct fieldstat_instance *instance)
clock_gettime(CLOCK_MONOTONIC,&(instance->last_output_time));
if(instance->background_thread_disable == 0)
{
- pthread_create(&(instance->cfg_mon_t), NULL, fieldstat_thread_schema_output, (void*)instance);
+ pthread_create(&(instance->background_thread), NULL, fieldstat_thread_schema_output, (void*)instance);
}
//append instance to prometheus output
}
@@ -490,6 +539,10 @@ struct fieldstat_instance * fieldstat_instance_new(const char *name)
{
return NULL;
}
+ if(!is_valid_field_name(name))
+ {
+ return NULL;
+ }
instance = (struct fieldstat_instance *)calloc(sizeof(struct fieldstat_instance),1);
strcpy(instance->name, name);
@@ -500,6 +553,65 @@ struct fieldstat_instance * fieldstat_instance_new(const char *name)
return instance;
}
+void fieldstat_instance_free(struct fieldstat_instance *instance)
+{
+ int i = 0;
+ void *pthread_ret;
+ struct metric *metric = NULL;
+ if(instance == NULL)
+ {
+ return;
+ }
+
+ if(instance->background_thread_is_created == 1)
+ {
+ pthread_cancel(instance->background_thread);
+ pthread_join(instance->background_thread, &pthread_ret);
+ instance->background_thread_is_created = 0;
+ instance->running = 0;
+ }
+
+ if(instance->local_output_fp)
+ {
+ fclose(instance->local_output_fp);
+ instance->local_output_fp = NULL;
+ instance->local_output_enable = 0;
+ }
+
+ if(instance->line_protocol_socket != -1)
+ {
+ close(instance->line_protocol_socket);
+ instance->line_protocol_socket = -1;
+ }
+
+ for(i = 0; i < instance->metric_cnt; i++)
+ {
+ metric = get_metric(instance, i);
+ metric_free(metric);
+ }
+
+ for(i = 0; i < instance->table_num; i++)
+ {
+ table_metric_free(instance->table_metrics[i]);
+ instance->table_metrics[i] = NULL;
+ }
+
+ if(instance->metric_block_list != NULL)
+ {
+ for(i = 0; i < BLOCK_LIST_SIZE; i++)
+ {
+ if(instance->metric_block_list[i] != NULL)
+ {
+ free(instance->metric_block_list[i]);
+ instance->metric_block_list[i] = NULL;
+ }
+ }
+ }
+ free(instance);
+ return;
+}
+
+
struct table_metric* table_metric_new(const char *name, const char *column_name[], enum field_type column_type[], size_t n_column)
{
int i = 0;
@@ -516,12 +628,70 @@ struct table_metric* table_metric_new(const char *name, const char *column_name[
return table_metric;
}
+void table_metric_free(struct table_metric *table)
+{
+ int i = 0;
+ struct table_line *table_line = NULL;
+
+ if(table == NULL)
+ {
+ return;
+ }
+ free(table->name);
+ table->name = NULL;
+ for(i = 0; i < (int)table->column_cnt; i++)
+ {
+ if(table->column_name[i] == NULL)
+ {
+ continue;
+ }
+ free(table->column_name[i]);
+ table->column_name[i] = NULL;
+ }
+
+ for(i = 0; i < table->line_cnt; i++)
+ {
+ table_line = read_table_line(table, i);
+ table_line_free(table_line);
+ }
+
+ if(table->line_block != NULL)
+ {
+ for(i = 0; i < BLOCK_LIST_SIZE; i++)
+ {
+ if(table->line_block[i] == NULL)
+ {
+ continue;
+ }
+ free(table->line_block[i]);
+ table->line_block[i] = NULL;
+ }
+ }
+ table->column_cnt = 0;
+ free(table);
+ return;
+}
+
+
int fieldstat_register_table(struct fieldstat_instance *instance, const char *table_name, const char *column_name[], enum field_type column_type[], size_t n_column)
{
int table_id = 0;
struct table_metric *table_metric = NULL;
+ if(!is_valid_field_name(table_name))
+ {
+ return -1;
+ }
+
+ for(int i = 0; i < (int)n_column; i++)
+ {
+ if(!is_valid_field_name(column_name[i]))
+ {
+ return -1;
+ }
+ }
+
if(n_column <= 0 || n_column > TABLE_COLUMN_SIZE)
{
return -1;
@@ -539,7 +709,7 @@ struct table_metric* table_metric_new(const char *name, const char *column_name[
return table_id;
}
-static struct table_line ** read_table_line_slot(struct table_metric *table, int line_id)
+struct table_line ** read_table_line_slot(struct table_metric *table, int line_id)
{
int block_index = 0;
int in_block_index = 0;
@@ -561,7 +731,7 @@ static struct table_line ** read_table_line_slot(struct table_metric *table, int
return (struct table_line **)&(line[in_block_index]);
}
-static struct table_line *table_line_new(const char *name, const struct fieldstat_tag tags[],size_t n_tag)
+struct table_line *table_line_new(const char *name, const struct fieldstat_tag tags[],size_t n_tag)
{
struct table_line *table_line = (struct table_line *)calloc(sizeof(struct table_line), 1);
@@ -574,6 +744,32 @@ static struct table_line *table_line_new(const char *name, const struct fieldsta
}
+void table_line_free(struct table_line *table_line)
+{
+ if(table_line == NULL)
+ {
+ return;
+ }
+
+ free(table_line->name);
+
+ table_line->name = NULL;
+
+ for(int i = 0; i < (int)table_line->n_tag; i++)
+ {
+ free(table_line->tag_key[i]);
+ table_line->tag_key[i] = NULL;
+
+ free(table_line->tag_value[i]);
+ table_line->tag_value[i] = NULL;
+ }
+ table_line->n_tag = 0;
+
+ free(table_line);
+}
+
+
+
int fieldstat_register_table_row(struct fieldstat_instance * instance, int table_id, const char *row_name, const struct fieldstat_tag tags[], size_t n_tag, int output_metric_ids[])
{
int metric_id = 0;
@@ -595,6 +791,11 @@ int fieldstat_register_table_row(struct fieldstat_instance * instance, int table
return -1;
}
+ if(0 == is_valid_tags(tags, n_tag))
+ {
+ return -1;
+ }
+
table = instance->table_metrics[table_id];
line_id = atomic_inc(&(table->line_cnt)) - 1;
line_slot = read_table_line_slot(table, line_id);
@@ -607,11 +808,15 @@ int fieldstat_register_table_row(struct fieldstat_instance * instance, int table
table_line->metric_id_belong_to_line[i] = metric_id;
metric = get_metric(instance, metric_id);
+
+ metric->table = table;
+ metric->table_column_id = i;
+/*
metric->table_id = table_id;
metric->table_column_name = __str_dup(table->column_name[i]);
metric->table_name = __str_dup(table->name);
metric->belong_to_table = 1;
-
+*/
output_metric_ids[i] = metric_id;
}
*line_slot = table_line;
diff --git a/src/fieldstat_dynamic.cpp b/src/fieldstat_dynamic.cpp
index b9f163a..72f3155 100644
--- a/src/fieldstat_dynamic.cpp
+++ b/src/fieldstat_dynamic.cpp
@@ -8,6 +8,11 @@ struct fieldstat_dynamic_instance * fieldstat_dynamic_instance_new(const char *n
{
return NULL;
}
+
+ if(!is_valid_field_name(name))
+ {
+ return NULL;
+ }
instance = (struct fieldstat_dynamic_instance *)calloc(sizeof(struct fieldstat_dynamic_instance), 1);
@@ -22,9 +27,81 @@ struct fieldstat_dynamic_instance * fieldstat_dynamic_instance_new(const char *n
return instance;
}
+void fieldstat_dynamic_instance_free(struct fieldstat_dynamic_instance *instance)
+{
+ int i = 0;
+ struct dynamic_metric **head = NULL;
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ void *pthread_ret;
+
+ if(instance == NULL)
+ {
+ return;
+ }
+
+ if(instance->background_thread_is_created == 1)
+ {
+ pthread_cancel(instance->background_thread);
+ pthread_join(instance->background_thread, &pthread_ret);
+ instance->background_thread_is_created = 0;
+ instance->running = 0;
+ }
+
+ if(instance->line_protocol_socket != -1)
+ {
+ close(instance->line_protocol_socket);
+ instance->line_protocol_socket = -1;
+ }
+
+ for(i = 0; i < instance->n_thread; i++)
+ {
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ HASH_DEL(*head, dyn_metric);
+ if(dyn_metric->metrics)
+ {
+ int n_loop = 0;
+ struct metric *metric = dyn_metric->metrics[0];
+ if(metric->table)
+ {
+ n_loop = metric->table->column_cnt;
+ }
+ else
+ {
+ n_loop = 1;
+ }
+ for(int j = 0; j < n_loop; j ++)
+ {
+ metric_free(dyn_metric->metrics[j]);
+ dyn_metric->metrics[j] = NULL;
+ }
+ free(dyn_metric->metrics);
+ dyn_metric->metrics = NULL;
+ }
+ free(dyn_metric);
+ }
+ instance->n_thread_dynamic_metric[i] = NULL;
+ }
+
+ for(i = 0; i < instance->table_num; i++)
+ {
+ table_metric_free(instance->table_metrics[i]);
+ instance->table_metrics[i] = NULL;
+ }
+
+ free(instance->n_thread_dynamic_metric);
+ instance->n_thread_dynamic_metric = NULL;
+ free(instance);
+
+ return;
+}
+
+
+
int fieldstat_dynamic_set_line_protocol_server(struct fieldstat_dynamic_instance *instance, const char *ip, unsigned short port)
{
- if(instance->running == 1)
+ if(instance == NULL || instance->running == 1)
{
return -1;
}
@@ -85,6 +162,7 @@ void fieldstat_dynamic_passive_output(struct fieldstat_dynamic_instance *instanc
}
if(ret == -1)
{
+ printf("Passive return: output ret -1\n");
return;
}
memcpy(&(instance->last_output_time),&this_output_time, sizeof(this_output_time));
@@ -107,7 +185,8 @@ void fieldstat_dynamic_instance_start(struct fieldstat_dynamic_instance *instanc
clock_gettime(CLOCK_MONOTONIC, &(instance->last_output_time));
if(instance->background_thread_disable == 0)
{
- pthread_create(&(instance->cfg_mon_t), NULL, fieldstat_dynamic_thread_schema_output, (void*)instance);
+ pthread_create(&(instance->background_thread), NULL, fieldstat_dynamic_thread_schema_output, (void*)instance);
+ instance->background_thread_is_created = 1;
}
}
@@ -118,6 +197,19 @@ int fieldstat_register_dynamic_table(struct fieldstat_dynamic_instance *instance
struct table_metric *table_metric = NULL;
+ if(!is_valid_field_name(table_name))
+ {
+ return -1;
+ }
+
+ for(i = 0; i < (int)n_column; i++)
+ {
+ if(!is_valid_field_name(column_name[i]))
+ {
+ return -1;
+ }
+ }
+
if(n_column <= 0 || n_column > TABLE_COLUMN_SIZE)
{
return -1;
@@ -226,11 +318,15 @@ static struct metric * create_dynamic_table_metric(struct fieldstat_dynamic_inst
assert(0);
break;
}
+ metric->table = table;
+ metric->table_column_id = i;
+/*
metric->table_id = table_id;
metric->table_column_name = __str_dup(table->column_name[i]);
metric->table_name = __str_dup(table->name);
metric->belong_to_table = 1;
-
+ metric->table_column_cnt = table->column_cnt;
+*/
value->metrics[i] = metric;
}
@@ -297,21 +393,48 @@ static int fieldstat_dynamic_metric_value_operate(struct fieldstat_dynamic_insta
int fieldstat_dynamic_metric_value_incrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id)
{
int ret = 0;
- fieldstat_dynamic_metric_value_operate(instance, FS_OP_ADD, type, field_name, value, tags, n_tags, thread_id);
+ if(!is_valid_field_name(field_name))
+ {
+ return -1;
+ }
+
+ if(0 == is_valid_tags(tags, n_tags))
+ {
+ return -1;
+ }
+ ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_ADD, type, field_name, value, tags, n_tags, thread_id);
return ret;
}
int fieldstat_dynamic_metric_value_set(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id)
{
int ret = 0;
- fieldstat_dynamic_metric_value_operate(instance, FS_OP_SET, type, field_name, value, tags, n_tags, thread_id);
+ if(!is_valid_field_name(field_name))
+ {
+ return -1;
+ }
+ if(0 == is_valid_tags(tags, n_tags))
+ {
+ return -1;
+ }
+
+ ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_SET, type, field_name, value, tags, n_tags, thread_id);
return ret;
}
int fieldstat_dynamic_metric_value_decrby(struct fieldstat_dynamic_instance *instance, enum field_type type, const char *field_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id)
{
int ret = 0;
- fieldstat_dynamic_metric_value_operate(instance, FS_OP_SUB, type, field_name, value, tags, n_tags, thread_id);
+ if(!is_valid_field_name(field_name))
+ {
+ return -1;
+ }
+ if(0 == is_valid_tags(tags, n_tags))
+ {
+ return -1;
+ }
+
+ ret = fieldstat_dynamic_metric_value_operate(instance, FS_OP_SUB, type, field_name, value, tags, n_tags, thread_id);
return ret;
}
@@ -336,21 +459,48 @@ int fieldstat_dynamic_table_metric_value_operate(struct fieldstat_dynamic_instan
int fieldstat_dynamic_table_metric_value_incrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id)
{
int ret = 0;
- fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_ADD, table_id, column_id, row_name, value, tags, n_tags, thread_id);
+ if(!is_valid_field_name(row_name))
+ {
+ return -1;
+ }
+ if(0 == is_valid_tags(tags, n_tags))
+ {
+ return -1;
+ }
+
+ ret = fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_ADD, table_id, column_id, row_name, value, tags, n_tags, thread_id);
return ret;
}
int fieldstat_dynamic_table_metric_value_set(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id)
{
int ret = 0;
- fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SET, table_id, column_id, row_name, value, tags, n_tags, thread_id);
+ if(!is_valid_field_name(row_name))
+ {
+ return -1;
+ }
+ if(0 == is_valid_tags(tags, n_tags))
+ {
+ return -1;
+ }
+
+ ret = fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SET, table_id, column_id, row_name, value, tags, n_tags, thread_id);
return ret;
}
int fieldstat_dynamic_table_metric_value_decrby(struct fieldstat_dynamic_instance *instance, int table_id, unsigned int column_id, const char *row_name, long long value, const struct fieldstat_tag tags[], size_t n_tags, int thread_id)
{
int ret = 0;
- fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SUB, table_id, column_id, row_name, value, tags, n_tags, thread_id);
+ if(!is_valid_field_name(row_name))
+ {
+ return -1;
+ }
+ if(0 == is_valid_tags(tags, n_tags))
+ {
+ return -1;
+ }
+
+ ret = fieldstat_dynamic_table_metric_value_operate( instance, FS_OP_SUB, table_id, column_id, row_name, value, tags, n_tags, thread_id);
return ret;
}
diff --git a/src/fieldstat_internal.h b/src/fieldstat_internal.h
index 1e8fc34..97171e5 100644
--- a/src/fieldstat_internal.h
+++ b/src/fieldstat_internal.h
@@ -100,6 +100,27 @@ struct histogram_t
double *bins;
};
+struct table_line
+{
+ char *name;
+ size_t n_tag;
+ char *tag_key[N_TAG_MAX];
+ char *tag_value[N_TAG_MAX];
+
+ int metric_id_belong_to_line[TABLE_COLUMN_SIZE];
+};
+
+struct table_metric
+{
+ char *name;
+ char *column_name[TABLE_COLUMN_SIZE];
+ enum field_type column_type[TABLE_COLUMN_SIZE];
+ int column_cnt;
+
+ int line_cnt;
+ struct table_line **line_block[BLOCK_LIST_SIZE];
+};
+
struct metric
{
@@ -115,13 +136,15 @@ struct metric
int not_send_to_server;
int numerator_id;
int denominator_id;
-
+/*
int belong_to_table;
int table_id;
- size_t line_seq;
- int table_column_id;
char *table_column_name;
char *table_name;
+ int table_column_cnt;
+*/
+ struct table_metric *table;
+ int table_column_id;
union
{
@@ -131,28 +154,6 @@ struct metric
};
};
-struct table_line
-{
- char *name;
- size_t n_tag;
- char *tag_key[N_TAG_MAX];
- char *tag_value[N_TAG_MAX];
-
- int metric_id_belong_to_line[TABLE_COLUMN_SIZE];
-};
-
-struct table_metric
-{
- char *name;
- char *column_name[TABLE_COLUMN_SIZE];
- enum field_type column_type[TABLE_COLUMN_SIZE];
- int column_cnt;
-
- int line_cnt;
- struct table_line **line_block[BLOCK_LIST_SIZE];
-};
-
-
struct fieldstat_instance
{
char name[INSTANCE_NAME_LEN];
@@ -161,6 +162,7 @@ struct fieldstat_instance
unsigned int statsd_server_ip;
unsigned short statsd_server_port;
int statsd_output_enable;
+ int line_protocol_socket;
//char line_protocol_server_str_ip[LEN_IP_MAX];
unsigned int line_protocol_server_ip;
@@ -170,8 +172,12 @@ struct fieldstat_instance
char local_output_filename[LEN_PATH_MAX];
char local_output_format[LEN_FORMAT_MAX];
int local_output_enable;
+ FILE* local_output_fp;
int background_thread_disable;
+ pthread_t background_thread;
+ int background_thread_is_created;
+
int output_interval_ms;
int running;
@@ -182,10 +188,7 @@ struct fieldstat_instance
struct table_metric *table_metrics[TABLE_MAX_NUM];
- int *index_table[TABLE_MAX_NUM][TABLE_COLUMN_SIZE];
-
int table_num;
- int line_seq;
int prometheus_output_enable;
@@ -194,14 +197,9 @@ struct fieldstat_instance
struct timespec last_output_time;
- pthread_t cfg_mon_t;
char line_protocol_send_buff[UDP_PAYLOAD_SIZE];
size_t line_protocol_send_buff_offset;
- int line_protocol_socket;
- pthread_mutex_t output_lock;
-
- FILE* fp;
};
struct prometheus_endpoint_instance
@@ -209,6 +207,7 @@ struct prometheus_endpoint_instance
unsigned short port;
char *url_path;
pthread_t tid;
+ int thread_created;
int running;
struct http_server_s *server_handle;
int fs_instance_cnt;
@@ -238,7 +237,8 @@ struct fieldstat_dynamic_instance
int table_num;
struct timespec last_output_time;
- pthread_t cfg_mon_t;
+ pthread_t background_thread;
+ int background_thread_is_created;
char line_protocol_send_buff[UDP_PAYLOAD_SIZE];
size_t line_protocol_send_buff_offset;
int line_protocol_socket;
@@ -255,8 +255,10 @@ long long hdr_count_le_value(const struct hdr_histogram* h, long long value);
struct metric * get_metric(struct fieldstat_instance *instance, int metric_id);
long long get_metric_unit_val(struct metric *metric,enum field_calc_algo calc_type,int is_refer);
int is_valid_field_name(const char* name);
+int is_valid_tags(const struct fieldstat_tag *tags, size_t n_tags);
struct metric ** read_metric_slot(struct fieldstat_instance *instance, int metric_id);
struct metric * metric_new(enum field_type type, const char *field_name, const struct fieldstat_tag tags[], size_t n_tag);
+void metric_free(struct metric *metric);
int fieldstat_output_file(struct fieldstat_instance *instance,long long interval_ms);
struct table_line * read_table_line(struct table_metric *table, int line_id);
int send_udp(int sd, unsigned int dest_ip, unsigned short dest_port, const char * data, int len);
@@ -266,4 +268,12 @@ int startup_udp();
void metric_value_operate(struct metric *metric, enum field_op op, long long value);
struct table_metric* table_metric_new(const char *name, const char *column_name[], enum field_type column_type[], size_t n_column);
-int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *instance); \ No newline at end of file
+void table_metric_free(struct table_metric *table);
+
+struct table_line *table_line_new(const char *name, const struct fieldstat_tag tags[],size_t n_tag);
+void table_line_free(struct table_line *table_line);
+int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *instance);
+
+struct table_line ** read_table_line_slot(struct table_metric *table, int line_id);
+
+void fieldstat_global_disable_prometheus_endpoint(); \ No newline at end of file
diff --git a/src/file_output.cpp b/src/file_output.cpp
index 3c4c921..40d28a1 100644
--- a/src/file_output.cpp
+++ b/src/file_output.cpp
@@ -64,7 +64,7 @@ static int output_file_format_default_type_gauge(struct fieldstat_instance *inst
{
continue;
}
- if(metric->belong_to_table == 1)
+ if(metric->table)
{
continue;
}
@@ -137,7 +137,7 @@ static int output_file_format_default_type_counter(struct fieldstat_instance *in
{
continue;
}
- if(metric->belong_to_table == 1)
+ if(metric->table)
{
continue;
}
@@ -403,8 +403,8 @@ static int output_file_format_default_type_histogram_and_summary(struct fieldsta
char *pos = print_buf;
//display_manifest_t* p=NULL;
struct metric *metric = NULL;
- struct metric *metric_array[current_metric_cnt] = {NULL};
- int metric_is_print[current_metric_cnt] = {0};
+ struct metric *metric_array[current_metric_cnt];
+ int metric_is_print[current_metric_cnt];
if(instance->histogram_cnt == 0
&& instance->summary_cnt == 0)
@@ -476,10 +476,10 @@ int fieldstat_output_file(struct fieldstat_instance *instance,long long interval
time_t current = 0;
char ctime_buff[STR_LEN_32]={0};
- if(instance->fp == NULL)
+ if(instance->local_output_fp == NULL)
{
- instance->fp = fopen(instance->local_output_filename, "w");
- if(instance->fp == NULL)
+ instance->local_output_fp = fopen(instance->local_output_filename, "w");
+ if(instance->local_output_fp == NULL)
{
printf("Field Stat: open %s failed.\n",instance->local_output_filename);
assert(0);
@@ -511,10 +511,10 @@ int fieldstat_output_file(struct fieldstat_instance *instance,long long interval
//TODO from json output
}
- fseek(instance->fp,0,SEEK_SET);
- fwrite(print_buf,append_pos - print_buf,1,instance->fp);
+ fseek(instance->local_output_fp, 0, SEEK_SET);
+ fwrite(print_buf,append_pos - print_buf,1,instance->local_output_fp);
- fflush(instance->fp);
+ fflush(instance->local_output_fp);
if(print_buf)
{
diff --git a/src/line_protocol_output.cpp b/src/line_protocol_output.cpp
index 3f4e86c..f1b2c16 100644
--- a/src/line_protocol_output.cpp
+++ b/src/line_protocol_output.cpp
@@ -121,7 +121,7 @@ static void output_line_protocol_table(struct fieldstat_instance *instance,int t
field_pos += snprintf(field_pos,
sizeof(field_set_buff) - (field_set_buff - field_set_buff),
"%s=%lld,",
- metric->table_column_name,
+ metric->table->column_name[metric->table_column_id],
value
);
@@ -178,7 +178,7 @@ int line_protocol_output(struct fieldstat_instance *instance)
continue;
}
- if(metric->belong_to_table == 1)
+ if(metric->table)
{
continue;
}
@@ -258,7 +258,7 @@ static void append_line_protocol_dynamic_row(struct fieldstat_dynamic_instance *
{
flush_line_protocol_dynamic_metric(instance);
}
- printf("Line_protocol metric: %s%s %s\n",measurement,tag_set,field_set);
+ //printf("Line_protocol metric: %s:%s %s\n",measurement,tag_set,field_set);
instance->line_protocol_send_buff_offset += snprintf(instance->line_protocol_send_buff + instance->line_protocol_send_buff_offset,
sizeof(instance->line_protocol_send_buff) - instance->line_protocol_send_buff_offset,
"%s%s %s\n",
@@ -294,16 +294,16 @@ int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *insta
metrics = dyn_metric->metrics;
metric = metrics[0];
memset(tag_set_buff, 0, sizeof(tag_set_buff));
- memset(field_set_buff, 0 ,sizeof(field_set_buff));
+ memset(field_set_buff, 0,sizeof(field_set_buff));
field_used_len = 0;
tag_used_len = 0;
- if(metric->belong_to_table == 1)
+ if(metric->table)
{
- table = instance->table_metrics[metric->table_id];
+ table = metric->table;
for(j = 0; j < table->column_cnt; j++)
{
- metric = metrics[i];
+ metric = metrics[j];
value = metric->field_type == FIELD_TYPE_GAUGE ?
get_metric_unit_val(metric, FS_CALC_CURRENT, 0):
get_metric_unit_val(metric, FS_CALC_SPEED, 0);
@@ -314,15 +314,18 @@ int line_protocol_dynamic_metric_output(struct fieldstat_dynamic_instance *insta
field_used_len += snprintf(field_set_buff + field_used_len,
sizeof(field_set_buff) - field_used_len,
"%s=%lld,",
- metric->table_column_name,
+ metric->table->column_name[metric->table_column_id],
value
);
}
- if(row_value_is_not_zero == 1)
+ if(row_value_is_not_zero != 1)
{
continue;
}
+ metric = metrics[0];
+ field_used_len--;
+ field_set_buff[field_used_len] = '\0';
tag_used_len += snprintf(tag_set_buff + tag_used_len,
sizeof(tag_set_buff) - tag_used_len,
",app_name=%s,table_name=%s",
diff --git a/src/prometheus_output.cpp b/src/prometheus_output.cpp
index 151bfba..8b31ae3 100644
--- a/src/prometheus_output.cpp
+++ b/src/prometheus_output.cpp
@@ -8,6 +8,7 @@ struct prometheus_endpoint_instance g_prometheus_endpoint_instance =
NULL,
0,
0,
+ 0,
NULL,
0,
NULL,
@@ -98,17 +99,24 @@ static void prometheus_output_uri_list(struct prometheus_endpoint_instance *prom
fs_instance = prometheus_output->fs_instance;
+ if(prometheus_output->fs_instance_cnt > 0)
+ {
+ payload_len = prometheus_output->fs_instance_cnt * 128; //TODO using marco, len?
+ printf("payload_len =%d\n, n_instance =%d\n", payload_len, prometheus_output->fs_instance_cnt);
+ payload = (char *)calloc(1,payload_len);
+ payload_append_position = payload;
+ payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"url_path:\n\t%s\n", prometheus_output->url_path);
- payload_len = prometheus_output->fs_instance_cnt * 128; //TODO using marco, len?
- payload_append_position = payload = (char *)calloc(1,payload_len);
-
- payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"url_path:\n\t%s\n", prometheus_output->url_path);
-
- for(i = 0; i < prometheus_output->fs_instance_cnt; i++)
+ for(i = 0; i < prometheus_output->fs_instance_cnt; i++)
+ {
+ payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"\t/%s\n", fs_instance[i]->name);
+ }
+ }
+ else
{
- payload_append_position += snprintf(payload_append_position, payload_len - (payload_append_position - payload),"\t/%s\n", fs_instance[i]->name);
+ payload = (char *)calloc(1, 128);
+ strncpy(payload, "Not Invaild instance\n", 128);
}
-
response = http_response_init();
http_response_status(response, 404);
http_response_header(response, "Content-Type", "text/plain; charset=utf-8");
@@ -130,7 +138,7 @@ static int prometheus_output_read_metric_tags(struct metric *metric, char *insta
append_pos += snprintf(append_pos, size - (append_pos - tags_buff), "app_name=\"%s\"", instance_name);
- if(metric->belong_to_table == 1)
+ if(metric->table)
{
append_pos += snprintf(append_pos, size - (append_pos - tags_buff), ",line_name=\"%s\"", metric->field_name);
}
@@ -149,9 +157,9 @@ static int prometheus_output_read_metric_name(struct metric *metric, char *insta
{
char unescape[256] = {0};
char *append_pos = name_buff;
- if(metric->belong_to_table == 1)
+ if(metric->table)
{
- str_unescape(metric->table_column_name, unescape, sizeof(unescape));
+ str_unescape(metric->table->column_name[metric->table_column_id], unescape, sizeof(unescape));
}
else
{
@@ -417,9 +425,8 @@ int fieldstat_global_enable_prometheus_endpoint(unsigned short listen_port, cons
g_prometheus_endpoint_instance.port = listen_port;
g_prometheus_endpoint_instance.running = 1;
g_prometheus_endpoint_instance.fs_instance = (struct fieldstat_instance **)calloc( sizeof(struct fieldstat_instance *), g_prometheus_endpoint_instance.fs_instance_size);
-
pthread_create(&g_prometheus_endpoint_instance.tid, NULL, prometheus_endpoint_listen_thread_entry, (void *)&g_prometheus_endpoint_instance);
-
+ g_prometheus_endpoint_instance.thread_created = 1;
return 0;
}
@@ -444,3 +451,34 @@ int fieldstat_enable_prometheus_output(struct fieldstat_instance *instance)
}
+void fieldstat_global_disable_prometheus_endpoint()
+{
+ void *pthread_ret;
+
+ if(g_prometheus_endpoint_instance.thread_created == 1)
+ {
+ pthread_cancel(g_prometheus_endpoint_instance.tid);
+ pthread_join(g_prometheus_endpoint_instance.tid, &pthread_ret);
+ g_prometheus_endpoint_instance.running = 0;
+ g_prometheus_endpoint_instance.thread_created = 0;
+ free(g_prometheus_endpoint_instance.server_handle);
+ g_prometheus_endpoint_instance.server_handle = NULL;
+ }
+
+ if(g_prometheus_endpoint_instance.url_path)
+ {
+ free(g_prometheus_endpoint_instance.url_path);
+ g_prometheus_endpoint_instance.url_path = NULL;
+ }
+
+ if(g_prometheus_endpoint_instance.fs_instance)
+ {
+ free(g_prometheus_endpoint_instance.fs_instance);
+ g_prometheus_endpoint_instance.fs_instance = NULL;
+ g_prometheus_endpoint_instance.fs_instance_cnt = 0;
+ g_prometheus_endpoint_instance.fs_instance_size = 0;
+ }
+
+ return;
+}
+
diff --git a/test/src/CMakeLists.txt b/test/src/CMakeLists.txt
index aa1250b..fa02909 100644
--- a/test/src/CMakeLists.txt
+++ b/test/src/CMakeLists.txt
@@ -2,8 +2,7 @@ cmake_minimum_required(VERSION 2.8)
include_directories(${PROJECT_SOURCE_DIR}/inc/)
include_directories(${PROJECT_SOURCE_DIR}/src/)
-
-
+add_definitions(-std=c++11)
#add_executable(gtest_rule ${PROJECT_SOURCE_DIR}/src/tsg_rule.cpp ${PROJECT_SOURCE_DIR}/src/tsg_bridge.cpp ${PROJECT_SOURCE_DIR}/src/tsg_leaky_bucket.cpp gtest_common.cpp gtest_rule.cpp)
#target_link_libraries(gtest_rule gtest-static ctemplate-static cjson MESA_prof_load MESA_handle_logger MESA_jump_layer MESA_field_stat2 maatframe)
diff --git a/test/src/gtest_dynamic_fieldstat.cpp b/test/src/gtest_dynamic_fieldstat.cpp
index 4fe76e2..7c3aa09 100644
--- a/test/src/gtest_dynamic_fieldstat.cpp
+++ b/test/src/gtest_dynamic_fieldstat.cpp
@@ -4,12 +4,14 @@
#include <gtest/gtest.h>
#include "fieldstat.h"
#include "fieldstat_internal.h"
+#include "cJSON.h"
extern struct prometheus_endpoint_instance g_prometheus_endpoint_instance;
TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceNew)
{
- struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", 16);
+ struct fieldstat_dynamic_instance *instance = NULL;
+ instance = fieldstat_dynamic_instance_new("firewall", 16);
EXPECT_NE(nullptr, instance);
EXPECT_STREQ("firewall", instance->name);
@@ -19,6 +21,53 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceNew)
{
EXPECT_EQ(nullptr, instance->n_thread_dynamic_metric[i]);
}
+ fieldstat_dynamic_instance_free(instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall-name-length-more-than-32", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall", 0);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall\n", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall|", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall:", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall.", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall ", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall\t", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall<", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall>", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall[", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall]", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall#", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall!", 16);
+ EXPECT_EQ(nullptr, instance);
+
+ instance = fieldstat_dynamic_instance_new("firewall@", 16);
+ EXPECT_EQ(nullptr, instance);
+
}
TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceSetPara)
@@ -44,6 +93,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceSetPara)
ret = fieldstat_dynamic_set_output_interval(instance, 5000);
EXPECT_EQ(0, ret);
EXPECT_EQ(5000, instance->output_interval_ms);
+ fieldstat_dynamic_instance_free(instance);
}
@@ -56,8 +106,9 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicStart)
fieldstat_dynamic_instance_start(instance);
EXPECT_EQ(1, instance->running);
- ret = pthread_kill(instance->cfg_mon_t, 0);
+ ret = pthread_kill(instance->background_thread, 0);
EXPECT_EQ(0, ret);
+ fieldstat_dynamic_instance_free(instance);
}
TEST(FeildStatDynamicAPI, FieldStatDynamicPassiveOutput)
@@ -85,7 +136,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicPassiveOutput)
fieldstat_dynamic_passive_output(instance);
EXPECT_NE(0, instance->last_output_time.tv_sec);
EXPECT_NE(0, instance->last_output_time.tv_nsec);
-
+ fieldstat_dynamic_instance_free(instance);
}
TEST(FeildStatDynamicAPI, FieldStatRegisterDynamicTable)
@@ -130,7 +181,7 @@ TEST(FeildStatDynamicAPI, FieldStatRegisterDynamicTable)
}
}
-
+ fieldstat_dynamic_instance_free(instance);
}
@@ -192,7 +243,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueIncrby)
}
}
-
+ fieldstat_dynamic_instance_free(instance);
}
@@ -253,6 +304,7 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueSet)
}
}
}
+ fieldstat_dynamic_instance_free(instance);
}
TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueDecrby)
@@ -312,8 +364,2209 @@ TEST(FeildStatDynamicAPI, FieldStatDynamicMetricValueDecrby)
}
}
}
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicTableMetricValueIncrby)
+{
+ int ret = 0;
+ int n_thread = 64;
+ struct fieldstat_tag tags[3];
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 20 + i, tags, sizeof(tags)/sizeof(tags[0]), i);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 200 + i, tags, sizeof(tags)/sizeof(tags[0]), i);
+ EXPECT_EQ(0, ret);
+ }
+ //EXPECT Per thread add one value.
+ for(int i = 0; i < n_thread; i++)
+ {
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ for(int j = 0; j < 2; j++)
+ {
+ metric = metrics[j];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ switch(j)
+ {
+ case 0:
+ EXPECT_EQ(value, 20 + i);
+ break;
+ case 1:
+ EXPECT_EQ(value, 200 + i);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ }
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicTableMetricValueSet)
+{
+ int ret = 0;
+ int n_thread = 64;
+ struct fieldstat_tag tags[3];
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], "security_rule_hits", 20 + i, tags, sizeof(tags)/sizeof(tags[0]), i);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], "security_rule_hits", 200 + i, tags, sizeof(tags)/sizeof(tags[0]), i);
+ EXPECT_EQ(0, ret);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ for(int j = 0; j < 2; j++)
+ {
+ metric = metrics[j];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ switch(j)
+ {
+ case 0:
+ EXPECT_EQ(value, 20 + i);
+ break;
+ case 1:
+ EXPECT_EQ(value, 200 + i);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ }
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicTableMetricValueDecrby)
+{
+ int ret = 0;
+ int n_thread = 64;
+ struct fieldstat_tag tags[3];
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], "security_rule_hits", 20 + i, tags, sizeof(tags)/sizeof(tags[0]), i);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], "security_rule_hits", 200 + i, tags, sizeof(tags)/sizeof(tags[0]), i);
+ EXPECT_EQ(0, ret);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ for(int j = 0; j < 2; j++)
+ {
+ metric = metrics[j];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ switch(j)
+ {
+ case 0:
+ EXPECT_EQ(value, -(20 + i));
+ break;
+ case 1:
+ EXPECT_EQ(value, -(200 + i));
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ }
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+void parse_telegraf_cjson_output(const char *compare)
+{
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ FILE *fp;
+ char line[1024] = {0};
+ char *cjson_metric_str = NULL;
+ int ret = 0;
+
+ fp = fopen(telegraf_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+
+ while(!feof(fp))
+ {
+ fgets(line, sizeof(line), fp);
+ }
+ fclose(fp);
+
+//{"fields":{"Active_sessions":10},"name":"Active_sessions","tags":{"app_name":"firewall","host":"developer-testing-41.22"},"timestamp":1679308196}
+//{"fields":{"Active_sessions":10},"name":"Active_sessions","tags":{"app_name":"firewall"}}
+
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+
+ cjson_metric = cJSON_Parse(line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric ,"timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ ret = strcmp(cjson_metric_str, compare);
+ EXPECT_EQ(0, ret);
+ cJSON_Delete(cjson_metric);
+ if(cjson_metric_str)
+ {
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ return;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolNoTag)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ const char *compare_zero_tag = "{\"fields\":{\"Active_sessions\":10},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}";
+
+
+ EXPECT_NE(nullptr, instance);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, NULL, 0, 0);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_zero_tag);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolOneTag)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ struct fieldstat_tag tags[1];
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ const char *compare_one_tag = "{\"fields\":{\"Active_sessions\":11},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\"}}";
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ EXPECT_NE(nullptr, instance);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 11, tags, 1, 0);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_one_tag);
+ fieldstat_dynamic_instance_free(instance);
+
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTwoTags)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ struct fieldstat_tag tags[2];
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ const char *compare_two_tags = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\",\"quanlity\":\"0.500000\"}}";
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ EXPECT_NE(nullptr, instance);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 12, tags, 2, 0);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_two_tags);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricNoTag)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ const char *compare_zero_tag = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+
+
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_zero_tag);
+ fieldstat_dynamic_instance_free(instance);
+ //parse_telegraf_cjson_output(compare_zero_tag_column1);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricOneTag)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ struct fieldstat_tag tags[1];
+
+ const char *compare_one_tag = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\",\"table_name\":\"shaping\"}}";
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_one_tag);
+ fieldstat_dynamic_instance_free(instance);
+ //parse_telegraf_cjson_output(compare_zero_tag_column1);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTowTags)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ struct fieldstat_tag tags[2];
+
+ const char *compare_two_tags = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"policy_id\":\"1\",\"quanlity\":\"0.500000\",\"table_name\":\"shaping\"}}";
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_two_tags);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTypeGauge)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+
+ const char *compare_first_output = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}";
+ const char *compare_second_output = "{\"fields\":{\"Active_sessions\":24},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}";
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 12, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_first_output);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 12, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_second_output);
+ fieldstat_dynamic_instance_free(instance);
+
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTypeCounter)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+
+ const char *compare_first_output = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}";
+ const char *compare_second_output = "{\"fields\":{\"Active_sessions\":12},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}";
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, "Active_sessions", 12, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_first_output);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, "Active_sessions", 12, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_second_output);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTypeAllCounter)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ const char *compare_update_column_0 = "{\"fields\":{\"bytes\":0,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+ const char *compare_update_column_1 = "{\"fields\":{\"bytes\":30,\"packages\":0},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+ const char *compare_update_column_all = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_0);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_1);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_all);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTypeAllGauge)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_GAUGE, FIELD_TYPE_GAUGE};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ const char *compare_update_column_0 = "{\"fields\":{\"bytes\":0,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+ const char *compare_update_column_1 = "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+ const char *compare_update_column_all = "{\"fields\":{\"bytes\":60,\"packages\":60},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_0);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_1);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_all);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricTypeOneCounterOneGauge)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_GAUGE};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ const char *compare_update_column_0 = "{\"fields\":{\"bytes\":0,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+ const char *compare_update_column_1 = "{\"fields\":{\"bytes\":30,\"packages\":0},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+ const char *compare_update_column_all = "{\"fields\":{\"bytes\":60,\"packages\":30},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_0);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_1);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, NULL, 0, 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output(compare_update_column_all);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+void parse_telegraf_cjson_output_not_equal(const char *compare)
+{
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ FILE *fp;
+ char line[1024] = {0};
+ char *cjson_metric_str = NULL;
+ int ret = 0;
+
+ fp = fopen(telegraf_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+
+ while(!feof(fp))
+ {
+ fgets(line, sizeof(line), fp);
+ }
+ fclose(fp);
+
+
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+
+ cjson_metric = cJSON_Parse(line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ ret = strcmp(cjson_metric_str, compare);
+ EXPECT_NE(0, ret);
+ cJSON_Delete(cjson_metric);
+ if(cjson_metric_str)
+ {
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ return;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolValueZero)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+
+ const char *compare_output = "{\"fields\":{\"Active_sessions\":0},\"name\":\"Active_sessions\",\"tags\":{\"app_name\":\"firewall\"}}";
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 0, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output_not_equal(compare_output);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolTableMetricValueZero)
+{
+ int n_thread = 48;
+ int ret = 0;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+ const char *compare_column = "{\"fields\":{\"bytes\":0,\"packages\":0},\"name\":\"security_rule_hits\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}";
+
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 0, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output_not_equal(compare_column);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 0, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output_not_equal(compare_column);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 0, NULL, 0, 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 0, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(1);
+ parse_telegraf_cjson_output_not_equal(compare_column);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolMultiMetric)
+{
+ int n_thread = 48;
+ int ret = 0;
+ int loops = 5000;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ char field_name[32];
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ FILE *fp;
+ char line[1024] = {0};
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ char compare[1024];
+ char *cjson_metric_str = NULL;
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+ for(int i = 0; i < loops; i++)
+ {
+ memset(field_name, 0, sizeof(field_name));
+ snprintf(field_name, sizeof(field_name), "Active_sessions_%d", i);
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, (const char *)field_name, 12, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ }
+ ret = system("cat /dev/null > /tmp/metrics.out");
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(5);
+
+ fp = fopen(telegraf_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ int n_line = 0;
+
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ cjson_metric = cJSON_Parse(line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ memset(compare, 0, sizeof(compare));
+ snprintf(compare, sizeof(compare), "{\"fields\":{\"Active_sessions_%d\":12},\"name\":\"Active_sessions_%d\",\"tags\":{\"app_name\":\"firewall\"}}", n_line, n_line);
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_STREQ(compare, cjson_metric_str);
+ cJSON_Delete(cjson_metric);
+ if(cjson_metric_str)
+ {
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, loops);
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicOutputLineProtocolMultiTableRow)
+{
+ int n_thread = 48;
+ int ret = 0;
+ int loops = 5000;
+ struct fieldstat_dynamic_instance *instance = NULL;
+ char row_name[32];
+ const char *telegraf_output_file = "/tmp/metrics.out";
+ FILE *fp;
+ char line[1024] = {0};
+ cJSON *cjson_metric = NULL;
+ cJSON *cjson_tags = NULL;
+ char compare[1024];
+ char *cjson_metric_str = NULL;
+
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+ EXPECT_NE(nullptr, instance);
+ ret = fieldstat_dynamic_set_line_protocol_server(instance, "127.0.0.1", 8600);
+ EXPECT_EQ(0, ret);
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+ EXPECT_EQ(0, table_id);
+ for(int i = 0; i < loops; i++)
+ {
+ memset(row_name, 0, sizeof(row_name));
+ snprintf(row_name, sizeof(row_name), "security_rule_hits_%d", i);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], row_name, 30, NULL, 0, 0);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], row_name, 30, NULL, 0, 0);
+ EXPECT_EQ(0, ret);
+ }
+ ret = system("cat /dev/null > /tmp/metrics.out");
+ ret = line_protocol_dynamic_metric_output(instance);
+ EXPECT_EQ(0, ret);
+ sleep(5);
+
+ fp = fopen(telegraf_output_file, "r");
+ EXPECT_NE(nullptr, fp);
+ int n_line = 0;
+
+ while(!feof(fp))
+ {
+ if(NULL == fgets(line, sizeof(line), fp))
+ {
+ continue;
+ }
+ cjson_metric = cJSON_Parse(line);
+ EXPECT_NE(nullptr, cjson_metric);
+ cJSON_DeleteItemFromObject(cjson_metric, "timestamp");
+
+ cjson_tags = cJSON_GetObjectItem(cjson_metric, "tags");
+ EXPECT_NE(nullptr, cjson_tags);
+ cJSON_DeleteItemFromObject(cjson_tags, "host");
+ memset(compare, 0, sizeof(compare));
+
+ snprintf(compare, sizeof(compare), "{\"fields\":{\"bytes\":30,\"packages\":30},\"name\":\"security_rule_hits_%d\",\"tags\":{\"app_name\":\"firewall\",\"table_name\":\"shaping\"}}", n_line);
+ cjson_metric_str = cJSON_PrintUnformatted(cjson_metric);
+ EXPECT_STREQ(compare, cjson_metric_str);
+ cJSON_Delete(cjson_metric);
+ if(cjson_metric_str)
+ {
+ free(cjson_metric_str);
+ cjson_metric_str = NULL;
+ }
+ n_line++;
+ }
+ fclose(fp);
+ EXPECT_EQ(n_line, loops);
+
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+
+struct thread_para
+{
+ int loops;
+ struct fieldstat_dynamic_instance * instance;
+ int thread_id;
+ int table_id;
+ unsigned int *out_column_ids;
+};
+
+void _worker_thread_multi_incrby(void *arg)
+{
+
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, "Traffic_bytes", 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], "security_rule_hits", 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ return;
+}
+void * worker_thread_multi_incrby(void *arg)
+{
+ _worker_thread_multi_incrby(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiIncrby)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 50000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_incrby, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((30 * n_loops), value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((31 * n_loops), value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((10 * n_loops), value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ((20 * n_loops), value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ(3, n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+void _worker_thread_multi_decrby(void *arg)
+{
+
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_COUNTER, "Traffic_bytes", 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], "security_rule_hits", 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ return;
}
+void * worker_thread_multi_decrby(void *arg)
+{
+ _worker_thread_multi_decrby(arg);
+ return NULL;
+}
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiDecrby)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 50000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_decrby, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((-30 * n_loops), value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((-31 * n_loops), value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((-10 * n_loops), value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ((-20 * n_loops), value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ(3, n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+void _worker_thread_multi_set(void *arg)
+{
+
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_GAUGE, "Active_sessions", 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_COUNTER, "Traffic_bytes", 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], "security_rule_hits", 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], "security_rule_hits", 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ return;
+}
+void * worker_thread_multi_set(void *arg)
+{
+ _worker_thread_multi_set(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiSet)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 50000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_set, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(30, value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(31, value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(10, value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ(20, value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ(3, n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+void _worker_thread_incrby_multi_metric(void *arg)
+{
+
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ char gauge_name[32];
+ char counter_name[32];
+ char table_column_name[32];
+ snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i);
+ snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i);
+ snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i);
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+}
+void * worker_thread_incrby_multi_metric(void *arg)
+{
+ _worker_thread_incrby_multi_metric(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceIncrbyMultiMetric)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 1000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_incrby_multi_metric, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(30, value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(31, value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(10, value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ(20, value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ((3 * n_loops), n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+void _worker_thread_decrby_multi_metric(void *arg)
+{
+
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ char gauge_name[32];
+ char counter_name[32];
+ char table_column_name[32];
+ snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i);
+ snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i);
+ snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i);
+ ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_GAUGE, gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_COUNTER, counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ return;
+}
+void * worker_thread_decrby_multi_metric(void *arg)
+{
+ _worker_thread_decrby_multi_metric(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceDecrbyMultiMetric)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 1000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_decrby_multi_metric, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(-30, value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(-31, value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(-10, value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ(-20, value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ((3 * n_loops), n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+
+void _worker_thread_set_multi_metric(void *arg)
+{
+
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ char gauge_name[32];
+ char counter_name[32];
+ char table_column_name[32];
+ snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i);
+ snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i);
+ snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i);
+ ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_GAUGE, gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_COUNTER, counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ return;
+}
+void * worker_thread_set_multi_metric(void *arg)
+{
+ _worker_thread_set_multi_metric(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceSetMultiMetric)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 1000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_set_multi_metric, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(30, value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(31, value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(10, value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ(20, value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ((3 * n_loops), n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+
+
+
+void _worker_thread_multi_incrby_multi_metric(void *arg)
+{
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ char gauge_name[32];
+ char counter_name[32];
+ char table_column_name[32];
+ snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i);
+ snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i);
+ snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i);
+
+ for(int j = 0; j < loops; j++)
+ {
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_GAUGE, (const char *)gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_incrby(instance, FIELD_TYPE_COUNTER, (const char *)counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[0], (const char *)table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_incrby(instance, table_id, out_column_ids[1], (const char *)table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ }
+ return;
+}
+void * worker_thread_multi_incrby_multi_metric(void *arg)
+{
+ _worker_thread_multi_incrby_multi_metric(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiIncrbyMultiMetric)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 1000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_incrby_multi_metric, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((30 * n_loops), value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((31 * n_loops), value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((10 * n_loops), value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ((20 * n_loops), value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ((3 * n_loops), n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+
+void _worker_thread_multi_decrby_multi_metric(void *arg)
+{
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ char gauge_name[32];
+ char counter_name[32];
+ char table_column_name[32];
+ snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i);
+ snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i);
+ snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i);
+
+ for(int j = 0; j < loops; j++)
+ {
+ ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_GAUGE, (const char *)gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_decrby(instance, FIELD_TYPE_COUNTER, (const char *)counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[0], (const char *)table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_decrby(instance, table_id, out_column_ids[1], (const char *)table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ }
+ return;
+}
+void * worker_thread_multi_decrby_multi_metric(void *arg)
+{
+ _worker_thread_multi_decrby_multi_metric(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiDecrbyMultiMetric)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 1000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_decrby_multi_metric, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((-1 * 30 * n_loops), value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((-1 * 31 * n_loops), value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ((-1 * 10 * n_loops), value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ((-1 * 20 * n_loops), value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ((3 * n_loops), n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
+
+void _worker_thread_multi_set_multi_metric(void *arg)
+{
+ struct thread_para *para = (struct thread_para*)arg;
+ int loops = para->loops;
+ int thread_id = para->thread_id;
+ int table_id = para->table_id;
+ unsigned int *out_column_ids = para->out_column_ids;
+
+ struct fieldstat_dynamic_instance *instance = para->instance;
+ int ret = 0;
+ struct fieldstat_tag tags[3];
+
+ int i = 0;
+
+ tags[0].key = "policy_id";
+ tags[0].value_int = 1;
+ tags[0].value_type = 0;
+
+ tags[1].key = "quanlity";
+ tags[1].value_double = 0.50;
+ tags[1].value_type = 1;
+
+ tags[2].key = "device_id";
+ tags[2].value_str = "test_device";
+ tags[2].value_type = 2;
+
+ for(i = 0; i < loops; i++)
+ {
+ char gauge_name[32];
+ char counter_name[32];
+ char table_column_name[32];
+ snprintf(gauge_name, sizeof(gauge_name), "Active_sessions_%d", i);
+ snprintf(counter_name, sizeof(gauge_name), "Traffic_bytes_%d", i);
+ snprintf(table_column_name, sizeof(gauge_name), "security_rule_hits_%d", i);
+
+ for(int j = 0; j < loops; j++)
+ {
+ ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_GAUGE, (const char *)gauge_name, 10, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_metric_value_set(instance, FIELD_TYPE_COUNTER, (const char *)counter_name, 20, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[0], (const char *)table_column_name, 30, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ ret = fieldstat_dynamic_table_metric_value_set(instance, table_id, out_column_ids[1], (const char *)table_column_name, 31, tags, sizeof(tags)/sizeof(tags[0]), thread_id);
+ EXPECT_EQ(0, ret);
+ }
+ }
+ return;
+}
+void * worker_thread_multi_set_multi_metric(void *arg)
+{
+ _worker_thread_multi_set_multi_metric(arg);
+ return NULL;
+}
+
+
+TEST(FeildStatDynamicAPI, FieldStatDynamicInstanceMultiSetMultiMetric)
+{
+ int ret = 0;
+ int n_thread = 64;
+ int n_loops = 1000;
+
+ struct dynamic_metric *dyn_metric, *tmp_dyn_metric;
+ struct dynamic_metric **head = NULL;
+ struct metric **metrics = NULL;
+ struct metric *metric = NULL;
+ long long value = 0;
+
+ const char *column_name[] = {"packages", "bytes"};
+ enum field_type column_type[] = {FIELD_TYPE_COUNTER, FIELD_TYPE_COUNTER};
+ unsigned int out_column_ids[2];
+ int table_id = -1;
+
+ struct thread_para para[n_thread];
+ pthread_t thread_ids[n_thread];
+
+
+ struct fieldstat_dynamic_instance *instance = fieldstat_dynamic_instance_new("firewall", n_thread);
+
+ table_id = fieldstat_register_dynamic_table(instance, "shaping", column_name, column_type, sizeof(column_name)/sizeof(column_name[0]), out_column_ids);
+
+ EXPECT_EQ(0, table_id);
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ para[i].loops = n_loops;
+ para[i].instance = instance;
+ para[i].thread_id = i;
+ para[i].table_id = table_id;
+ para[i].out_column_ids = out_column_ids;
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ ret = pthread_create(&(thread_ids[i]), NULL, worker_thread_multi_set_multi_metric, &(para[i]));
+ EXPECT_EQ(0, ret);
+ }
+
+ void *temp;
+ for(int i = 0; i < n_thread; i++)
+ {
+ pthread_join(thread_ids[i], (void**)&temp);
+ }
+
+ for(int i = 0; i < n_thread; i++)
+ {
+ int n_metrics = 0;
+ head = &instance->n_thread_dynamic_metric[i];
+ HASH_ITER(hh, *head, dyn_metric, tmp_dyn_metric)
+ {
+ metrics = dyn_metric->metrics;
+ metric = metrics[0];
+ if(metric->table)
+ {
+ metric = metrics[0];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(30, value);
+ metric = metrics[1];
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(31, value);
+ }
+ else
+ {
+ switch(metric->field_type)
+ {
+ case FIELD_TYPE_GAUGE:
+ value = get_metric_unit_val(metric, FS_CALC_SPEED, 0);
+ EXPECT_EQ(10, value);
+ break;
+ case FIELD_TYPE_COUNTER:
+ value = get_metric_unit_val(metric, FS_CALC_CURRENT, 0);
+ EXPECT_EQ(20, value);
+ break;
+ default:
+ FAIL() << "Field type should be in {counter, gauge}";
+ }
+ }
+ n_metrics++;
+ }
+ EXPECT_EQ((3 * n_loops), n_metrics);
+ }
+ fieldstat_dynamic_instance_free(instance);
+}
diff --git a/test/src/gtest_fieldstat.cpp b/test/src/gtest_fieldstat.cpp
index ee69475..2434539 100644
--- a/test/src/gtest_fieldstat.cpp
+++ b/test/src/gtest_fieldstat.cpp
@@ -7,25 +7,30 @@
extern struct prometheus_endpoint_instance g_prometheus_endpoint_instance;
-TEST(FeildStatAPI, CreateFieldStatInstance)
+TEST(FeildStatAPI, FieldStatInstanceNew)
{
struct fieldstat_instance *instance = fieldstat_instance_new("test");
EXPECT_NE(nullptr, instance);
EXPECT_STREQ("test", instance->name);
+ fieldstat_instance_free(instance);
}
+/*
TEST(FeildStatAPI, FieldStatEnablePrometheusEndpoint)
{
int ret_enable_prometheus_endpoint = 0;
int ret_req_prometheus_endpoint = 0;
+ const char *request_cmd = "curl -s -o /dev/null http://127.0.0.1:9020/metrics";
ret_enable_prometheus_endpoint = fieldstat_global_enable_prometheus_endpoint(9020, "/metrcis");
EXPECT_EQ(0, ret_enable_prometheus_endpoint);
-
- ret_req_prometheus_endpoint = system("curl -s -o /dev/null http://127.0.0.1:9020/metrics");
+ usleep(500 * 1000);
+ ret_req_prometheus_endpoint = system(request_cmd);
EXPECT_EQ(0,ret_req_prometheus_endpoint);
+ usleep(500 * 1000);
+ fieldstat_global_disable_prometheus_endpoint();
}
-
+*/
TEST(FeildStatAPI, FieldStatSetPrometheusOutput)
{
struct fieldstat_instance *instance = NULL;
@@ -35,7 +40,7 @@ TEST(FeildStatAPI, FieldStatSetPrometheusOutput)
instance = fieldstat_instance_new("test");
EXPECT_STREQ("test", instance->name);
- ret_enable_prometheus_endpoint = fieldstat_global_enable_prometheus_endpoint(9020, "/metrcis");
+ ret_enable_prometheus_endpoint = fieldstat_global_enable_prometheus_endpoint(9020, "/metrics");
EXPECT_EQ(0, ret_enable_prometheus_endpoint);
ret_set_prometheus_output = fieldstat_enable_prometheus_output(instance);
@@ -44,8 +49,13 @@ TEST(FeildStatAPI, FieldStatSetPrometheusOutput)
EXPECT_EQ(1, g_prometheus_endpoint_instance.running);
EXPECT_EQ(instance, g_prometheus_endpoint_instance.fs_instance[0]);
EXPECT_EQ(1, g_prometheus_endpoint_instance.fs_instance_cnt);
+
+ usleep(500 * 1000);
+ fieldstat_global_disable_prometheus_endpoint();
+ fieldstat_instance_free(instance);
}
+
TEST(FeildStatAPI, FieldStatSetLineProtocolServer)
{
struct fieldstat_instance *instance = NULL;
@@ -59,6 +69,7 @@ TEST(FeildStatAPI, FieldStatSetLineProtocolServer)
EXPECT_EQ(0, ret_set_line_protocol_server);
EXPECT_EQ(1, instance->line_protocol_output_enable);
EXPECT_NE(-1, instance->line_protocol_socket);
+ fieldstat_instance_free(instance);
}
TEST(FeildStatAPI, FieldStatSetLocalOutput)
@@ -74,10 +85,9 @@ TEST(FeildStatAPI, FieldStatSetLocalOutput)
EXPECT_STREQ("test.fs", instance->local_output_filename);
EXPECT_STREQ("default", instance->local_output_format);
EXPECT_EQ(1, instance->local_output_enable);
+ fieldstat_instance_free(instance);
}
-int fieldstat_disable_background_thread(struct fieldstat_instance *instance);
-
TEST(FeildStatAPI, FieldStatBackgroundThreadDisable)
{
struct fieldstat_instance *instance = NULL;
@@ -88,6 +98,7 @@ TEST(FeildStatAPI, FieldStatBackgroundThreadDisable)
ret_background_thread_disable = fieldstat_disable_background_thread(instance);
EXPECT_EQ(0, ret_background_thread_disable);
EXPECT_EQ(1, instance->background_thread_disable);
+ fieldstat_instance_free(instance);
}
TEST(FeildStatAPI, FieldStatSetOutputInterval)
@@ -101,6 +112,19 @@ TEST(FeildStatAPI, FieldStatSetOutputInterval)
ret_set_output_interval = fieldstat_set_output_interval(instance, 1);
EXPECT_EQ(0, ret_set_output_interval);
EXPECT_EQ(1, instance->output_interval_ms);
+ fieldstat_instance_free(instance);
+}
+
+TEST(FeildStatAPI, FieldStatInstanceStart)
+{
+ struct fieldstat_instance *instance = NULL;
+
+ instance = fieldstat_instance_new("test");
+ EXPECT_STREQ("test", instance->name);
+
+ fieldstat_instance_start(instance);
+ usleep(500 * 1000);
+ fieldstat_instance_free(instance);
}
TEST(FeildStatAPI, FieldStatRegister)
@@ -137,6 +161,7 @@ TEST(FeildStatAPI, FieldStatRegister)
EXPECT_EQ(2, metric_id);
EXPECT_EQ(3, instance->metric_cnt);
EXPECT_NE(nullptr, in_block_metric[2]);
+ fieldstat_instance_free(instance);
}
TEST(FieldStatAPI, FieldStatRegisterTable)
@@ -164,6 +189,7 @@ TEST(FieldStatAPI, FieldStatRegisterTable)
EXPECT_EQ(0, table->line_cnt);
EXPECT_EQ(nullptr, table->line_block[0]);
+
table_id = fieldstat_register_table(instance, sc_table_name, sc_column_name, sc_column_type, sizeof(sc_column_name)/sizeof(sc_column_name[0]));
EXPECT_EQ(1, table_id);
@@ -172,6 +198,8 @@ TEST(FieldStatAPI, FieldStatRegisterTable)
EXPECT_EQ(4, table->column_cnt);
EXPECT_EQ(0, table->line_cnt);
EXPECT_EQ(nullptr, table->line_block[0]);
+
+ fieldstat_instance_free(instance);
}
@@ -179,7 +207,6 @@ TEST(FieldStatAPI, FieldStatRegisterTableMetrics)
{
struct fieldstat_instance * instance = NULL;
int table_id = -1;
- struct table_metric *table = NULL;
const char *sc_column_name[] = {"sent_pkts", "send_bytes", "recv_pkts", "recv_bytes"};
enum field_type sc_column_type[] = {FIELD_TYPE_COUNTER,FIELD_TYPE_COUNTER,FIELD_TYPE_COUNTER,FIELD_TYPE_COUNTER};
@@ -190,7 +217,8 @@ TEST(FieldStatAPI, FieldStatRegisterTableMetrics)
EXPECT_STREQ("test", instance->name);
table_id = fieldstat_register_table(instance, sc_table_name, sc_column_name, sc_column_type, sizeof(sc_column_name)/sizeof(sc_column_name[0]));
-
+ EXPECT_EQ(0, table_id);
+ fieldstat_instance_free(instance);
}