From a4feec4dac7289ec89476abfd37dbb7ddb0a4e71 Mon Sep 17 00:00:00 2001 From: fengzero Date: Sat, 2 Apr 2022 10:06:40 +0000 Subject: [PATCH] improve plugin/node/group/tag storage --- CMakeLists.txt | 5 +- include/neuron/group.h | 0 include/neuron/node.h | 0 include/neuron/plugin.h | 0 include/neuron/tag.h | 76 ++++++++++++ include/neuron/tag_table.h | 49 ++++++++ include/neuron/type.h | 63 ++++++++++ include/{ => neuron}/utils/uthash.h | 0 src/base/tag_table.c | 177 ++++++++++++++++++++++++++++ 9 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 include/neuron/group.h create mode 100644 include/neuron/node.h create mode 100644 include/neuron/plugin.h create mode 100644 include/neuron/tag.h create mode 100644 include/neuron/tag_table.h create mode 100644 include/neuron/type.h rename include/{ => neuron}/utils/uthash.h (100%) create mode 100644 src/base/tag_table.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 07e0d725..8834c192 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS) CACHE INTERNAL "No dev warnings") endif() -configure_file(extern/uthash/include/uthash.h ${CMAKE_SOURCE_DIR}/include/utils/uthash.h) +configure_file(extern/uthash/include/uthash.h ${CMAKE_SOURCE_DIR}/include/neuron/utils/uthash.h) add_subdirectory(extern/vector) set_property(TARGET vector-static PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -133,6 +133,7 @@ target_link_libraries(neuron ssl crypto ${CMAKE_THREAD_LIBS_INIT}) # define neuron base library set(NEURON_BASE_SOURCES src/types.c + src/base/tag_table.c src/base/neu_tag.c src/base/neu_datatag_table.c src/base/neu_tag_group_config.c @@ -171,7 +172,7 @@ else() src/connection/mqtt_c_client.c) endif() -set(NEURON_BASE_INCLUDE_DIRECTORIES include src) +set(NEURON_BASE_INCLUDE_DIRECTORIES include include/neuron src) add_library(neuron-base SHARED) target_sources(neuron-base PRIVATE ${NEURON_BASE_SOURCES} ${NEURON_SRC_PARSE} ${NEURON_SRC_SCHEMA}) target_include_directories(neuron-base diff --git a/include/neuron/group.h b/include/neuron/group.h new file mode 100644 index 00000000..e69de29b diff --git a/include/neuron/node.h b/include/neuron/node.h new file mode 100644 index 00000000..e69de29b diff --git a/include/neuron/plugin.h b/include/neuron/plugin.h new file mode 100644 index 00000000..e69de29b diff --git a/include/neuron/tag.h b/include/neuron/tag.h new file mode 100644 index 00000000..b715282c --- /dev/null +++ b/include/neuron/tag.h @@ -0,0 +1,76 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +config_ **/ + +#ifndef _NEU_TAG_H_ +#define _NEU_TAG_H_ + +#include "type.h" + +typedef enum { + NEU_TAG_ENDIAN_L16 = 0, // #L + NEU_TAG_ENDIAN_B16 = 1, // #B + NEU_TAG_ENDIAN_LL32 = 2, // #LL + NEU_TAG_ENDIAN_LB32 = 3, // #LB + NEU_TAG_ENDIAN_BB32 = 4, // #BB + NEU_TAG_ENDIAN_BL32 = 5, // #BL +} neu_tag_endian_e; + +typedef enum { + NEU_TAG_STRING_TYPE_H = 0, // high-to-low endian + NEU_TAG_STRING_TYPE_L = 1, // low-to-high endian + NEU_TAG_STRING_TYPE_D = 2, // a high byte is stored in an int16 + NEU_TAG_STRING_TYPE_E = 3, // a low byte is stored in an int16 +} neu_tag_string_type_e; + +typedef union { + struct { + neu_tag_endian_e endian; + } value16; + struct { + neu_tag_endian_e endian; + } value32; + struct { + uint16_t length; + neu_tag_string_type_e type; + } string; + + struct { + uint8_t bit; + } bit; +} neu_tag_addr_option_u; + +typedef enum { + NEU_TAG_ATTR_READ = 1, + NEU_TAG_ATTR_WRITE = 2, + NEU_TAG_ATTR_SUBSCRIBE = 4, +} neu_tag_attr_e; + +#define NEU_TAG_NAME_LEN 64 +#define NEU_TAG_ADDRESS_LEN 64 + +typedef struct { + char name[NEU_TAG_NAME_LEN]; + char address[NEU_TAG_ADDRESS_LEN]; + + neu_type_e type; + neu_tag_attr_e attribute; + neu_tag_addr_option_u option; +} neu_tag_t; + +#endif \ No newline at end of file diff --git a/include/neuron/tag_table.h b/include/neuron/tag_table.h new file mode 100644 index 00000000..4e159162 --- /dev/null +++ b/include/neuron/tag_table.h @@ -0,0 +1,49 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + **/ + +#ifndef _NEU_TAG_TABLE_H_ +#define _NEU_TAG_TABLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tag.h" + +typedef struct neu_tag_table neu_tag_table_t; + +neu_tag_table_t *neu_tag_table_create(void); +void neu_tag_table_destory(neu_tag_table_t *tbl); +uint32_t neu_tag_table_size(neu_tag_table_t *tbl); +neu_tag_t * neu_tag_table_get(neu_tag_table_t *tbl, const char *name); +int neu_tag_table_add(neu_tag_table_t *tbl, neu_tag_t *tag); +int neu_tag_table_update(neu_tag_table_t *tbl, neu_tag_t *tag); +int neu_tag_table_delete(neu_tag_table_t *tbl, const char *name); + +typedef void (*neu_tag_table_foreach_fn)(void *arg, neu_tag_t *tag); +void neu_tag_table_foreach(neu_tag_table_t *tbl, void *arg, + neu_tag_table_foreach_fn fn); +int64_t neu_tag_table_change_foreach(neu_tag_table_t *tbl, int64_t timestamp, + void *arg, neu_tag_table_foreach_fn fn); + +#ifdef __cplusplus +} +#endif + +#endif //__DATATAG_TABLE_H__ diff --git a/include/neuron/type.h b/include/neuron/type.h new file mode 100644 index 00000000..314617ce --- /dev/null +++ b/include/neuron/type.h @@ -0,0 +1,63 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + **/ + +#ifndef _NEU_TYPE_H_ +#define _NEU_TYPE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef enum { + NEU_TYPE_INT8 = 1, + NEU_TYPE_UINT8 = 2, + NEU_TYPE_INT16 = 3, + NEU_TYPE_UINT16 = 4, + NEU_TYPE_INT32 = 5, + NEU_TYPE_UINT32 = 6, + NEU_TYPE_INT64 = 7, + NEU_TYPE_UINT64 = 8, + NEU_TYPE_FLOAT = 9, + NEU_TYPE_DOUBLE = 10, + NEU_TYPE_BIT = 11, + NEU_TYPE_BOOL = 12, + NEU_TYPE_STRING = 13, +} neu_type_e; + +typedef union { + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + int64_t i64; + uint64_t u64; + float f32; + double d64; + char * str; +} neu_value_u; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/utils/uthash.h b/include/neuron/utils/uthash.h similarity index 100% rename from include/utils/uthash.h rename to include/neuron/utils/uthash.h diff --git a/src/base/tag_table.c b/src/base/tag_table.c new file mode 100644 index 00000000..0c38a969 --- /dev/null +++ b/src/base/tag_table.c @@ -0,0 +1,177 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2021 EMQ Technologies Co., Ltd All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + **/ + +#include +#include +#include + +#include "utils/uthash.h" + +#include "tag_table.h" + +struct tag_elem { + neu_tag_t tag; + + char name[NEU_TAG_NAME_LEN]; + UT_hash_handle hh; +}; + +struct neu_tag_table { + pthread_mutex_t mtx; + int64_t timestamp; + + struct tag_elem *tags; +}; + +static void update_timestamp(neu_tag_table_t *tbl) +{ + struct timeval tv = { 0 }; + + gettimeofday(&tv, NULL); + + tbl->timestamp = tv.tv_sec * 1000 * 1000 + tv.tv_usec; +} + +neu_tag_table_t *neu_tag_table_create(void) +{ + neu_tag_table_t *table = calloc(1, sizeof(neu_tag_table_t)); + + pthread_mutex_init(&table->mtx, NULL); + + return table; +} + +void neu_tag_table_destory(neu_tag_table_t *tbl) +{ + pthread_mutex_destroy(&tbl->mtx); + + free(tbl); +} + +uint32_t neu_tag_table_size(neu_tag_table_t *tbl) +{ + uint32_t size = 0; + + pthread_mutex_lock(&tbl->mtx); + size = HASH_COUNT(tbl->tags); + pthread_mutex_unlock(&tbl->mtx); + + return size; +} + +neu_tag_t *neu_tag_table_get(neu_tag_table_t *tbl, const char *name) +{ + struct tag_elem *elem = NULL; + neu_tag_t * tag = NULL; + + pthread_mutex_lock(&tbl->mtx); + HASH_FIND_STR(tbl->tags, name, elem); + if (elem != NULL) { + tag = calloc(1, sizeof(neu_tag_t)); + memcpy(tag, &elem->tag, sizeof(neu_tag_t)); + } + pthread_mutex_unlock(&tbl->mtx); + + return tag; +} + +int neu_tag_table_add(neu_tag_table_t *tbl, neu_tag_t *tag) +{ + int ret = -1; + struct tag_elem *elem = NULL; + + pthread_mutex_lock(&tbl->mtx); + HASH_FIND_STR(tbl->tags, tag->name, elem); + if (elem == NULL) { + elem = calloc(1, sizeof(struct tag_elem)); + + elem->tag = *tag; + strncpy(elem->name, tag->name, strlen(tag->name)); + HASH_ADD_STR(tbl->tags, name, elem); + + update_timestamp(tbl); + ret = 0; + } + pthread_mutex_unlock(&tbl->mtx); + + return ret; +} + +int neu_tag_table_update(neu_tag_table_t *tbl, neu_tag_t *tag) +{ + int ret = -1; + struct tag_elem *elem = NULL; + + pthread_mutex_lock(&tbl->mtx); + HASH_FIND_STR(tbl->tags, tag->name, elem); + if (elem != NULL) { + elem->tag = *tag; + + update_timestamp(tbl); + ret = 0; + } + pthread_mutex_unlock(&tbl->mtx); + + return ret; +} + +int neu_tag_table_delete(neu_tag_table_t *tbl, const char *name) +{ + int ret = -1; + struct tag_elem *elem = NULL; + + pthread_mutex_lock(&tbl->mtx); + HASH_FIND_STR(tbl->tags, name, elem); + if (elem != NULL) { + HASH_DEL(tbl->tags, elem); + + update_timestamp(tbl); + ret = 0; + } + pthread_mutex_unlock(&tbl->mtx); + + return ret; +} +void neu_tag_table_foreach(neu_tag_table_t *tbl, void *arg, + neu_tag_table_foreach_fn fn) +{ + struct tag_elem *elem = NULL; + + pthread_mutex_lock(&tbl->mtx); + for (elem = tbl->tags; elem != NULL; elem = elem->hh.next) { + fn(arg, &elem->tag); + } + pthread_mutex_unlock(&tbl->mtx); +} + +int64_t neu_tag_table_change_foreach(neu_tag_table_t *tbl, int64_t timestamp, + void *arg, neu_tag_table_foreach_fn fn) +{ + struct tag_elem *elem = NULL; + + pthread_mutex_lock(&tbl->mtx); + if (timestamp != tbl->timestamp) { + for (elem = tbl->tags; elem != NULL; elem = elem->hh.next) { + fn(arg, &elem->tag); + } + } + pthread_mutex_unlock(&tbl->mtx); + + return tbl->timestamp; +} \ No newline at end of file