diff options
author | Andrew Moss <1043609+amoss@users.noreply.github.com> | 2019-12-16 15:12:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-12-16 15:12:00 +0100 |
commit | c8c72f18a6a8fd09d3b6284e49525396b24e8395 (patch) | |
tree | 5b9aeaea7d72e1d1029d45f67c0a5f130ecc2f80 /libnetdata | |
parent | c4bb3d2642ab34e6aca912b22e55aed52f84e974 (diff) |
Labels issues (#7515)
Initial work on host labels from the dedicated branch. Includes work for issues #7096, #7400, #7411, #7369, #7410, #7458, #7459, #7412 and #7408 by @vlvkobal, @thiagoftsm, @cakrit and @amoss.
Diffstat (limited to 'libnetdata')
-rw-r--r-- | libnetdata/config/appconfig.c | 81 | ||||
-rw-r--r-- | libnetdata/config/appconfig.h | 53 | ||||
-rw-r--r-- | libnetdata/inlined.h | 14 | ||||
-rw-r--r-- | libnetdata/simple_pattern/simple_pattern.c | 23 | ||||
-rw-r--r-- | libnetdata/simple_pattern/simple_pattern.h | 3 |
5 files changed, 123 insertions, 51 deletions
diff --git a/libnetdata/config/appconfig.c b/libnetdata/config/appconfig.c index 6ec5806fb4..31225336ee 100644 --- a/libnetdata/config/appconfig.c +++ b/libnetdata/config/appconfig.c @@ -2,46 +2,6 @@ #include "../libnetdata.h" -#define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2) - -// ---------------------------------------------------------------------------- -// definitions - -#define CONFIG_VALUE_LOADED 0x01 // has been loaded from the config -#define CONFIG_VALUE_USED 0x02 // has been accessed from the program -#define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value or the internal default value -#define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default - -struct config_option { - avl avl; // the index entry of this entry - this has to be first! - - uint8_t flags; - uint32_t hash; // a simple hash to speed up searching - // we first compare hashes, and only if the hashes are equal we do string comparisons - - char *name; - char *value; - - struct config_option *next; // config->mutex protects just this -}; - -struct section { - avl avl; // the index entry of this section - this has to be first! - - uint32_t hash; // a simple hash to speed up searching - // we first compare hashes, and only if the hashes are equal we do string comparisons - - char *name; - - struct section *next; // gloabl config_mutex protects just this - - struct config_option *values; - avl_tree_lock values_index; - - netdata_mutex_t mutex; // this locks only the writers, to ensure atomic updates - // readers are protected using the rwlock in avl_tree_lock -}; - /* * @Input: * Connector / instance to add to an internal structure @@ -129,19 +89,19 @@ int is_valid_connector(char *type, int check_reserved) // ---------------------------------------------------------------------------- // locking -static inline void appconfig_wrlock(struct config *root) { +inline void appconfig_wrlock(struct config *root) { netdata_mutex_lock(&root->mutex); } -static inline void appconfig_unlock(struct config *root) { +inline void appconfig_unlock(struct config *root) { netdata_mutex_unlock(&root->mutex); } -static inline void config_section_wrlock(struct section *co) { +inline void config_section_wrlock(struct section *co) { netdata_mutex_lock(&co->mutex); } -static inline void config_section_unlock(struct section *co) { +inline void config_section_unlock(struct section *co) { netdata_mutex_unlock(&co->mutex); } @@ -520,7 +480,7 @@ int appconfig_get_duration(struct config *root, const char *section, const char // ---------------------------------------------------------------------------- // config load/save -int appconfig_load(struct config *root, char *filename, int overwrite_used) +int appconfig_load(struct config *root, char *filename, int overwrite_used, const char *section_name) { int line = 0; struct section *co = NULL; @@ -543,6 +503,10 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used) return 0; } + uint32_t section_hash = 0; + if(section_name) { + section_hash = simple_hash(section_name); + } is_exporter_config = (strstr(filename, EXPORTING_CONF) != NULL); while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) { @@ -592,6 +556,23 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used) co = appconfig_section_find(root, s); if(!co) co = appconfig_section_create(root, s); + if(co && section_name && overwrite_used && section_hash == co->hash && !strcmp(section_name, co->name)) { + config_section_wrlock(co); + struct config_option *cv2 = co->values; + while (cv2) { + struct config_option *save = cv2->next; + struct config_option *found = appconfig_option_index_del(co, cv2); + if(found != cv2) + error("INTERNAL ERROR: Cannot remove '%s' from section '%s', it was not inserted before.", + cv2->name, co->name); + + free(cv2); + cv2 = save; + } + co->values = NULL; + config_section_unlock(co); + } + continue; } @@ -601,6 +582,10 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used) continue; } + if(section_name && overwrite_used && section_hash != co->hash && strcmp(section_name, co->name)) { + continue; + } + char *name = s; char *value = strchr(s, '='); if(!value) { @@ -701,6 +686,7 @@ void appconfig_generate(struct config *root, BUFFER *wb, int only_changed) || !strcmp(co->name, CONFIG_SECTION_HEALTH) || !strcmp(co->name, CONFIG_SECTION_BACKEND) || !strcmp(co->name, CONFIG_SECTION_STREAM) + || !strcmp(co->name, CONFIG_SECTION_HOST_LABEL) ) pri = 0; else if(!strncmp(co->name, "plugin:", 7)) pri = 1; @@ -806,3 +792,8 @@ int config_parse_duration(const char* string, int* result) { *result = 0; return 0; } + +struct section *appconfig_get_section(struct config *root, const char *name) +{ + return appconfig_section_find(root, name); +} diff --git a/libnetdata/config/appconfig.h b/libnetdata/config/appconfig.h index 1a60c46399..50c137ddb9 100644 --- a/libnetdata/config/appconfig.h +++ b/libnetdata/config/appconfig.h @@ -92,6 +92,7 @@ #define CONFIG_SECTION_BACKEND "backend" #define CONFIG_SECTION_STREAM "stream" #define CONFIG_SECTION_EXPORTING "exporting:global" +#define CONFIG_SECTION_HOST_LABEL "host labels" #define EXPORTING_CONF "exporting.conf" // these are used to limit the configuration names and values lengths @@ -99,17 +100,51 @@ #define CONFIG_MAX_NAME 1024 #define CONFIG_MAX_VALUE 2048 +// ---------------------------------------------------------------------------- +// Config definitions +#define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2) + +#define CONFIG_VALUE_LOADED 0x01 // has been loaded from the config +#define CONFIG_VALUE_USED 0x02 // has been accessed from the program +#define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value or the internal default value +#define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default + +struct config_option { + avl avl; // the index entry of this entry - this has to be first! + + uint8_t flags; + uint32_t hash; // a simple hash to speed up searching + // we first compare hashes, and only if the hashes are equal we do string comparisons + + char *name; + char *value; + + struct config_option *next; // config->mutex protects just this +}; + +struct section { + avl avl; // the index entry of this section - this has to be first! + + uint32_t hash; // a simple hash to speed up searching + // we first compare hashes, and only if the hashes are equal we do string comparisons + + char *name; + + struct section *next; // gloabl config_mutex protects just this + + struct config_option *values; + avl_tree_lock values_index; + + netdata_mutex_t mutex; // this locks only the writers, to ensure atomic updates + // readers are protected using the rwlock in avl_tree_lock +}; + struct config { struct section *sections; netdata_mutex_t mutex; avl_tree_lock index; }; -//struct connector_instance { -// char instance_name[CONFIG_MAX_NAME + 1]; -// char connector_name[CONFIG_MAX_NAME + 1]; -//}; - #define CONFIG_BOOLEAN_INVALID 100 // an invalid value to check for validity (used as default initialization when needed) #define CONFIG_BOOLEAN_NO 0 // disabled @@ -119,7 +154,9 @@ struct config { #define CONFIG_BOOLEAN_AUTO 2 // enabled if it has useful info when enabled #endif -extern int appconfig_load(struct config *root, char *filename, int overwrite_used); +extern int appconfig_load(struct config *root, char *filename, int overwrite_used, const char *section_name); +extern void config_section_wrlock(struct section *co); +extern void config_section_unlock(struct section *co); extern char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value); extern long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value); @@ -143,6 +180,10 @@ extern int appconfig_section_compare(void *a, void *b); extern int config_parse_duration(const char* string, int* result); +extern struct section *appconfig_get_section(struct config *root, const char *name); + +extern void appconfig_wrlock(struct config *root); +extern void appconfig_unlock(struct config *root); struct connector_instance { char instance_name[CONFIG_MAX_NAME + 1]; diff --git a/libnetdata/inlined.h b/libnetdata/inlined.h index 6a5994c12a..330b65648e 100644 --- a/libnetdata/inlined.h +++ b/libnetdata/inlined.h @@ -246,6 +246,20 @@ static inline char *strncpyz(char *dst, const char *src, size_t n) { return p; } +static inline void escape_json_string(char *dst, char *src, size_t len) { + while (*src != '\0' && len > 1) { + if (*src == '\\' || *src == '\"' || *src < 0x1F) { + *dst++ = '\\'; + *dst++ = *src++; + len -= 2; + } else { + *dst++ = *src++; + len--; + } + } + *dst = '\0'; +} + static inline int read_file(const char *filename, char *buffer, size_t size) { if(unlikely(!size)) return 3; diff --git a/libnetdata/simple_pattern/simple_pattern.c b/libnetdata/simple_pattern/simple_pattern.c index ab4b9de3c5..44fa42a629 100644 --- a/libnetdata/simple_pattern/simple_pattern.c +++ b/libnetdata/simple_pattern/simple_pattern.c @@ -331,3 +331,26 @@ extern int simple_pattern_is_potential_name(SIMPLE_PATTERN *p) } return (alpha || wildcards) && !colon; } + +char *simple_pattern_trim_around_equal(char *src) { + char *store = mallocz(strlen(src) +1); + if(!store) + return NULL; + + char *dst = store; + while (*src) { + if (*src == '=') { + if (*(dst -1) == ' ') + dst--; + + *dst++ = *src++; + if (*src == ' ') + src++; + } + + *dst++ = *src++; + } + *dst = 0x00; + + return store; +} diff --git a/libnetdata/simple_pattern/simple_pattern.h b/libnetdata/simple_pattern/simple_pattern.h index cb5e7699dd..ec6b535879 100644 --- a/libnetdata/simple_pattern/simple_pattern.h +++ b/libnetdata/simple_pattern/simple_pattern.h @@ -33,4 +33,7 @@ extern void simple_pattern_free(SIMPLE_PATTERN *list); extern void simple_pattern_dump(uint64_t debug_type, SIMPLE_PATTERN *p) ; extern int simple_pattern_is_potential_name(SIMPLE_PATTERN *p) ; +//Auxiliary function to create a pattern +char *simple_pattern_trim_around_equal(char *src); + #endif //NETDATA_SIMPLE_PATTERN_H |