rrdhost.c 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #define NETDATA_RRD_INTERNALS
  3. #include "rrd.h"
  4. int storage_tiers = 1;
  5. int storage_tiers_grouping_iterations[RRD_STORAGE_TIERS] = { 1, 60, 60, 60, 60 };
  6. RRD_BACKFILL storage_tiers_backfill[RRD_STORAGE_TIERS] = { RRD_BACKFILL_NEW, RRD_BACKFILL_NEW, RRD_BACKFILL_NEW, RRD_BACKFILL_NEW, RRD_BACKFILL_NEW };
  7. #if RRD_STORAGE_TIERS != 5
  8. #error RRD_STORAGE_TIERS is not 5 - you need to update the grouping iterations per tier
  9. #endif
  10. int get_tier_grouping(int tier) {
  11. if(unlikely(tier >= storage_tiers)) tier = storage_tiers - 1;
  12. if(unlikely(tier < 0)) tier = 0;
  13. int grouping = 1;
  14. // first tier is always 1 iteration of whatever update every the chart has
  15. for(int i = 1; i <= tier ;i++)
  16. grouping *= storage_tiers_grouping_iterations[i];
  17. return grouping;
  18. }
  19. RRDHOST *localhost = NULL;
  20. size_t rrd_hosts_available = 0;
  21. netdata_rwlock_t rrd_rwlock = NETDATA_RWLOCK_INITIALIZER;
  22. time_t rrdset_free_obsolete_time = 3600;
  23. time_t rrdhost_free_orphan_time = 3600;
  24. bool is_storage_engine_shared(STORAGE_INSTANCE *engine) {
  25. #ifdef ENABLE_DBENGINE
  26. for(int tier = 0; tier < storage_tiers ;tier++) {
  27. if (engine == (STORAGE_INSTANCE *)multidb_ctx[tier])
  28. return true;
  29. }
  30. #endif
  31. return false;
  32. }
  33. // ----------------------------------------------------------------------------
  34. // RRDHOST index
  35. int rrdhost_compare(void* a, void* b) {
  36. if(((RRDHOST *)a)->hash_machine_guid < ((RRDHOST *)b)->hash_machine_guid) return -1;
  37. else if(((RRDHOST *)a)->hash_machine_guid > ((RRDHOST *)b)->hash_machine_guid) return 1;
  38. else return strcmp(((RRDHOST *)a)->machine_guid, ((RRDHOST *)b)->machine_guid);
  39. }
  40. avl_tree_lock rrdhost_root_index = {
  41. .avl_tree = { NULL, rrdhost_compare },
  42. .rwlock = AVL_LOCK_INITIALIZER
  43. };
  44. RRDHOST *rrdhost_find_by_guid(const char *guid, uint32_t hash) {
  45. debug(D_RRDHOST, "Searching in index for host with guid '%s'", guid);
  46. RRDHOST tmp;
  47. strncpyz(tmp.machine_guid, guid, GUID_LEN);
  48. tmp.hash_machine_guid = (hash)?hash:simple_hash(tmp.machine_guid);
  49. return (RRDHOST *)avl_search_lock(&(rrdhost_root_index), (avl_t *) &tmp);
  50. }
  51. RRDHOST *rrdhost_find_by_hostname(const char *hostname, uint32_t hash) {
  52. if(unlikely(!strcmp(hostname, "localhost")))
  53. return localhost;
  54. if(unlikely(!hash)) hash = simple_hash(hostname);
  55. rrd_rdlock();
  56. RRDHOST *host;
  57. rrdhost_foreach_read(host) {
  58. if(unlikely((hash == host->hash_hostname && !strcmp(hostname, host->hostname)))) {
  59. rrd_unlock();
  60. return host;
  61. }
  62. }
  63. rrd_unlock();
  64. return NULL;
  65. }
  66. #define rrdhost_index_add(rrdhost) (RRDHOST *)avl_insert_lock(&(rrdhost_root_index), (avl_t *)(rrdhost))
  67. #define rrdhost_index_del(rrdhost) (RRDHOST *)avl_remove_lock(&(rrdhost_root_index), (avl_t *)(rrdhost))
  68. // ----------------------------------------------------------------------------
  69. // RRDHOST - internal helpers
  70. static inline void rrdhost_init_tags(RRDHOST *host, const char *tags) {
  71. if(host->tags && tags && !strcmp(host->tags, tags))
  72. return;
  73. void *old = (void *)host->tags;
  74. host->tags = (tags && *tags)?strdupz(tags):NULL;
  75. freez(old);
  76. }
  77. static inline void rrdhost_init_hostname(RRDHOST *host, const char *hostname) {
  78. if(host->hostname && hostname && !strcmp(host->hostname, hostname))
  79. return;
  80. void *old = host->hostname;
  81. host->hostname = strdupz(hostname?hostname:"localhost");
  82. host->hash_hostname = simple_hash(host->hostname);
  83. freez(old);
  84. }
  85. static inline void rrdhost_init_os(RRDHOST *host, const char *os) {
  86. if(host->os && os && !strcmp(host->os, os))
  87. return;
  88. void *old = (void *)host->os;
  89. host->os = strdupz(os?os:"unknown");
  90. freez(old);
  91. }
  92. static inline void rrdhost_init_timezone(RRDHOST *host, const char *timezone, const char *abbrev_timezone, int32_t utc_offset) {
  93. if (host->timezone && timezone && !strcmp(host->timezone, timezone) && host->abbrev_timezone && abbrev_timezone &&
  94. !strcmp(host->abbrev_timezone, abbrev_timezone) && host->utc_offset == utc_offset)
  95. return;
  96. void *old = (void *)host->timezone;
  97. host->timezone = strdupz((timezone && *timezone)?timezone:"unknown");
  98. freez(old);
  99. old = (void *)host->abbrev_timezone;
  100. host->abbrev_timezone = strdupz((abbrev_timezone && *abbrev_timezone) ? abbrev_timezone : "UTC");
  101. freez(old);
  102. host->utc_offset = utc_offset;
  103. }
  104. static inline void rrdhost_init_machine_guid(RRDHOST *host, const char *machine_guid) {
  105. strncpy(host->machine_guid, machine_guid, GUID_LEN);
  106. host->machine_guid[GUID_LEN] = '\0';
  107. host->hash_machine_guid = simple_hash(host->machine_guid);
  108. }
  109. void set_host_properties(RRDHOST *host, int update_every, RRD_MEMORY_MODE memory_mode, const char *hostname,
  110. const char *registry_hostname, const char *guid, const char *os, const char *tags,
  111. const char *tzone, const char *abbrev_tzone, int32_t utc_offset, const char *program_name,
  112. const char *program_version)
  113. {
  114. host->rrd_update_every = update_every;
  115. host->rrd_memory_mode = memory_mode;
  116. rrdhost_init_hostname(host, hostname);
  117. rrdhost_init_machine_guid(host, guid);
  118. rrdhost_init_os(host, os);
  119. rrdhost_init_timezone(host, tzone, abbrev_tzone, utc_offset);
  120. rrdhost_init_tags(host, tags);
  121. host->program_name = strdupz((program_name && *program_name) ? program_name : "unknown");
  122. host->program_version = strdupz((program_version && *program_version) ? program_version : "unknown");
  123. host->registry_hostname = strdupz((registry_hostname && *registry_hostname) ? registry_hostname : host->hostname);
  124. }
  125. // ----------------------------------------------------------------------------
  126. // RRDHOST - add a host
  127. RRDHOST *rrdhost_create(const char *hostname,
  128. const char *registry_hostname,
  129. const char *guid,
  130. const char *os,
  131. const char *timezone,
  132. const char *abbrev_timezone,
  133. int32_t utc_offset,
  134. const char *tags,
  135. const char *program_name,
  136. const char *program_version,
  137. int update_every,
  138. long entries,
  139. RRD_MEMORY_MODE memory_mode,
  140. unsigned int health_enabled,
  141. unsigned int rrdpush_enabled,
  142. char *rrdpush_destination,
  143. char *rrdpush_api_key,
  144. char *rrdpush_send_charts_matching,
  145. struct rrdhost_system_info *system_info,
  146. int is_localhost
  147. ) {
  148. debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid);
  149. #ifdef ENABLE_DBENGINE
  150. int is_legacy = (memory_mode == RRD_MEMORY_MODE_DBENGINE) && is_legacy_child(guid);
  151. #else
  152. int is_legacy = 1;
  153. #endif
  154. rrd_check_wrlock();
  155. int is_in_multihost = (memory_mode == RRD_MEMORY_MODE_DBENGINE && !is_legacy);
  156. RRDHOST *host = callocz(1, sizeof(RRDHOST));
  157. set_host_properties(host, (update_every > 0)?update_every:1, memory_mode, hostname, registry_hostname, guid, os,
  158. tags, timezone, abbrev_timezone, utc_offset, program_name, program_version);
  159. host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries);
  160. host->health_enabled = ((memory_mode == RRD_MEMORY_MODE_NONE)) ? 0 : health_enabled;
  161. host->sender = mallocz(sizeof(*host->sender));
  162. sender_init(host->sender, host);
  163. netdata_mutex_init(&host->receiver_lock);
  164. host->rrdpush_send_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key) ? 1 : 0;
  165. host->rrdpush_send_destination = (host->rrdpush_send_enabled)?strdupz(rrdpush_destination):NULL;
  166. if (host->rrdpush_send_destination)
  167. host->destinations = destinations_init(host->rrdpush_send_destination);
  168. host->rrdpush_send_api_key = (host->rrdpush_send_enabled)?strdupz(rrdpush_api_key):NULL;
  169. host->rrdpush_send_charts_matching = simple_pattern_create(rrdpush_send_charts_matching, NULL, SIMPLE_PATTERN_EXACT);
  170. host->rrdpush_sender_pipe[0] = -1;
  171. host->rrdpush_sender_pipe[1] = -1;
  172. host->rrdpush_sender_socket = -1;
  173. //host->stream_version = STREAMING_PROTOCOL_CURRENT_VERSION; Unused?
  174. #ifdef ENABLE_HTTPS
  175. host->ssl.conn = NULL;
  176. host->ssl.flags = NETDATA_SSL_START;
  177. host->stream_ssl.conn = NULL;
  178. host->stream_ssl.flags = NETDATA_SSL_START;
  179. #endif
  180. netdata_rwlock_init(&host->rrdhost_rwlock);
  181. host->host_labels = rrdlabels_create();
  182. netdata_mutex_init(&host->aclk_state_lock);
  183. host->system_info = system_info;
  184. avl_init_lock(&(host->rrdset_root_index), rrdset_compare);
  185. avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name);
  186. avl_init_lock(&(host->rrdfamily_root_index), rrdfamily_compare);
  187. avl_init_lock(&(host->rrdvar_root_index), rrdvar_compare);
  188. if(config_get_boolean(CONFIG_SECTION_DB, "delete obsolete charts files", 1))
  189. rrdhost_flag_set(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS);
  190. if(config_get_boolean(CONFIG_SECTION_DB, "delete orphan hosts files", 1) && !is_localhost)
  191. rrdhost_flag_set(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST);
  192. host->health_default_warn_repeat_every = config_get_duration(CONFIG_SECTION_HEALTH, "default repeat warning", "never");
  193. host->health_default_crit_repeat_every = config_get_duration(CONFIG_SECTION_HEALTH, "default repeat critical", "never");
  194. avl_init_lock(&(host->alarms_idx_health_log), alarm_compare_id);
  195. avl_init_lock(&(host->alarms_idx_name), alarm_compare_name);
  196. // ------------------------------------------------------------------------
  197. // initialize health variables
  198. host->health_log.next_log_id = 1;
  199. host->health_log.next_alarm_id = 1;
  200. host->health_log.max = 1000;
  201. host->health_log.next_log_id = (uint32_t)now_realtime_sec();
  202. host->health_log.next_alarm_id = 0;
  203. long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max);
  204. if(n < 10) {
  205. error("Host '%s': health configuration has invalid max log entries %ld. Using default %u", host->hostname, n, host->health_log.max);
  206. config_set_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", (long)host->health_log.max);
  207. }
  208. else
  209. host->health_log.max = (unsigned int)n;
  210. netdata_rwlock_init(&host->health_log.alarm_log_rwlock);
  211. char filename[FILENAME_MAX + 1];
  212. if(is_localhost) {
  213. host->cache_dir = strdupz(netdata_configured_cache_dir);
  214. host->varlib_dir = strdupz(netdata_configured_varlib_dir);
  215. }
  216. else {
  217. // this is not localhost - append our GUID to localhost path
  218. if (is_in_multihost) { // don't append to cache dir in multihost
  219. host->cache_dir = strdupz(netdata_configured_cache_dir);
  220. } else {
  221. snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid);
  222. host->cache_dir = strdupz(filename);
  223. }
  224. if((host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || (
  225. host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE && is_legacy))) {
  226. int r = mkdir(host->cache_dir, 0775);
  227. if(r != 0 && errno != EEXIST)
  228. error("Host '%s': cannot create directory '%s'", host->hostname, host->cache_dir);
  229. }
  230. snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid);
  231. host->varlib_dir = strdupz(filename);
  232. if(host->health_enabled) {
  233. int r = mkdir(host->varlib_dir, 0775);
  234. if(r != 0 && errno != EEXIST)
  235. error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir);
  236. }
  237. }
  238. if(host->health_enabled) {
  239. snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir);
  240. int r = mkdir(filename, 0775);
  241. if(r != 0 && errno != EEXIST)
  242. error("Host '%s': cannot create directory '%s'", host->hostname, filename);
  243. }
  244. snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
  245. host->health_log_filename = strdupz(filename);
  246. snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_primary_plugins_dir);
  247. host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
  248. host->health_default_recipient = strdupz("root");
  249. // ------------------------------------------------------------------------
  250. // load health configuration
  251. if(host->health_enabled) {
  252. rrdhost_wrlock(host);
  253. health_readdir(host, health_user_config_dir(), health_stock_config_dir(), NULL);
  254. rrdhost_unlock(host);
  255. }
  256. RRDHOST *t = rrdhost_index_add(host);
  257. if(t != host) {
  258. error("Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.", host->hostname, host->machine_guid, t->hostname, t->machine_guid);
  259. rrdhost_free(host);
  260. return NULL;
  261. }
  262. if (likely(!uuid_parse(host->machine_guid, host->host_uuid))) {
  263. int rc = sql_store_host(&host->host_uuid, hostname, registry_hostname, update_every, os, timezone, tags,
  264. host->system_info ? host->system_info->hops : 0);
  265. if (unlikely(rc))
  266. error_report("Failed to store machine GUID to the database");
  267. sql_load_node_id(host);
  268. if (host->health_enabled) {
  269. if (!file_is_migrated(host->health_log_filename)) {
  270. int rc = sql_create_health_log_table(host);
  271. if (unlikely(rc)) {
  272. error_report("Failed to create health log table in the database");
  273. health_alarm_log_load(host);
  274. health_alarm_log_open(host);
  275. }
  276. else {
  277. health_alarm_log_load(host);
  278. add_migrated_file(host->health_log_filename, 0);
  279. }
  280. } else {
  281. sql_create_health_log_table(host);
  282. sql_health_alarm_log_load(host);
  283. }
  284. }
  285. }
  286. else
  287. error_report("Host machine GUID %s is not valid", host->machine_guid);
  288. if (host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
  289. #ifdef ENABLE_DBENGINE
  290. char dbenginepath[FILENAME_MAX + 1];
  291. int ret;
  292. snprintfz(dbenginepath, FILENAME_MAX, "%s/dbengine", host->cache_dir);
  293. ret = mkdir(dbenginepath, 0775);
  294. if (ret != 0 && errno != EEXIST)
  295. error("Host '%s': cannot create directory '%s'", host->hostname, dbenginepath);
  296. else ret = 0; // succeed
  297. if (is_legacy) {
  298. // initialize legacy dbengine instance as needed
  299. ret = rrdeng_init(
  300. host,
  301. (struct rrdengine_instance **)&host->storage_instance[0],
  302. dbenginepath,
  303. default_rrdeng_page_cache_mb,
  304. default_rrdeng_disk_quota_mb,
  305. 0); // may fail here for legacy dbengine initialization
  306. if(ret == 0) {
  307. // assign the rest of the shared storage instances to it
  308. // to allow them collect its metrics too
  309. for(int tier = 1; tier < storage_tiers ; tier++)
  310. host->storage_instance[tier] = (STORAGE_INSTANCE *)multidb_ctx[tier];
  311. }
  312. }
  313. else {
  314. for(int tier = 0; tier < storage_tiers ; tier++)
  315. host->storage_instance[tier] = (STORAGE_INSTANCE *)multidb_ctx[tier];
  316. }
  317. if (ret) { // check legacy or multihost initialization success
  318. error(
  319. "Host '%s': cannot initialize host with machine guid '%s'. Failed to initialize DB engine at '%s'.",
  320. host->hostname, host->machine_guid, host->cache_dir);
  321. rrdhost_free(host);
  322. host = NULL;
  323. //rrd_hosts_available++; //TODO: maybe we want this?
  324. return host;
  325. }
  326. #else
  327. fatal("RRD_MEMORY_MODE_DBENGINE is not supported in this platform.");
  328. #endif
  329. }
  330. else {
  331. #ifdef ENABLE_DBENGINE
  332. // the first tier is reserved for the non-dbengine modes
  333. for(int tier = 1; tier < storage_tiers ; tier++)
  334. host->storage_instance[tier] = (STORAGE_INSTANCE *)multidb_ctx[tier];
  335. #endif
  336. }
  337. // ------------------------------------------------------------------------
  338. // link it and add it to the index
  339. if(is_localhost) {
  340. host->next = localhost;
  341. localhost = host;
  342. }
  343. else {
  344. if(localhost) {
  345. host->next = localhost->next;
  346. localhost->next = host;
  347. }
  348. else localhost = host;
  349. }
  350. // ------------------------------------------------------------------------
  351. // init new ML host and update system_info to let upstreams know
  352. // about ML functionality
  353. //
  354. if (is_localhost && host->system_info) {
  355. host->system_info->ml_capable = ml_capable();
  356. host->system_info->ml_enabled = ml_enabled(host);
  357. host->system_info->mc_version = enable_metric_correlations ? metric_correlations_version : 0;
  358. }
  359. ml_new_host(host);
  360. info("Host '%s' (at registry as '%s') with guid '%s' initialized"
  361. ", os '%s'"
  362. ", timezone '%s'"
  363. ", tags '%s'"
  364. ", program_name '%s'"
  365. ", program_version '%s'"
  366. ", update every %d"
  367. ", memory mode %s"
  368. ", history entries %ld"
  369. ", streaming %s"
  370. " (to '%s' with api key '%s')"
  371. ", health %s"
  372. ", cache_dir '%s'"
  373. ", varlib_dir '%s'"
  374. ", health_log '%s'"
  375. ", alarms default handler '%s'"
  376. ", alarms default recipient '%s'"
  377. , host->hostname
  378. , host->registry_hostname
  379. , host->machine_guid
  380. , host->os
  381. , host->timezone
  382. , (host->tags)?host->tags:""
  383. , host->program_name
  384. , host->program_version
  385. , host->rrd_update_every
  386. , rrd_memory_mode_name(host->rrd_memory_mode)
  387. , host->rrd_history_entries
  388. , host->rrdpush_send_enabled?"enabled":"disabled"
  389. , host->rrdpush_send_destination?host->rrdpush_send_destination:""
  390. , host->rrdpush_send_api_key?host->rrdpush_send_api_key:""
  391. , host->health_enabled?"enabled":"disabled"
  392. , host->cache_dir
  393. , host->varlib_dir
  394. , host->health_log_filename
  395. , host->health_default_exec
  396. , host->health_default_recipient
  397. );
  398. rrd_hosts_available++;
  399. return host;
  400. }
  401. void rrdhost_update(RRDHOST *host
  402. , const char *hostname
  403. , const char *registry_hostname
  404. , const char *guid
  405. , const char *os
  406. , const char *timezone
  407. , const char *abbrev_timezone
  408. , int32_t utc_offset
  409. , const char *tags
  410. , const char *program_name
  411. , const char *program_version
  412. , int update_every
  413. , long history
  414. , RRD_MEMORY_MODE mode
  415. , unsigned int health_enabled
  416. , unsigned int rrdpush_enabled
  417. , char *rrdpush_destination
  418. , char *rrdpush_api_key
  419. , char *rrdpush_send_charts_matching
  420. , struct rrdhost_system_info *system_info
  421. )
  422. {
  423. UNUSED(guid);
  424. UNUSED(rrdpush_enabled);
  425. UNUSED(rrdpush_destination);
  426. UNUSED(rrdpush_api_key);
  427. UNUSED(rrdpush_send_charts_matching);
  428. host->health_enabled = (mode == RRD_MEMORY_MODE_NONE) ? 0 : health_enabled;
  429. //host->stream_version = STREAMING_PROTOCOL_CURRENT_VERSION; Unused?
  430. rrdhost_system_info_free(host->system_info);
  431. host->system_info = system_info;
  432. rrdhost_init_os(host, os);
  433. rrdhost_init_timezone(host, timezone, abbrev_timezone, utc_offset);
  434. freez(host->registry_hostname);
  435. host->registry_hostname = strdupz((registry_hostname && *registry_hostname)?registry_hostname:hostname);
  436. if(strcmp(host->hostname, hostname) != 0) {
  437. info("Host '%s' has been renamed to '%s'. If this is not intentional it may mean multiple hosts are using the same machine_guid.", host->hostname, hostname);
  438. char *t = host->hostname;
  439. host->hostname = strdupz(hostname);
  440. host->hash_hostname = simple_hash(host->hostname);
  441. freez(t);
  442. }
  443. if(strcmp(host->program_name, program_name) != 0) {
  444. info("Host '%s' switched program name from '%s' to '%s'", host->hostname, host->program_name, program_name);
  445. char *t = host->program_name;
  446. host->program_name = strdupz(program_name);
  447. freez(t);
  448. }
  449. if(strcmp(host->program_version, program_version) != 0) {
  450. info("Host '%s' switched program version from '%s' to '%s'", host->hostname, host->program_version, program_version);
  451. char *t = host->program_version;
  452. host->program_version = strdupz(program_version);
  453. freez(t);
  454. }
  455. if(host->rrd_update_every != update_every)
  456. error("Host '%s' has an update frequency of %d seconds, but the wanted one is %d seconds. Restart netdata here to apply the new settings.", host->hostname, host->rrd_update_every, update_every);
  457. if(host->rrd_history_entries < history)
  458. error("Host '%s' has history of %ld entries, but the wanted one is %ld entries. Restart netdata here to apply the new settings.", host->hostname, host->rrd_history_entries, history);
  459. if(host->rrd_memory_mode != mode)
  460. error("Host '%s' has memory mode '%s', but the wanted one is '%s'. Restart netdata here to apply the new settings.", host->hostname, rrd_memory_mode_name(host->rrd_memory_mode), rrd_memory_mode_name(mode));
  461. // update host tags
  462. rrdhost_init_tags(host, tags);
  463. if (rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED)) {
  464. rrdhost_flag_clear(host, RRDHOST_FLAG_ARCHIVED);
  465. if(host->health_enabled) {
  466. int r;
  467. char filename[FILENAME_MAX + 1];
  468. if (host != localhost) {
  469. r = mkdir(host->varlib_dir, 0775);
  470. if (r != 0 && errno != EEXIST)
  471. error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir);
  472. }
  473. snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir);
  474. r = mkdir(filename, 0775);
  475. if(r != 0 && errno != EEXIST)
  476. error("Host '%s': cannot create directory '%s'", host->hostname, filename);
  477. rrdhost_wrlock(host);
  478. health_readdir(host, health_user_config_dir(), health_stock_config_dir(), NULL);
  479. rrdhost_unlock(host);
  480. if (!file_is_migrated(host->health_log_filename)) {
  481. int rc = sql_create_health_log_table(host);
  482. if (unlikely(rc)) {
  483. error_report("Failed to create health log table in the database");
  484. health_alarm_log_load(host);
  485. health_alarm_log_open(host);
  486. } else {
  487. health_alarm_log_load(host);
  488. add_migrated_file(host->health_log_filename, 0);
  489. }
  490. } else {
  491. sql_create_health_log_table(host);
  492. sql_health_alarm_log_load(host);
  493. }
  494. }
  495. rrd_hosts_available++;
  496. info("Host %s is not in archived mode anymore", host->hostname);
  497. }
  498. return;
  499. }
  500. RRDHOST *rrdhost_find_or_create(
  501. const char *hostname
  502. , const char *registry_hostname
  503. , const char *guid
  504. , const char *os
  505. , const char *timezone
  506. , const char *abbrev_timezone
  507. , int32_t utc_offset
  508. , const char *tags
  509. , const char *program_name
  510. , const char *program_version
  511. , int update_every
  512. , long history
  513. , RRD_MEMORY_MODE mode
  514. , unsigned int health_enabled
  515. , unsigned int rrdpush_enabled
  516. , char *rrdpush_destination
  517. , char *rrdpush_api_key
  518. , char *rrdpush_send_charts_matching
  519. , struct rrdhost_system_info *system_info
  520. ) {
  521. debug(D_RRDHOST, "Searching for host '%s' with guid '%s'", hostname, guid);
  522. rrd_wrlock();
  523. RRDHOST *host = rrdhost_find_by_guid(guid, 0);
  524. if (unlikely(host && RRD_MEMORY_MODE_DBENGINE != mode && rrdhost_flag_check(host, RRDHOST_FLAG_ARCHIVED))) {
  525. /* If a legacy memory mode instantiates all dbengine state must be discarded to avoid inconsistencies */
  526. error("Archived host '%s' has memory mode '%s', but the wanted one is '%s'. Discarding archived state.",
  527. host->hostname, rrd_memory_mode_name(host->rrd_memory_mode), rrd_memory_mode_name(mode));
  528. rrdhost_free(host);
  529. host = NULL;
  530. }
  531. if(!host) {
  532. host = rrdhost_create(
  533. hostname
  534. , registry_hostname
  535. , guid
  536. , os
  537. , timezone
  538. , abbrev_timezone
  539. , utc_offset
  540. , tags
  541. , program_name
  542. , program_version
  543. , update_every
  544. , history
  545. , mode
  546. , health_enabled
  547. , rrdpush_enabled
  548. , rrdpush_destination
  549. , rrdpush_api_key
  550. , rrdpush_send_charts_matching
  551. , system_info
  552. , 0
  553. );
  554. }
  555. else {
  556. rrdhost_update(host
  557. , hostname
  558. , registry_hostname
  559. , guid
  560. , os
  561. , timezone
  562. , abbrev_timezone
  563. , utc_offset
  564. , tags
  565. , program_name
  566. , program_version
  567. , update_every
  568. , history
  569. , mode
  570. , health_enabled
  571. , rrdpush_enabled
  572. , rrdpush_destination
  573. , rrdpush_api_key
  574. , rrdpush_send_charts_matching
  575. , system_info);
  576. }
  577. if (host) {
  578. rrdhost_wrlock(host);
  579. rrdhost_flag_clear(host, RRDHOST_FLAG_ORPHAN);
  580. host->senders_disconnected_time = 0;
  581. rrdhost_unlock(host);
  582. }
  583. rrd_unlock();
  584. return host;
  585. }
  586. inline int rrdhost_should_be_removed(RRDHOST *host, RRDHOST *protected_host, time_t now) {
  587. if(host != protected_host
  588. && host != localhost
  589. && rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN)
  590. && !host->receiver
  591. && host->senders_disconnected_time
  592. && host->senders_disconnected_time + rrdhost_free_orphan_time < now)
  593. return 1;
  594. return 0;
  595. }
  596. void rrdhost_cleanup_orphan_hosts_nolock(RRDHOST *protected_host) {
  597. time_t now = now_realtime_sec();
  598. RRDHOST *host;
  599. restart_after_removal:
  600. rrdhost_foreach_write(host) {
  601. if(rrdhost_should_be_removed(host, protected_host, now)) {
  602. info("Host '%s' with machine guid '%s' is obsolete - cleaning up.", host->hostname, host->machine_guid);
  603. if (rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST)
  604. #ifdef ENABLE_DBENGINE
  605. /* don't delete multi-host DB host files */
  606. && !(host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE && is_storage_engine_shared(host->storage_instance[0]))
  607. #endif
  608. )
  609. rrdhost_delete_charts(host);
  610. else
  611. rrdhost_save_charts(host);
  612. rrdhost_free(host);
  613. goto restart_after_removal;
  614. }
  615. }
  616. }
  617. // ----------------------------------------------------------------------------
  618. // RRDHOST global / startup initialization
  619. int rrd_init(char *hostname, struct rrdhost_system_info *system_info) {
  620. #ifdef ENABLE_DBENGINE
  621. storage_tiers = config_get_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  622. if(storage_tiers < 1) {
  623. error("At least 1 storage tier is required. Assuming 1.");
  624. storage_tiers = 1;
  625. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  626. }
  627. if(storage_tiers > RRD_STORAGE_TIERS) {
  628. error("Up to %d storage tier are supported. Assuming %d.", RRD_STORAGE_TIERS, RRD_STORAGE_TIERS);
  629. storage_tiers = RRD_STORAGE_TIERS;
  630. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  631. }
  632. default_rrdeng_page_fetch_timeout = (int) config_get_number(CONFIG_SECTION_DB, "dbengine page fetch timeout secs", PAGE_CACHE_FETCH_WAIT_TIMEOUT);
  633. if (default_rrdeng_page_fetch_timeout < 1) {
  634. info("'dbengine page fetch timeout secs' cannot be %d, using 1", default_rrdeng_page_fetch_timeout);
  635. default_rrdeng_page_fetch_timeout = 1;
  636. config_set_number(CONFIG_SECTION_DB, "dbengine page fetch timeout secs", default_rrdeng_page_fetch_timeout);
  637. }
  638. default_rrdeng_page_fetch_retries = (int) config_get_number(CONFIG_SECTION_DB, "dbengine page fetch retries", MAX_PAGE_CACHE_FETCH_RETRIES);
  639. if (default_rrdeng_page_fetch_retries < 1) {
  640. info("\"dbengine page fetch retries\" found in netdata.conf cannot be %d, using 1", default_rrdeng_page_fetch_retries);
  641. default_rrdeng_page_fetch_retries = 1;
  642. config_set_number(CONFIG_SECTION_DB, "dbengine page fetch retries", default_rrdeng_page_fetch_retries);
  643. }
  644. if(config_get_boolean(CONFIG_SECTION_DB, "dbengine page descriptors in file mapped memory", rrdeng_page_descr_is_mmap()) == CONFIG_BOOLEAN_YES)
  645. rrdeng_page_descr_use_mmap();
  646. else
  647. rrdeng_page_descr_use_malloc();
  648. #endif
  649. rrdset_free_obsolete_time = config_get_number(CONFIG_SECTION_DB, "cleanup obsolete charts after secs", rrdset_free_obsolete_time);
  650. // Current chart locking and invalidation scheme doesn't prevent Netdata from segmentation faults if a short
  651. // cleanup delay is set. Extensive stress tests showed that 10 seconds is quite a safe delay. Look at
  652. // https://github.com/netdata/netdata/pull/11222#issuecomment-868367920 for more information.
  653. if (rrdset_free_obsolete_time < 10) {
  654. rrdset_free_obsolete_time = 10;
  655. info("The \"cleanup obsolete charts after seconds\" option was set to 10 seconds.");
  656. config_set_number(CONFIG_SECTION_DB, "cleanup obsolete charts after secs", rrdset_free_obsolete_time);
  657. }
  658. gap_when_lost_iterations_above = (int)config_get_number(CONFIG_SECTION_DB, "gap when lost iterations above", gap_when_lost_iterations_above);
  659. if (gap_when_lost_iterations_above < 1) {
  660. gap_when_lost_iterations_above = 1;
  661. config_set_number(CONFIG_SECTION_DB, "gap when lost iterations above", gap_when_lost_iterations_above);
  662. }
  663. if (unlikely(sql_init_database(DB_CHECK_NONE, system_info ? 0 : 1))) {
  664. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  665. fatal("Failed to initialize SQLite");
  666. info("Skipping SQLITE metadata initialization since memory mode is not db engine");
  667. }
  668. health_init();
  669. rrdpush_init();
  670. debug(D_RRDHOST, "Initializing localhost with hostname '%s'", hostname);
  671. rrd_wrlock();
  672. localhost = rrdhost_create(
  673. hostname
  674. , registry_get_this_machine_hostname()
  675. , registry_get_this_machine_guid()
  676. , os_type
  677. , netdata_configured_timezone
  678. , netdata_configured_abbrev_timezone
  679. , netdata_configured_utc_offset
  680. , ""
  681. , program_name
  682. , program_version
  683. , default_rrd_update_every
  684. , default_rrd_history_entries
  685. , default_rrd_memory_mode
  686. , default_health_enabled
  687. , default_rrdpush_enabled
  688. , default_rrdpush_destination
  689. , default_rrdpush_api_key
  690. , default_rrdpush_send_charts_matching
  691. , system_info
  692. , 1
  693. );
  694. if (unlikely(!localhost)) {
  695. rrd_unlock();
  696. return 1;
  697. }
  698. #ifdef ENABLE_DBENGINE
  699. rrdeng_page_descr_aral_go_singlethreaded();
  700. int created_tiers = 0;
  701. char dbenginepath[FILENAME_MAX + 1];
  702. char dbengineconfig[200 + 1];
  703. for(int tier = 0; tier < storage_tiers ;tier++) {
  704. if(tier == 0)
  705. snprintfz(dbenginepath, FILENAME_MAX, "%s/dbengine", localhost->cache_dir);
  706. else
  707. snprintfz(dbenginepath, FILENAME_MAX, "%s/dbengine-tier%d", localhost->cache_dir, tier);
  708. int ret = mkdir(dbenginepath, 0775);
  709. if (ret != 0 && errno != EEXIST) {
  710. error("DBENGINE on '%s': cannot create directory '%s'", localhost->hostname, dbenginepath);
  711. break;
  712. }
  713. int page_cache_mb = default_rrdeng_page_cache_mb;
  714. int disk_space_mb = default_multidb_disk_quota_mb;
  715. int grouping_iterations = storage_tiers_grouping_iterations[tier];
  716. RRD_BACKFILL backfill = storage_tiers_backfill[tier];
  717. if(tier > 0) {
  718. snprintfz(dbengineconfig, 200, "dbengine tier %d page cache size MB", tier);
  719. page_cache_mb = config_get_number(CONFIG_SECTION_DB, dbengineconfig, page_cache_mb);
  720. snprintfz(dbengineconfig, 200, "dbengine tier %d multihost disk space MB", tier);
  721. disk_space_mb = config_get_number(CONFIG_SECTION_DB, dbengineconfig, disk_space_mb);
  722. snprintfz(dbengineconfig, 200, "dbengine tier %d update every iterations", tier);
  723. grouping_iterations = config_get_number(CONFIG_SECTION_DB, dbengineconfig, grouping_iterations);
  724. if(grouping_iterations < 2) {
  725. grouping_iterations = 2;
  726. config_set_number(CONFIG_SECTION_DB, dbengineconfig, grouping_iterations);
  727. error("DBENGINE on '%s': 'dbegnine tier %d update every iterations' cannot be less than 2. Assuming 2.", localhost->hostname, tier);
  728. }
  729. snprintfz(dbengineconfig, 200, "dbengine tier %d backfill", tier);
  730. const char *bf = config_get(CONFIG_SECTION_DB, dbengineconfig, backfill == RRD_BACKFILL_NEW ? "new" : backfill == RRD_BACKFILL_FULL ? "full" : "none");
  731. if(strcmp(bf, "new") == 0) backfill = RRD_BACKFILL_NEW;
  732. else if(strcmp(bf, "full") == 0) backfill = RRD_BACKFILL_FULL;
  733. else if(strcmp(bf, "none") == 0) backfill = RRD_BACKFILL_NONE;
  734. else {
  735. error("DBENGINE: unknown backfill value '%s', assuming 'new'", bf);
  736. config_set(CONFIG_SECTION_DB, dbengineconfig, "new");
  737. backfill = RRD_BACKFILL_NEW;
  738. }
  739. }
  740. storage_tiers_grouping_iterations[tier] = grouping_iterations;
  741. storage_tiers_backfill[tier] = backfill;
  742. if(tier > 0 && get_tier_grouping(tier) > 65535) {
  743. storage_tiers_grouping_iterations[tier] = 1;
  744. error("DBENGINE on '%s': dbengine tier %d gives aggregation of more than 65535 points of tier 0. Disabling tiers above %d", localhost->hostname, tier, tier);
  745. break;
  746. }
  747. internal_error(true, "DBENGINE tier %d grouping iterations is set to %d", tier, storage_tiers_grouping_iterations[tier]);
  748. ret = rrdeng_init(NULL, NULL, dbenginepath, page_cache_mb, disk_space_mb, tier);
  749. if(ret != 0) {
  750. error("DBENGINE on '%s': Failed to initialize multi-host database tier %d on path '%s'",
  751. localhost->hostname, tier, dbenginepath);
  752. break;
  753. }
  754. else
  755. created_tiers++;
  756. }
  757. if(created_tiers && created_tiers < storage_tiers) {
  758. error("DBENGINE on '%s': Managed to create %d tiers instead of %d. Continuing with %d available.",
  759. localhost->hostname, created_tiers, storage_tiers, created_tiers);
  760. storage_tiers = created_tiers;
  761. }
  762. else if(!created_tiers) {
  763. error("DBENGINE on '%s', with machine guid '%s', failed to initialize databases at '%s'.",
  764. localhost->hostname, localhost->machine_guid, localhost->cache_dir);
  765. rrdhost_free(localhost);
  766. localhost = NULL;
  767. rrd_unlock();
  768. fatal("DBENGINE: Failed to be initialized.");
  769. }
  770. rrdeng_page_descr_aral_go_multithreaded();
  771. #else
  772. storage_tiers = config_get_number(CONFIG_SECTION_DB, "storage tiers", 1);
  773. if(storage_tiers != 1) {
  774. error("DBENGINE is not available on '%s', so only 1 database tier can be supported.", localhost->hostname);
  775. storage_tiers = 1;
  776. config_set_number(CONFIG_SECTION_DB, "storage tiers", storage_tiers);
  777. }
  778. #endif
  779. if (likely(system_info))
  780. migrate_localhost(&localhost->host_uuid);
  781. sql_aclk_sync_init();
  782. rrd_unlock();
  783. web_client_api_v1_management_init();
  784. return localhost==NULL;
  785. }
  786. // ----------------------------------------------------------------------------
  787. // RRDHOST - lock validations
  788. // there are only used when NETDATA_INTERNAL_CHECKS is set
  789. void __rrdhost_check_rdlock(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
  790. debug(D_RRDHOST, "Checking read lock on host '%s'", host->hostname);
  791. int ret = netdata_rwlock_trywrlock(&host->rrdhost_rwlock);
  792. if(ret == 0)
  793. fatal("RRDHOST '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
  794. }
  795. void __rrdhost_check_wrlock(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
  796. debug(D_RRDHOST, "Checking write lock on host '%s'", host->hostname);
  797. int ret = netdata_rwlock_tryrdlock(&host->rrdhost_rwlock);
  798. if(ret == 0)
  799. fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
  800. }
  801. void __rrd_check_rdlock(const char *file, const char *function, const unsigned long line) {
  802. debug(D_RRDHOST, "Checking read lock on all RRDs");
  803. int ret = netdata_rwlock_trywrlock(&rrd_rwlock);
  804. if(ret == 0)
  805. fatal("RRDs should be read-locked, but it are not, at function %s() at line %lu of file '%s'", function, line, file);
  806. }
  807. void __rrd_check_wrlock(const char *file, const char *function, const unsigned long line) {
  808. debug(D_RRDHOST, "Checking write lock on all RRDs");
  809. int ret = netdata_rwlock_tryrdlock(&rrd_rwlock);
  810. if(ret == 0)
  811. fatal("RRDs should be write-locked, but it are not, at function %s() at line %lu of file '%s'", function, line, file);
  812. }
  813. // ----------------------------------------------------------------------------
  814. // RRDHOST - free
  815. void rrdhost_system_info_free(struct rrdhost_system_info *system_info) {
  816. info("SYSTEM_INFO: free %p", system_info);
  817. if(likely(system_info)) {
  818. freez(system_info->cloud_provider_type);
  819. freez(system_info->cloud_instance_type);
  820. freez(system_info->cloud_instance_region);
  821. freez(system_info->host_os_name);
  822. freez(system_info->host_os_id);
  823. freez(system_info->host_os_id_like);
  824. freez(system_info->host_os_version);
  825. freez(system_info->host_os_version_id);
  826. freez(system_info->host_os_detection);
  827. freez(system_info->host_cores);
  828. freez(system_info->host_cpu_freq);
  829. freez(system_info->host_ram_total);
  830. freez(system_info->host_disk_space);
  831. freez(system_info->container_os_name);
  832. freez(system_info->container_os_id);
  833. freez(system_info->container_os_id_like);
  834. freez(system_info->container_os_version);
  835. freez(system_info->container_os_version_id);
  836. freez(system_info->container_os_detection);
  837. freez(system_info->kernel_name);
  838. freez(system_info->kernel_version);
  839. freez(system_info->architecture);
  840. freez(system_info->virtualization);
  841. freez(system_info->virt_detection);
  842. freez(system_info->container);
  843. freez(system_info->container_detection);
  844. freez(system_info->is_k8s_node);
  845. freez(system_info->install_type);
  846. freez(system_info->prebuilt_arch);
  847. freez(system_info->prebuilt_dist);
  848. freez(system_info);
  849. }
  850. }
  851. void destroy_receiver_state(struct receiver_state *rpt);
  852. void rrdhost_free(RRDHOST *host) {
  853. if(!host) return;
  854. info("Freeing all memory for host '%s'...", host->hostname);
  855. rrd_check_wrlock(); // make sure the RRDs are write locked
  856. rrdhost_wrlock(host);
  857. ml_delete_host(host);
  858. rrdhost_unlock(host);
  859. // ------------------------------------------------------------------------
  860. // clean up streaming
  861. rrdpush_sender_thread_stop(host); // stop a possibly running thread
  862. cbuffer_free(host->sender->buffer);
  863. buffer_free(host->sender->build);
  864. #ifdef ENABLE_COMPRESSION
  865. if (host->sender->compressor)
  866. host->sender->compressor->destroy(&host->sender->compressor);
  867. #endif
  868. freez(host->sender);
  869. host->sender = NULL;
  870. if (netdata_exit) {
  871. netdata_mutex_lock(&host->receiver_lock);
  872. if (host->receiver) {
  873. if (!host->receiver->exited)
  874. netdata_thread_cancel(host->receiver->thread);
  875. netdata_mutex_unlock(&host->receiver_lock);
  876. struct receiver_state *rpt = host->receiver;
  877. while (host->receiver && !rpt->exited)
  878. sleep_usec(50 * USEC_PER_MS);
  879. // If the receiver detached from the host then its thread will destroy the state
  880. if (host->receiver == rpt)
  881. destroy_receiver_state(host->receiver);
  882. }
  883. else
  884. netdata_mutex_unlock(&host->receiver_lock);
  885. }
  886. rrdhost_wrlock(host); // lock this RRDHOST
  887. #ifdef ENABLE_ACLK
  888. struct aclk_database_worker_config *wc = host->dbsync_worker;
  889. if (wc && !netdata_exit) {
  890. struct aclk_database_cmd cmd;
  891. memset(&cmd, 0, sizeof(cmd));
  892. cmd.opcode = ACLK_DATABASE_ORPHAN_HOST;
  893. struct aclk_completion compl ;
  894. init_aclk_completion(&compl );
  895. cmd.completion = &compl ;
  896. aclk_database_enq_cmd(wc, &cmd);
  897. wait_for_aclk_completion(&compl );
  898. destroy_aclk_completion(&compl );
  899. }
  900. #endif
  901. // ------------------------------------------------------------------------
  902. // release its children resources
  903. #ifdef ENABLE_DBENGINE
  904. for(int tier = 0; tier < storage_tiers ;tier++) {
  905. if(host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE &&
  906. host->storage_instance[tier] &&
  907. !is_storage_engine_shared(host->storage_instance[tier]))
  908. rrdeng_prepare_exit((struct rrdengine_instance *)host->storage_instance[tier]);
  909. }
  910. #endif
  911. while(host->rrdset_root)
  912. rrdset_free(host->rrdset_root);
  913. freez(host->exporting_flags);
  914. while(host->alarms)
  915. rrdcalc_unlink_and_free(host, host->alarms);
  916. RRDCALC *rc,*nc;
  917. for(rc = host->alarms_with_foreach; rc ; rc = nc) {
  918. nc = rc->next;
  919. rrdcalc_free(rc);
  920. }
  921. host->alarms_with_foreach = NULL;
  922. while(host->templates)
  923. rrdcalctemplate_unlink_and_free(host, host->templates);
  924. RRDCALCTEMPLATE *rt,*next;
  925. for(rt = host->alarms_template_with_foreach; rt ; rt = next) {
  926. next = rt->next;
  927. rrdcalctemplate_free(rt);
  928. }
  929. host->alarms_template_with_foreach = NULL;
  930. debug(D_RRD_CALLS, "RRDHOST: Cleaning up remaining host variables for host '%s'", host->hostname);
  931. rrdvar_free_remaining_variables(host, &host->rrdvar_root_index);
  932. health_alarm_log_free(host);
  933. #ifdef ENABLE_DBENGINE
  934. for(int tier = 0; tier < storage_tiers ;tier++) {
  935. if(host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE &&
  936. host->storage_instance[tier] &&
  937. !is_storage_engine_shared(host->storage_instance[tier]))
  938. rrdeng_exit((struct rrdengine_instance *)host->storage_instance[tier]);
  939. }
  940. #endif
  941. // ------------------------------------------------------------------------
  942. // remove it from the indexes
  943. if(rrdhost_index_del(host) != host)
  944. error("RRDHOST '%s' removed from index, deleted the wrong entry.", host->hostname);
  945. // ------------------------------------------------------------------------
  946. // unlink it from the host
  947. if(host == localhost) {
  948. localhost = host->next;
  949. }
  950. else {
  951. // find the previous one
  952. RRDHOST *h;
  953. for(h = localhost; h && h->next != host ; h = h->next) ;
  954. // bypass it
  955. if(h) h->next = host->next;
  956. else error("Request to free RRDHOST '%s': cannot find it", host->hostname);
  957. }
  958. // ------------------------------------------------------------------------
  959. // free it
  960. pthread_mutex_destroy(&host->aclk_state_lock);
  961. freez(host->aclk_state.claimed_id);
  962. freez(host->aclk_state.prev_claimed_id);
  963. freez((void *)host->tags);
  964. rrdlabels_destroy(host->host_labels);
  965. freez((void *)host->os);
  966. freez((void *)host->timezone);
  967. freez((void *)host->abbrev_timezone);
  968. freez(host->program_version);
  969. freez(host->program_name);
  970. rrdhost_system_info_free(host->system_info);
  971. freez(host->cache_dir);
  972. freez(host->varlib_dir);
  973. freez(host->rrdpush_send_api_key);
  974. freez(host->rrdpush_send_destination);
  975. freez(host->health_default_exec);
  976. freez(host->health_default_recipient);
  977. freez(host->health_log_filename);
  978. freez(host->hostname);
  979. freez(host->registry_hostname);
  980. simple_pattern_free(host->rrdpush_send_charts_matching);
  981. rrdhost_unlock(host);
  982. netdata_rwlock_destroy(&host->health_log.alarm_log_rwlock);
  983. netdata_rwlock_destroy(&host->rrdhost_rwlock);
  984. freez(host->node_id);
  985. freez(host);
  986. #ifdef ENABLE_ACLK
  987. if (wc)
  988. wc->is_orphan = 0;
  989. #endif
  990. rrd_hosts_available--;
  991. }
  992. void rrdhost_free_all(void) {
  993. rrd_wrlock();
  994. /* Make sure child-hosts are released before the localhost. */
  995. while(localhost->next) rrdhost_free(localhost->next);
  996. rrdhost_free(localhost);
  997. rrd_unlock();
  998. }
  999. // ----------------------------------------------------------------------------
  1000. // RRDHOST - save host files
  1001. void rrdhost_save_charts(RRDHOST *host) {
  1002. if(!host) return;
  1003. info("Saving/Closing database of host '%s'...", host->hostname);
  1004. RRDSET *st;
  1005. // we get a write lock
  1006. // to ensure only one thread is saving the database
  1007. rrdhost_wrlock(host);
  1008. rrdset_foreach_write(st, host) {
  1009. rrdset_rdlock(st);
  1010. rrdset_save(st);
  1011. rrdset_unlock(st);
  1012. }
  1013. rrdhost_unlock(host);
  1014. }
  1015. static void rrdhost_load_auto_labels(void) {
  1016. DICTIONARY *labels = localhost->host_labels;
  1017. if (localhost->system_info->cloud_provider_type)
  1018. rrdlabels_add(labels, "_cloud_provider_type", localhost->system_info->cloud_provider_type, RRDLABEL_SRC_AUTO);
  1019. if (localhost->system_info->cloud_instance_type)
  1020. rrdlabels_add(labels, "_cloud_instance_type", localhost->system_info->cloud_instance_type, RRDLABEL_SRC_AUTO);
  1021. if (localhost->system_info->cloud_instance_region)
  1022. rrdlabels_add(
  1023. labels, "_cloud_instance_region", localhost->system_info->cloud_instance_region, RRDLABEL_SRC_AUTO);
  1024. if (localhost->system_info->host_os_name)
  1025. rrdlabels_add(labels, "_os_name", localhost->system_info->host_os_name, RRDLABEL_SRC_AUTO);
  1026. if (localhost->system_info->host_os_version)
  1027. rrdlabels_add(labels, "_os_version", localhost->system_info->host_os_version, RRDLABEL_SRC_AUTO);
  1028. if (localhost->system_info->kernel_version)
  1029. rrdlabels_add(labels, "_kernel_version", localhost->system_info->kernel_version, RRDLABEL_SRC_AUTO);
  1030. if (localhost->system_info->host_cores)
  1031. rrdlabels_add(labels, "_system_cores", localhost->system_info->host_cores, RRDLABEL_SRC_AUTO);
  1032. if (localhost->system_info->host_cpu_freq)
  1033. rrdlabels_add(labels, "_system_cpu_freq", localhost->system_info->host_cpu_freq, RRDLABEL_SRC_AUTO);
  1034. if (localhost->system_info->host_ram_total)
  1035. rrdlabels_add(labels, "_system_ram_total", localhost->system_info->host_ram_total, RRDLABEL_SRC_AUTO);
  1036. if (localhost->system_info->host_disk_space)
  1037. rrdlabels_add(labels, "_system_disk_space", localhost->system_info->host_disk_space, RRDLABEL_SRC_AUTO);
  1038. if (localhost->system_info->architecture)
  1039. rrdlabels_add(labels, "_architecture", localhost->system_info->architecture, RRDLABEL_SRC_AUTO);
  1040. if (localhost->system_info->virtualization)
  1041. rrdlabels_add(labels, "_virtualization", localhost->system_info->virtualization, RRDLABEL_SRC_AUTO);
  1042. if (localhost->system_info->container)
  1043. rrdlabels_add(labels, "_container", localhost->system_info->container, RRDLABEL_SRC_AUTO);
  1044. if (localhost->system_info->container_detection)
  1045. rrdlabels_add(labels, "_container_detection", localhost->system_info->container_detection, RRDLABEL_SRC_AUTO);
  1046. if (localhost->system_info->virt_detection)
  1047. rrdlabels_add(labels, "_virt_detection", localhost->system_info->virt_detection, RRDLABEL_SRC_AUTO);
  1048. if (localhost->system_info->is_k8s_node)
  1049. rrdlabels_add(labels, "_is_k8s_node", localhost->system_info->is_k8s_node, RRDLABEL_SRC_AUTO);
  1050. if (localhost->system_info->install_type)
  1051. rrdlabels_add(labels, "_install_type", localhost->system_info->install_type, RRDLABEL_SRC_AUTO);
  1052. if (localhost->system_info->prebuilt_arch)
  1053. rrdlabels_add(labels, "_prebuilt_arch", localhost->system_info->prebuilt_arch, RRDLABEL_SRC_AUTO);
  1054. if (localhost->system_info->prebuilt_dist)
  1055. rrdlabels_add(labels, "_prebuilt_dist", localhost->system_info->prebuilt_dist, RRDLABEL_SRC_AUTO);
  1056. add_aclk_host_labels();
  1057. rrdlabels_add(
  1058. labels, "_is_parent", (localhost->next || configured_as_parent()) ? "true" : "false", RRDLABEL_SRC_AUTO);
  1059. if (localhost->rrdpush_send_destination)
  1060. rrdlabels_add(labels, "_streams_to", localhost->rrdpush_send_destination, RRDLABEL_SRC_AUTO);
  1061. }
  1062. static void rrdhost_load_config_labels(void) {
  1063. int status = config_load(NULL, 1, CONFIG_SECTION_HOST_LABEL);
  1064. if(!status) {
  1065. char *filename = CONFIG_DIR "/" CONFIG_FILENAME;
  1066. error("RRDLABEL: Cannot reload the configuration file '%s', using labels in memory", filename);
  1067. }
  1068. struct section *co = appconfig_get_section(&netdata_config, CONFIG_SECTION_HOST_LABEL);
  1069. if(co) {
  1070. config_section_wrlock(co);
  1071. struct config_option *cv;
  1072. for(cv = co->values; cv ; cv = cv->next) {
  1073. rrdlabels_add(localhost->host_labels, cv->name, cv->value, RRDLABEL_SRC_CONFIG);
  1074. cv->flags |= CONFIG_VALUE_USED;
  1075. }
  1076. config_section_unlock(co);
  1077. }
  1078. }
  1079. static void rrdhost_load_kubernetes_labels(void) {
  1080. char label_script[sizeof(char) * (strlen(netdata_configured_primary_plugins_dir) + strlen("get-kubernetes-labels.sh") + 2)];
  1081. sprintf(label_script, "%s/%s", netdata_configured_primary_plugins_dir, "get-kubernetes-labels.sh");
  1082. if (unlikely(access(label_script, R_OK) != 0)) {
  1083. error("Kubernetes pod label fetching script %s not found.",label_script);
  1084. return;
  1085. }
  1086. debug(D_RRDHOST, "Attempting to fetch external labels via %s", label_script);
  1087. pid_t pid;
  1088. FILE *fp = mypopen(label_script, &pid);
  1089. if(!fp) return;
  1090. char buffer[1000 + 1];
  1091. while (fgets(buffer, 1000, fp) != NULL)
  1092. rrdlabels_add_pair(localhost->host_labels, buffer, RRDLABEL_SRC_AUTO|RRDLABEL_SRC_K8S);
  1093. // Non-zero exit code means that all the script output is error messages. We've shown already any message that didn't include a ':'
  1094. // Here we'll inform with an ERROR that the script failed, show whatever (if anything) was added to the list of labels, free the memory and set the return to null
  1095. int rc = mypclose(fp, pid);
  1096. if(rc) error("%s exited abnormally. Failed to get kubernetes labels.", label_script);
  1097. }
  1098. void reload_host_labels(void) {
  1099. if(!localhost->host_labels)
  1100. localhost->host_labels = rrdlabels_create();
  1101. rrdlabels_unmark_all(localhost->host_labels);
  1102. // priority is important here
  1103. rrdhost_load_config_labels();
  1104. rrdhost_load_kubernetes_labels();
  1105. rrdhost_load_auto_labels();
  1106. rrdlabels_remove_all_unmarked(localhost->host_labels);
  1107. health_label_log_save(localhost);
  1108. /* TODO-GAPS - fix this so that it looks properly at the state and version of the sender
  1109. if(localhost->rrdpush_send_enabled && localhost->rrdpush_sender_buffer){
  1110. localhost->labels.labels_flag |= RRDHOST_FLAG_STREAM_LABELS_UPDATE;
  1111. rrdpush_send_labels(localhost);
  1112. }
  1113. */
  1114. health_reload();
  1115. }
  1116. // ----------------------------------------------------------------------------
  1117. // RRDHOST - delete host files
  1118. void rrdhost_delete_charts(RRDHOST *host) {
  1119. if(!host) return;
  1120. info("Deleting database of host '%s'...", host->hostname);
  1121. RRDSET *st;
  1122. // we get a write lock
  1123. // to ensure only one thread is saving the database
  1124. rrdhost_wrlock(host);
  1125. rrdset_foreach_write(st, host) {
  1126. rrdset_rdlock(st);
  1127. rrdset_delete(st);
  1128. rrdset_unlock(st);
  1129. }
  1130. recursively_delete_dir(host->cache_dir, "left over host");
  1131. rrdhost_unlock(host);
  1132. }
  1133. // ----------------------------------------------------------------------------
  1134. // RRDHOST - cleanup host files
  1135. void rrdhost_cleanup_charts(RRDHOST *host) {
  1136. if(!host) return;
  1137. info("Cleaning up database of host '%s'...", host->hostname);
  1138. RRDSET *st;
  1139. uint32_t rrdhost_delete_obsolete_charts = rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS);
  1140. // we get a write lock
  1141. // to ensure only one thread is saving the database
  1142. rrdhost_wrlock(host);
  1143. rrdset_foreach_write(st, host) {
  1144. rrdset_rdlock(st);
  1145. if(rrdhost_delete_obsolete_charts && rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE))
  1146. rrdset_delete(st);
  1147. else if(rrdhost_delete_obsolete_charts && rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE_DIMENSIONS))
  1148. rrdset_delete_obsolete_dimensions(st);
  1149. else
  1150. rrdset_save(st);
  1151. rrdset_unlock(st);
  1152. }
  1153. rrdhost_unlock(host);
  1154. }
  1155. // ----------------------------------------------------------------------------
  1156. // RRDHOST - save all hosts to disk
  1157. void rrdhost_save_all(void) {
  1158. info("Saving database [%zu hosts(s)]...", rrd_hosts_available);
  1159. rrd_rdlock();
  1160. RRDHOST *host;
  1161. rrdhost_foreach_read(host)
  1162. rrdhost_save_charts(host);
  1163. rrd_unlock();
  1164. }
  1165. // ----------------------------------------------------------------------------
  1166. // RRDHOST - save or delete all hosts from disk
  1167. void rrdhost_cleanup_all(void) {
  1168. info("Cleaning up database [%zu hosts(s)]...", rrd_hosts_available);
  1169. rrd_rdlock();
  1170. RRDHOST *host;
  1171. rrdhost_foreach_read(host) {
  1172. if (host != localhost && rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_ORPHAN_HOST) && !host->receiver
  1173. #ifdef ENABLE_DBENGINE
  1174. /* don't delete multi-host DB host files */
  1175. && !(host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE && is_storage_engine_shared(host->storage_instance[0]))
  1176. #endif
  1177. )
  1178. rrdhost_delete_charts(host);
  1179. else
  1180. rrdhost_cleanup_charts(host);
  1181. }
  1182. rrd_unlock();
  1183. }
  1184. // ----------------------------------------------------------------------------
  1185. // RRDHOST - save or delete all the host charts from disk
  1186. void rrdhost_cleanup_obsolete_charts(RRDHOST *host) {
  1187. time_t now = now_realtime_sec();
  1188. RRDSET *st;
  1189. uint32_t rrdhost_delete_obsolete_charts = rrdhost_flag_check(host, RRDHOST_FLAG_DELETE_OBSOLETE_CHARTS);
  1190. restart_after_removal:
  1191. rrdset_foreach_write(st, host) {
  1192. if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)
  1193. && st->last_accessed_time + rrdset_free_obsolete_time < now
  1194. && st->last_updated.tv_sec + rrdset_free_obsolete_time < now
  1195. && st->last_collected_time.tv_sec + rrdset_free_obsolete_time < now
  1196. )) {
  1197. st->rrdhost->obsolete_charts_count--;
  1198. #ifdef ENABLE_DBENGINE
  1199. if(st->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
  1200. RRDDIM *rd, *last;
  1201. rrdset_flag_set(st, RRDSET_FLAG_ARCHIVED);
  1202. while (st->variables) rrdsetvar_free(st->variables);
  1203. while (st->alarms) rrdsetcalc_unlink(st->alarms);
  1204. rrdset_wrlock(st);
  1205. for (rd = st->dimensions, last = NULL ; likely(rd) ; ) {
  1206. if (rrddim_flag_check(rd, RRDDIM_FLAG_ARCHIVED)) {
  1207. last = rd;
  1208. rd = rd->next;
  1209. continue;
  1210. }
  1211. if (rrddim_flag_check(rd, RRDDIM_FLAG_ACLK)) {
  1212. last = rd;
  1213. rd = rd->next;
  1214. continue;
  1215. }
  1216. rrddim_flag_set(rd, RRDDIM_FLAG_ARCHIVED);
  1217. while (rd->variables)
  1218. rrddimvar_free(rd->variables);
  1219. if (rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
  1220. rrddim_flag_clear(rd, RRDDIM_FLAG_OBSOLETE);
  1221. /* only a collector can mark a chart as obsolete, so we must remove the reference */
  1222. size_t tiers_available = 0, tiers_said_yes = 0;
  1223. for(int tier = 0; tier < storage_tiers ;tier++) {
  1224. if(rd->tiers[tier]) {
  1225. tiers_available++;
  1226. if(rd->tiers[tier]->collect_ops.finalize(rd->tiers[tier]->db_collection_handle))
  1227. tiers_said_yes++;
  1228. rd->tiers[tier]->db_collection_handle = NULL;
  1229. }
  1230. }
  1231. if (tiers_available == tiers_said_yes && tiers_said_yes) {
  1232. /* This metric has no data and no references */
  1233. delete_dimension_uuid(&rd->metric_uuid);
  1234. rrddim_free(st, rd);
  1235. if (unlikely(!last)) {
  1236. rd = st->dimensions;
  1237. }
  1238. else {
  1239. rd = last->next;
  1240. }
  1241. continue;
  1242. }
  1243. #ifdef ENABLE_ACLK
  1244. else
  1245. queue_dimension_to_aclk(rd, rd->last_collected_time.tv_sec);
  1246. #endif
  1247. }
  1248. last = rd;
  1249. rd = rd->next;
  1250. }
  1251. rrdset_unlock(st);
  1252. debug(D_RRD_CALLS, "RRDSET: Cleaning up remaining chart variables for host '%s', chart '%s'", host->hostname, st->id);
  1253. rrdvar_free_remaining_variables(host, &st->rrdvar_root_index);
  1254. rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE);
  1255. if (st->dimensions) {
  1256. /* If the chart still has dimensions don't delete it from the metadata log */
  1257. continue;
  1258. }
  1259. }
  1260. #endif
  1261. rrdset_rdlock(st);
  1262. if(rrdhost_delete_obsolete_charts)
  1263. rrdset_delete(st);
  1264. else
  1265. rrdset_save(st);
  1266. rrdset_unlock(st);
  1267. rrdset_free(st);
  1268. goto restart_after_removal;
  1269. }
  1270. #ifdef ENABLE_ACLK
  1271. else
  1272. sql_check_chart_liveness(st);
  1273. #endif
  1274. }
  1275. }
  1276. void rrdset_check_obsoletion(RRDHOST *host)
  1277. {
  1278. RRDSET *st;
  1279. time_t last_entry_t;
  1280. rrdset_foreach_read(st, host) {
  1281. last_entry_t = rrdset_last_entry_t(st);
  1282. if (last_entry_t && last_entry_t < host->senders_connect_time) {
  1283. rrdset_is_obsolete(st);
  1284. }
  1285. }
  1286. }
  1287. void rrd_cleanup_obsolete_charts()
  1288. {
  1289. rrd_rdlock();
  1290. RRDHOST *host;
  1291. rrdhost_foreach_read(host)
  1292. {
  1293. if (host->obsolete_charts_count) {
  1294. rrdhost_wrlock(host);
  1295. rrdhost_cleanup_obsolete_charts(host);
  1296. rrdhost_unlock(host);
  1297. }
  1298. if ( host != localhost &&
  1299. host->trigger_chart_obsoletion_check &&
  1300. ((host->senders_last_chart_command &&
  1301. host->senders_last_chart_command + host->health_delay_up_to < now_realtime_sec())
  1302. || (host->senders_connect_time + 300 < now_realtime_sec())) ) {
  1303. rrdhost_rdlock(host);
  1304. rrdset_check_obsoletion(host);
  1305. rrdhost_unlock(host);
  1306. host->trigger_chart_obsoletion_check = 0;
  1307. }
  1308. }
  1309. rrd_unlock();
  1310. }
  1311. // ----------------------------------------------------------------------------
  1312. // RRDHOST - set system info from environment variables
  1313. // system_info fields must be heap allocated or NULL
  1314. int rrdhost_set_system_info_variable(struct rrdhost_system_info *system_info, char *name, char *value) {
  1315. int res = 0;
  1316. if (!strcmp(name, "NETDATA_PROTOCOL_VERSION"))
  1317. return res;
  1318. else if(!strcmp(name, "NETDATA_INSTANCE_CLOUD_TYPE")){
  1319. freez(system_info->cloud_provider_type);
  1320. system_info->cloud_provider_type = strdupz(value);
  1321. }
  1322. else if(!strcmp(name, "NETDATA_INSTANCE_CLOUD_INSTANCE_TYPE")){
  1323. freez(system_info->cloud_instance_type);
  1324. system_info->cloud_instance_type = strdupz(value);
  1325. }
  1326. else if(!strcmp(name, "NETDATA_INSTANCE_CLOUD_INSTANCE_REGION")){
  1327. freez(system_info->cloud_instance_region);
  1328. system_info->cloud_instance_region = strdupz(value);
  1329. }
  1330. else if(!strcmp(name, "NETDATA_CONTAINER_OS_NAME")){
  1331. freez(system_info->container_os_name);
  1332. system_info->container_os_name = strdupz(value);
  1333. }
  1334. else if(!strcmp(name, "NETDATA_CONTAINER_OS_ID")){
  1335. freez(system_info->container_os_id);
  1336. system_info->container_os_id = strdupz(value);
  1337. }
  1338. else if(!strcmp(name, "NETDATA_CONTAINER_OS_ID_LIKE")){
  1339. freez(system_info->container_os_id_like);
  1340. system_info->container_os_id_like = strdupz(value);
  1341. }
  1342. else if(!strcmp(name, "NETDATA_CONTAINER_OS_VERSION")){
  1343. freez(system_info->container_os_version);
  1344. system_info->container_os_version = strdupz(value);
  1345. }
  1346. else if(!strcmp(name, "NETDATA_CONTAINER_OS_VERSION_ID")){
  1347. freez(system_info->container_os_version_id);
  1348. system_info->container_os_version_id = strdupz(value);
  1349. }
  1350. else if(!strcmp(name, "NETDATA_CONTAINER_OS_DETECTION")){
  1351. freez(system_info->container_os_detection);
  1352. system_info->container_os_detection = strdupz(value);
  1353. }
  1354. else if(!strcmp(name, "NETDATA_HOST_OS_NAME")){
  1355. freez(system_info->host_os_name);
  1356. system_info->host_os_name = strdupz(value);
  1357. json_fix_string(system_info->host_os_name);
  1358. }
  1359. else if(!strcmp(name, "NETDATA_HOST_OS_ID")){
  1360. freez(system_info->host_os_id);
  1361. system_info->host_os_id = strdupz(value);
  1362. }
  1363. else if(!strcmp(name, "NETDATA_HOST_OS_ID_LIKE")){
  1364. freez(system_info->host_os_id_like);
  1365. system_info->host_os_id_like = strdupz(value);
  1366. }
  1367. else if(!strcmp(name, "NETDATA_HOST_OS_VERSION")){
  1368. freez(system_info->host_os_version);
  1369. system_info->host_os_version = strdupz(value);
  1370. }
  1371. else if(!strcmp(name, "NETDATA_HOST_OS_VERSION_ID")){
  1372. freez(system_info->host_os_version_id);
  1373. system_info->host_os_version_id = strdupz(value);
  1374. }
  1375. else if(!strcmp(name, "NETDATA_HOST_OS_DETECTION")){
  1376. freez(system_info->host_os_detection);
  1377. system_info->host_os_detection = strdupz(value);
  1378. }
  1379. else if(!strcmp(name, "NETDATA_SYSTEM_KERNEL_NAME")){
  1380. freez(system_info->kernel_name);
  1381. system_info->kernel_name = strdupz(value);
  1382. }
  1383. else if(!strcmp(name, "NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT")){
  1384. freez(system_info->host_cores);
  1385. system_info->host_cores = strdupz(value);
  1386. }
  1387. else if(!strcmp(name, "NETDATA_SYSTEM_CPU_FREQ")){
  1388. freez(system_info->host_cpu_freq);
  1389. system_info->host_cpu_freq = strdupz(value);
  1390. }
  1391. else if(!strcmp(name, "NETDATA_SYSTEM_TOTAL_RAM")){
  1392. freez(system_info->host_ram_total);
  1393. system_info->host_ram_total = strdupz(value);
  1394. }
  1395. else if(!strcmp(name, "NETDATA_SYSTEM_TOTAL_DISK_SIZE")){
  1396. freez(system_info->host_disk_space);
  1397. system_info->host_disk_space = strdupz(value);
  1398. }
  1399. else if(!strcmp(name, "NETDATA_SYSTEM_KERNEL_VERSION")){
  1400. freez(system_info->kernel_version);
  1401. system_info->kernel_version = strdupz(value);
  1402. }
  1403. else if(!strcmp(name, "NETDATA_SYSTEM_ARCHITECTURE")){
  1404. freez(system_info->architecture);
  1405. system_info->architecture = strdupz(value);
  1406. }
  1407. else if(!strcmp(name, "NETDATA_SYSTEM_VIRTUALIZATION")){
  1408. freez(system_info->virtualization);
  1409. system_info->virtualization = strdupz(value);
  1410. }
  1411. else if(!strcmp(name, "NETDATA_SYSTEM_VIRT_DETECTION")){
  1412. freez(system_info->virt_detection);
  1413. system_info->virt_detection = strdupz(value);
  1414. }
  1415. else if(!strcmp(name, "NETDATA_SYSTEM_CONTAINER")){
  1416. freez(system_info->container);
  1417. system_info->container = strdupz(value);
  1418. }
  1419. else if(!strcmp(name, "NETDATA_SYSTEM_CONTAINER_DETECTION")){
  1420. freez(system_info->container_detection);
  1421. system_info->container_detection = strdupz(value);
  1422. }
  1423. else if(!strcmp(name, "NETDATA_HOST_IS_K8S_NODE")){
  1424. freez(system_info->is_k8s_node);
  1425. system_info->is_k8s_node = strdupz(value);
  1426. }
  1427. else if (!strcmp(name, "NETDATA_SYSTEM_CPU_VENDOR"))
  1428. return res;
  1429. else if (!strcmp(name, "NETDATA_SYSTEM_CPU_MODEL"))
  1430. return res;
  1431. else if (!strcmp(name, "NETDATA_SYSTEM_CPU_DETECTION"))
  1432. return res;
  1433. else if (!strcmp(name, "NETDATA_SYSTEM_RAM_DETECTION"))
  1434. return res;
  1435. else if (!strcmp(name, "NETDATA_SYSTEM_DISK_DETECTION"))
  1436. return res;
  1437. else if (!strcmp(name, "NETDATA_CONTAINER_IS_OFFICIAL_IMAGE"))
  1438. return res;
  1439. else {
  1440. res = 1;
  1441. }
  1442. return res;
  1443. }
  1444. /**
  1445. * Alarm Compare ID
  1446. *
  1447. * Callback function used with the binary trees to compare the id of RRDCALC
  1448. *
  1449. * @param a a pointer to the RRDCAL item to insert,compare or update the binary tree
  1450. * @param b the pointer to the binary tree.
  1451. *
  1452. * @return It returns 0 case the values are equal, 1 case a is bigger than b and -1 case a is smaller than b.
  1453. */
  1454. int alarm_compare_id(void *a, void *b) {
  1455. register uint32_t hash1 = ((RRDCALC *)a)->id;
  1456. register uint32_t hash2 = ((RRDCALC *)b)->id;
  1457. if(hash1 < hash2) return -1;
  1458. else if(hash1 > hash2) return 1;
  1459. return 0;
  1460. }
  1461. /**
  1462. * Alarm Compare NAME
  1463. *
  1464. * Callback function used with the binary trees to compare the name of RRDCALC
  1465. *
  1466. * @param a a pointer to the RRDCAL item to insert,compare or update the binary tree
  1467. * @param b the pointer to the binary tree.
  1468. *
  1469. * @return It returns 0 case the values are equal, 1 case a is bigger than b and -1 case a is smaller than b.
  1470. */
  1471. int alarm_compare_name(void *a, void *b) {
  1472. RRDCALC *in1 = (RRDCALC *)a;
  1473. RRDCALC *in2 = (RRDCALC *)b;
  1474. if(in1->hash < in2->hash) return -1;
  1475. else if(in1->hash > in2->hash) return 1;
  1476. return strcmp(in1->name,in2->name);
  1477. }
  1478. // Added for gap-filling, if this proves to be a bottleneck in large-scale systems then we will need to cache
  1479. // the last entry times as the metric updates, but let's see if it is a problem first.
  1480. time_t rrdhost_last_entry_t(RRDHOST *h) {
  1481. rrdhost_rdlock(h);
  1482. RRDSET *st;
  1483. time_t result = 0;
  1484. rrdset_foreach_read(st, h) {
  1485. time_t st_last = rrdset_last_entry_t(st);
  1486. if (st_last > result)
  1487. result = st_last;
  1488. }
  1489. rrdhost_unlock(h);
  1490. return result;
  1491. }