diff --git a/include/neuron/msg.h b/include/neuron/msg.h index 88e9ad8b7..ead132e21 100644 --- a/include/neuron/msg.h +++ b/include/neuron/msg.h @@ -893,6 +893,11 @@ static inline void neu_trans_data_free(neu_reqresp_trans_data_t *data) { if (tag_value->value.type == NEU_TYPE_PTR) { free(tag_value->value.value.ptr.ptr); + } else if (tag_value->value.type == NEU_TYPE_ARRAY_STRING) { + for (size_t i = 0; i < tag_value->value.value.strs.length; + ++i) { + free(tag_value->value.value.strs.strs[i]); + } } } utarray_free(data->tags); @@ -1087,6 +1092,12 @@ static inline void neu_tag_value_to_json(neu_resp_tag_value_meta_t *tag_value, tag_json->value.val_array_double.f64s = tag_value->value.value.f64s.f64s; break; + case NEU_TYPE_ARRAY_STRING: + tag_json->t = NEU_JSON_ARRAY_STR; + tag_json->value.val_array_str.length = + tag_value->value.value.strs.length; + tag_json->value.val_array_str.p_strs = tag_value->value.value.strs.strs; + break; case NEU_TYPE_CUSTOM: tag_json->t = NEU_JSON_OBJECT; tag_json->value.val_object = tag_value->value.value.json; @@ -1289,6 +1300,12 @@ neu_tag_value_to_json_paginate(neu_resp_tag_value_meta_paginate_t *tag_value, tag_json->value.val_array_double.f64s = tag_value->value.value.f64s.f64s; break; + case NEU_TYPE_ARRAY_STRING: + tag_json->t = NEU_JSON_ARRAY_STR; + tag_json->value.val_array_str.length = + tag_value->value.value.strs.length; + tag_json->value.val_array_str.p_strs = tag_value->value.value.strs.strs; + break; case NEU_TYPE_CUSTOM: tag_json->t = NEU_JSON_OBJECT; tag_json->value.val_object = tag_value->value.value.json; diff --git a/include/neuron/type.h b/include/neuron/type.h index 826b966f2..34c630b46 100644 --- a/include/neuron/type.h +++ b/include/neuron/type.h @@ -67,6 +67,7 @@ typedef enum { NEU_TYPE_ARRAY_FLOAT = 31, NEU_TYPE_ARRAY_DOUBLE = 32, NEU_TYPE_ARRAY_BOOL = 33, + NEU_TYPE_ARRAY_STRING = 34, NEU_TYPE_CUSTOM = 40, } neu_type_e; @@ -139,6 +140,8 @@ inline static const char *neu_type_string(neu_type_e type) return "NEU_TYPE_ARRAY_FLOAT"; case NEU_TYPE_ARRAY_BOOL: return "NEU_TYPE_ARRAY_BOOL"; + case NEU_TYPE_ARRAY_STRING: + return "NEU_TYPE_ARRAY_STRING"; case NEU_TYPE_CUSTOM: return "NEU_TYPE_CUSTOM"; } @@ -214,6 +217,11 @@ typedef struct { uint8_t length; } neu_value_array_bool_t; +typedef struct { + char * strs[NEU_VALUE_SIZE]; + uint8_t length; +} neu_value_array_string_t; + typedef union { bool boolean; int8_t i8; @@ -241,6 +249,7 @@ typedef union { neu_value_array_float_t f32s; neu_value_array_double_t f64s; neu_value_array_bool_t bools; + neu_value_array_string_t strs; } neu_value_u; static inline char *neu_value_str(neu_type_e type, neu_value_u value) diff --git a/plugins/mqtt/mqtt_handle.c b/plugins/mqtt/mqtt_handle.c index 77a9308b0..46ef075a7 100644 --- a/plugins/mqtt/mqtt_handle.c +++ b/plugins/mqtt/mqtt_handle.c @@ -293,6 +293,13 @@ static int json_value_to_tag_value(union neu_json_value *req, value->value.i64s.i64s[i] = req->val_array_int64.i64s[i]; } break; + case NEU_JSON_ARRAY_STR: + value->type = NEU_TYPE_ARRAY_STRING; + value->value.strs.length = req->val_array_str.length; + for (int i = 0; i < req->val_array_str.length; i++) { + value->value.strs.strs[i] = req->val_array_str.p_strs[i]; + } + break; case NEU_JSON_OBJECT: value->type = NEU_TYPE_CUSTOM; value->value.json = req->val_object; diff --git a/plugins/restful/rw_handle.c b/plugins/restful/rw_handle.c index 89c8b60ed..dd0e97425 100644 --- a/plugins/restful/rw_handle.c +++ b/plugins/restful/rw_handle.c @@ -363,6 +363,14 @@ void handle_write(nng_aio *aio) req->value.val_array_bool.bools[i]; } break; + case NEU_JSON_ARRAY_STR: + cmd.value.type = NEU_TYPE_ARRAY_STRING; + cmd.value.value.strs.length = req->value.val_array_str.length; + for (int i = 0; i < req->value.val_array_str.length; i++) { + cmd.value.value.strs.strs[i] = + req->value.val_array_str.p_strs[i]; + } + break; case NEU_JSON_OBJECT: cmd.value.type = NEU_TYPE_CUSTOM; cmd.value.value.json = req->value.val_object; @@ -564,6 +572,16 @@ void handle_write_tags(nng_aio *aio) req->tags[i].value.val_array_bool.bools[k]; } break; + case NEU_JSON_ARRAY_STR: + cmd.tags[i].value.type = NEU_TYPE_ARRAY_STRING; + cmd.tags[i].value.value.strs.length = + req->tags[i].value.val_array_str.length; + for (int k = 0; k < req->tags[i].value.val_array_str.length; + k++) { + cmd.tags[i].value.value.strs.strs[k] = + req->tags[i].value.val_array_str.p_strs[k]; + } + break; case NEU_JSON_OBJECT: cmd.tags[i].value.type = NEU_TYPE_CUSTOM; cmd.tags[i].value.value.json = @@ -802,6 +820,13 @@ void handle_read_resp(nng_aio *aio, neu_resp_read_group_t *resp) if (api_res.tags[i].n_meta > 0) { free(api_res.tags[i].metas); } + + if (api_res.tags[i].t == NEU_JSON_ARRAY_STR) { + for (int j = 0; j < api_res.tags[i].value.val_array_str.length; + j++) { + free(api_res.tags[i].value.val_array_str.p_strs[j]); + } + } } neu_http_ok(aio, result); free(api_res.tags); @@ -942,6 +967,13 @@ void handle_read_paginate_resp(nng_aio * aio, if (api_res.tags[i].n_meta > 0) { free(api_res.tags[i].metas); } + + if (api_res.tags[i].t == NEU_JSON_ARRAY_STR) { + for (int j = 0; j < api_res.tags[i].value.val_array_str.length; + j++) { + free(api_res.tags[i].value.val_array_str.p_strs[j]); + } + } } neu_http_ok(aio, result); free(api_res.tags); diff --git a/src/adapter/driver/cache.c b/src/adapter/driver/cache.c index cfe79ec4c..6e8afe4d7 100644 --- a/src/adapter/driver/cache.c +++ b/src/adapter/driver/cache.c @@ -104,6 +104,11 @@ void neu_driver_cache_destroy(neu_driver_cache_t *cache) json_decref(elem->value.value.json); elem->value.value.json = NULL; } + } else if (elem->value.type == NEU_TYPE_ARRAY_STRING) { + for (int i = 0; i < elem->value.value.strs.length; i++) { + free(elem->value.value.strs.strs[i]); + elem->value.value.strs.strs[i] = NULL; + } } free(elem); @@ -399,6 +404,18 @@ void neu_driver_cache_update_change(neu_driver_cache_t *cache, } } break; + case NEU_TYPE_ARRAY_STRING: + if (elem->value_old.value.strs.length != + value.value.strs.length) { + elem->changed = true; + } else { + if (memcmp(elem->value_old.value.strs.strs, + value.value.strs.strs, + value.value.strs.length * sizeof(char *)) != 0) { + elem->changed = true; + } + } + break; case NEU_TYPE_CUSTOM: { if (json_equal(elem->value_old.value.json, value.value.json) != 0) { @@ -602,6 +619,17 @@ void neu_driver_cache_update_change(neu_driver_cache_t *cache, } } break; + case NEU_TYPE_ARRAY_STRING: + if (elem->value.value.strs.length != value.value.strs.length) { + elem->changed = true; + } else { + if (memcmp(elem->value.value.strs.strs, + value.value.strs.strs, + value.value.strs.length * sizeof(char *)) != 0) { + elem->changed = true; + } + } + break; case NEU_TYPE_PTR: { if (elem->value.value.ptr.length != value.value.ptr.length) { elem->changed = true; @@ -668,14 +696,43 @@ void neu_driver_cache_update_change(neu_driver_cache_t *cache, elem->value.value.ptr.ptr = calloc(1, value.value.ptr.length); memcpy(elem->value.value.ptr.ptr, value.value.ptr.ptr, value.value.ptr.length); - } else if (value.type == NEU_TYPE_CUSTOM || - value.type == NEU_TYPE_ERROR) { - if (elem->value.type == NEU_TYPE_CUSTOM && - elem->value.value.json != NULL) { - json_decref(elem->value.value.json); - elem->value.value.json = NULL; + } else if (value.type == NEU_TYPE_CUSTOM) { + if (elem->value.type == NEU_TYPE_CUSTOM) { + if (elem->value.value.json != NULL) { + json_decref(elem->value.value.json); + elem->value.value.json = NULL; + } } + elem->value.value.json = value.value.json; + + } else if (value.type == NEU_TYPE_ARRAY_STRING) { + if (elem->value.type == NEU_TYPE_ARRAY_STRING) { + for (int i = 0; i < elem->value.value.strs.length; i++) { + free(elem->value.value.strs.strs[i]); + elem->value.value.strs.strs[i] = NULL; + } + } + elem->value.value.strs.length = value.value.strs.length; + for (int i = 0; i < value.value.strs.length; i++) { + elem->value.value.strs.strs[i] = value.value.strs.strs[i]; + } + + } else if (value.type == NEU_TYPE_ERROR) { + if (elem->value.type == NEU_TYPE_CUSTOM) { + if (elem->value.value.json != NULL) { + json_decref(elem->value.value.json); + elem->value.value.json = NULL; + } + } + + if (elem->value.type == NEU_TYPE_ARRAY_STRING) { + for (int i = 0; i < elem->value.value.strs.length; i++) { + free(elem->value.value.strs.strs[i]); + elem->value.value.strs.strs[i] = NULL; + } + } + elem->value.value = value.value; } else { elem->value.value = value.value; } @@ -814,6 +871,13 @@ int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group, memcpy(value->value.value.f64s.f64s, elem->value.value.f64s.f64s, elem->value.value.f64s.length * sizeof(double)); break; + case NEU_TYPE_ARRAY_STRING: + value->value.value.strs.length = elem->value.value.strs.length; + for (int i = 0; i < elem->value.value.strs.length; i++) { + value->value.value.strs.strs[i] = + strdup(elem->value.value.strs.strs[i]); + } + break; case NEU_TYPE_PTR: value->value.value.ptr.length = elem->value.value.ptr.length; value->value.value.ptr.type = elem->value.value.ptr.type; @@ -958,6 +1022,13 @@ int neu_driver_cache_meta_get_changed(neu_driver_cache_t *cache, memcpy(value->value.value.f64s.f64s, elem->value.value.f64s.f64s, elem->value.value.f64s.length * sizeof(double)); break; + case NEU_TYPE_ARRAY_STRING: + value->value.value.strs.length = elem->value.value.strs.length; + for (int i = 0; i < elem->value.value.strs.length; i++) { + value->value.value.strs.strs[i] = + strdup(elem->value.value.strs.strs[i]); + } + break; case NEU_TYPE_PTR: value->value.value.ptr.length = elem->value.value.ptr.length; value->value.value.ptr.type = elem->value.value.ptr.type; @@ -1010,6 +1081,11 @@ void neu_driver_cache_del(neu_driver_cache_t *cache, const char *group, json_decref(elem->value.value.json); elem->value.value.json = NULL; } + } else if (elem->value.type == NEU_TYPE_ARRAY_STRING) { + for (int i = 0; i < elem->value.value.strs.length; i++) { + free(elem->value.value.strs.strs[i]); + elem->value.value.strs.strs[i] = NULL; + } } free(elem); } diff --git a/src/adapter/driver/driver.c b/src/adapter/driver/driver.c index 20072e86c..72616dbc9 100644 --- a/src/adapter/driver/driver.c +++ b/src/adapter/driver/driver.c @@ -751,6 +751,7 @@ static void fix_value(neu_datatag_t *tag, neu_type_e value_type, case NEU_TYPE_ARRAY_INT64: case NEU_TYPE_ARRAY_CHAR: case NEU_TYPE_ARRAY_BOOL: + case NEU_TYPE_ARRAY_STRING: case NEU_TYPE_CUSTOM: break; case NEU_TYPE_BIT: @@ -2184,6 +2185,11 @@ static int report_callback(void *usr_data) free(tag_value->value.value.ptr.ptr); } else if (tag_value->value.type == NEU_TYPE_CUSTOM) { json_decref(tag_value->value.value.json); + } else if (tag_value->value.type == NEU_TYPE_ARRAY_STRING) { + for (size_t i = 0; i < tag_value->value.value.strs.length; + ++i) { + free(tag_value->value.value.strs.strs[i]); + } } } utarray_free(data->tags); @@ -2487,6 +2493,10 @@ static void read_report_group(int64_t timestamp, int64_t timeout, free(value.value.value.ptr.ptr); } else if (value.value.type == NEU_TYPE_CUSTOM) { json_decref(value.value.value.json); + } else if (value.value.type == NEU_TYPE_ARRAY_STRING) { + for (size_t i = 0; i < value.value.value.strs.length; ++i) { + free(value.value.value.strs.strs[i]); + } } tag_value.value.type = NEU_TYPE_ERROR; tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED; @@ -2651,6 +2661,12 @@ static void read_group(int64_t timestamp, int64_t timeout, (timestamp - value.timestamp) > timeout) { if (value.value.type == NEU_TYPE_PTR) { free(value.value.value.ptr.ptr); + } else if (value.value.type == NEU_TYPE_CUSTOM) { + json_decref(value.value.value.json); + } else if (value.value.type == NEU_TYPE_ARRAY_STRING) { + for (size_t i = 0; i < value.value.value.strs.length; ++i) { + free(value.value.value.strs.strs[i]); + } } tag_value.value.type = NEU_TYPE_ERROR; tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED; @@ -2829,6 +2845,12 @@ static void read_group_paginate(int64_t timestamp, int64_t timeout, (timestamp - value.timestamp) > timeout) { if (value.value.type == NEU_TYPE_PTR) { free(value.value.value.ptr.ptr); + } else if (value.value.type == NEU_TYPE_CUSTOM) { + json_decref(value.value.value.json); + } else if (value.value.type == NEU_TYPE_ARRAY_STRING) { + for (size_t i = 0; i < value.value.value.strs.length; ++i) { + free(value.value.value.strs.strs[i]); + } } tag_value.value.type = NEU_TYPE_ERROR; tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED; diff --git a/src/utils/json.c b/src/utils/json.c index b402ba8b6..215ab8a21 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -305,6 +305,17 @@ static json_t *encode_object(json_t *object, neu_json_elem_t ele) json_object_set_new(ob, ele.name, array); break; } + case NEU_JSON_ARRAY_STR: { + void *array = json_array(); + + for (int i = 0; i < ele.v.val_array_str.length; i++) { + json_array_append_new(array, + json_string(ele.v.val_array_str.p_strs[i])); + } + + json_object_set_new(ob, ele.name, array); + break; + } case NEU_JSON_OBJECT: json_object_set_new(ob, ele.name, ele.v.val_object); break; @@ -668,6 +679,9 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) } case NEU_JSON_OBJECT: ele->v.val_object = ob; + if (ele->name == NULL) { + json_incref(ele->v.val_object); + } break; default: ele->ok = false; diff --git a/tests/ft/neuron/config.py b/tests/ft/neuron/config.py index 484cb18fa..ca95adb49 100644 --- a/tests/ft/neuron/config.py +++ b/tests/ft/neuron/config.py @@ -55,6 +55,7 @@ NEU_TYPE_ARRAY_FLOAT = 31 NEU_TYPE_ARRAY_DOUBLE = 32 NEU_TYPE_ARRAY_BOOL = 33 +NEU_TYPE_ARRAY_STRING = 34 NEU_TYPE_CUSTOM = 40 NEU_BAUD_115200 = 0