appconfig.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. /*
  3. * This section manages ini config files, like netdata.conf and stream.conf
  4. *
  5. * It is organized like this:
  6. *
  7. * struct config (i.e. netdata.conf or stream.conf)
  8. * .sections = a linked list of struct section
  9. * .mutex = a mutex to protect the above linked list due to multi-threading
  10. * .index = an AVL tree of struct section
  11. *
  12. * struct section (i.e. [global] or [health] of netdata.conf)
  13. * .value = a linked list of struct config_option
  14. * .mutex = a mutex to protect the above linked list due to multi-threading
  15. * .value_index = an AVL tree of struct config_option
  16. *
  17. * struct config_option (ie. a name-value pair for each ini file option)
  18. *
  19. * The following operations on name-value options are supported:
  20. * SET to set the value of an option
  21. * SET DEFAULT to set the value and the default value of an option
  22. * GET to get the value of an option
  23. * EXISTS to check if an option exists
  24. * MOVE to move an option from a section to another section, and/or rename it
  25. *
  26. * GET and SET operations are provided for the following data types:
  27. * STRING
  28. * NUMBER (long long)
  29. * FLOAT (long double)
  30. * BOOLEAN (false, true)
  31. * BOOLEAN ONDEMAND (false, true, auto)
  32. *
  33. * GET and SET operations create struct config_option, if it is not already present.
  34. * This allows netdata to run even without netdata.conf and stream.conf. The internal
  35. * defaults are used to create the structure that should exist in the ini file and the config
  36. * file can be downloaded from the server.
  37. *
  38. * Also 2 operations are supported for the whole config file:
  39. *
  40. * LOAD To load the ini file from disk
  41. * GENERATE To generate the ini file (this is used to download the ini file from the server)
  42. *
  43. * For each option (name-value pair), the system maintains 4 flags:
  44. * LOADED to indicate that the value has been loaded from the file
  45. * USED to indicate that netdata used the value
  46. * CHANGED to indicate that the value has been changed from the loaded value or the internal default value
  47. * CHECKED is used internally for optimization (to avoid an strcmp() every time GET is called).
  48. *
  49. * TODO:
  50. * 1. The linked lists and the mutexes can be removed and the AVL trees can become DICTIONARY.
  51. * This part of the code was written before we add traversal to AVL.
  52. *
  53. * 2. High level data types could be supported, to simplify the rest of the code:
  54. * MULTIPLE CHOICE to let the user select one of the supported keywords
  55. * this would allow users see in comments the available options
  56. *
  57. * SIMPLE PATTERN to let the user define netdata SIMPLE PATTERNS
  58. *
  59. * 3. Sorting of options should be supported.
  60. * Today, when the ini file is downloaded from the server, the options are shown in the order
  61. * they appear in the linked list (the order they were added, listing changed options first).
  62. * If we remove the linked list, the order they appear in the AVL tree will be used (which is
  63. * random due to simple_hash()).
  64. * Ideally, we support sorting of options when generating the ini file.
  65. *
  66. * 4. There is no free() operation. So, memory is freed on netdata exit.
  67. *
  68. * 5. Avoid memory fragmentation
  69. * Since entries are created from multiple threads and a lot of allocations are required
  70. * for each config_option, fragmentation can be a problem for IoT.
  71. *
  72. * 6. Although this way of managing options is quite flexible and dynamic, it wastes memory
  73. * for the names of the options. Since most of the option names are static, we could provide
  74. * a method to allocate only the dynamic option names.
  75. */
  76. #ifndef NETDATA_CONFIG_H
  77. #define NETDATA_CONFIG_H 1
  78. #include "../libnetdata.h"
  79. #define CONFIG_FILENAME "netdata.conf"
  80. #define CONFIG_SECTION_GLOBAL "global"
  81. #define CONFIG_SECTION_DIRECTORIES "directories"
  82. #define CONFIG_SECTION_LOGS "logs"
  83. #define CONFIG_SECTION_ENV_VARS "environment variables"
  84. #define CONFIG_SECTION_SQLITE "sqlite"
  85. #define CONFIG_SECTION_WEB "web"
  86. #define CONFIG_SECTION_STATSD "statsd"
  87. #define CONFIG_SECTION_PLUGINS "plugins"
  88. #define CONFIG_SECTION_CLOUD "cloud"
  89. #define CONFIG_SECTION_REGISTRY "registry"
  90. #define CONFIG_SECTION_HEALTH "health"
  91. #define CONFIG_SECTION_STREAM "stream"
  92. #define CONFIG_SECTION_ML "ml"
  93. #define CONFIG_SECTION_EXPORTING "exporting:global"
  94. #define CONFIG_SECTION_PROMETHEUS "prometheus:exporter"
  95. #define CONFIG_SECTION_HOST_LABEL "host labels"
  96. #define EXPORTING_CONF "exporting.conf"
  97. #define CONFIG_SECTION_GLOBAL_STATISTICS "global statistics"
  98. #define CONFIG_SECTION_DB "db"
  99. // these are used to limit the configuration names and values lengths
  100. // they are not enforced by config.c functions (they will strdup() all strings, no matter of their length)
  101. #define CONFIG_MAX_NAME 1024
  102. #define CONFIG_MAX_VALUE 2048
  103. // ----------------------------------------------------------------------------
  104. // Config definitions
  105. #define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2)
  106. #define CONFIG_VALUE_LOADED 0x01 // has been loaded from the config
  107. #define CONFIG_VALUE_USED 0x02 // has been accessed from the program
  108. #define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value or the internal default value
  109. #define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default
  110. struct config_option {
  111. avl_t avl_node; // the index entry of this entry - this has to be first!
  112. uint8_t flags;
  113. uint32_t hash; // a simple hash to speed up searching
  114. // we first compare hashes, and only if the hashes are equal we do string comparisons
  115. char *name;
  116. char *value;
  117. struct config_option *next; // config->mutex protects just this
  118. };
  119. struct section {
  120. avl_t avl_node; // the index entry of this section - this has to be first!
  121. uint32_t hash; // a simple hash to speed up searching
  122. // we first compare hashes, and only if the hashes are equal we do string comparisons
  123. char *name;
  124. struct section *next; // global config_mutex protects just this
  125. struct config_option *values;
  126. avl_tree_lock values_index;
  127. netdata_mutex_t mutex; // this locks only the writers, to ensure atomic updates
  128. // readers are protected using the rwlock in avl_tree_lock
  129. };
  130. struct config {
  131. struct section *first_section;
  132. struct section *last_section; // optimize inserting at the end
  133. netdata_mutex_t mutex;
  134. avl_tree_lock index;
  135. };
  136. #define CONFIG_BOOLEAN_INVALID 100 // an invalid value to check for validity (used as default initialization when needed)
  137. #define CONFIG_BOOLEAN_NO 0 // disabled
  138. #define CONFIG_BOOLEAN_YES 1 // enabled
  139. #ifndef CONFIG_BOOLEAN_AUTO
  140. #define CONFIG_BOOLEAN_AUTO 2 // enabled if it has useful info when enabled
  141. #endif
  142. extern int appconfig_load(struct config *root, char *filename, int overwrite_used, const char *section_name);
  143. extern void config_section_wrlock(struct section *co);
  144. extern void config_section_unlock(struct section *co);
  145. extern char *appconfig_get_by_section(struct section *co, const char *name, const char *default_value);
  146. extern char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value);
  147. extern long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value);
  148. extern NETDATA_DOUBLE appconfig_get_float(struct config *root, const char *section, const char *name, NETDATA_DOUBLE value);
  149. extern int appconfig_get_boolean_by_section(struct section *co, const char *name, int value);
  150. extern int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value);
  151. extern int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value);
  152. extern int appconfig_get_duration(struct config *root, const char *section, const char *name, const char *value);
  153. extern const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value);
  154. extern const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value);
  155. extern long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value);
  156. extern NETDATA_DOUBLE appconfig_set_float(struct config *root, const char *section, const char *name, NETDATA_DOUBLE value);
  157. extern int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value);
  158. extern int appconfig_exists(struct config *root, const char *section, const char *name);
  159. extern int appconfig_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new);
  160. extern void appconfig_generate(struct config *root, BUFFER *wb, int only_changed);
  161. extern int appconfig_section_compare(void *a, void *b);
  162. extern void appconfig_section_destroy_non_loaded(struct config *root, const char *section);
  163. extern void appconfig_section_option_destroy_non_loaded(struct config *root, const char *section, const char *name);
  164. extern int config_parse_duration(const char* string, int* result);
  165. extern struct section *appconfig_get_section(struct config *root, const char *name);
  166. extern void appconfig_wrlock(struct config *root);
  167. extern void appconfig_unlock(struct config *root);
  168. struct connector_instance {
  169. char instance_name[CONFIG_MAX_NAME + 1];
  170. char connector_name[CONFIG_MAX_NAME + 1];
  171. };
  172. typedef struct _connector_instance {
  173. struct section *connector; // actual connector
  174. struct section *instance; // This instance
  175. char instance_name[CONFIG_MAX_NAME + 1];
  176. char connector_name[CONFIG_MAX_NAME + 1];
  177. struct _connector_instance *next; // Next instance
  178. } _CONNECTOR_INSTANCE;
  179. extern _CONNECTOR_INSTANCE *add_connector_instance(struct section *connector, struct section *instance);
  180. #endif /* NETDATA_CONFIG_H */