summaryrefslogtreecommitdiffstats
path: root/libnetdata
diff options
context:
space:
mode:
authorAndrew Moss <1043609+amoss@users.noreply.github.com>2019-12-16 15:12:00 +0100
committerGitHub <noreply@github.com>2019-12-16 15:12:00 +0100
commitc8c72f18a6a8fd09d3b6284e49525396b24e8395 (patch)
tree5b9aeaea7d72e1d1029d45f67c0a5f130ecc2f80 /libnetdata
parentc4bb3d2642ab34e6aca912b22e55aed52f84e974 (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.c81
-rw-r--r--libnetdata/config/appconfig.h53
-rw-r--r--libnetdata/inlined.h14
-rw-r--r--libnetdata/simple_pattern/simple_pattern.c23
-rw-r--r--libnetdata/simple_pattern/simple_pattern.h3
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