libnetdata.c 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "libnetdata.h"
  3. #ifdef __APPLE__
  4. #define INHERIT_NONE 0
  5. #endif /* __APPLE__ */
  6. #if defined(__FreeBSD__) || defined(__APPLE__)
  7. # define O_NOATIME 0
  8. # define MADV_DONTFORK INHERIT_NONE
  9. #endif /* __FreeBSD__ || __APPLE__*/
  10. struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 };
  11. #ifdef MADV_MERGEABLE
  12. int enable_ksm = 1;
  13. #else
  14. int enable_ksm = 0;
  15. #endif
  16. volatile sig_atomic_t netdata_exit = 0;
  17. const char *program_version = VERSION;
  18. #define MAX_JUDY_SIZE_TO_ARAL 24
  19. static bool judy_sizes_config[MAX_JUDY_SIZE_TO_ARAL + 1] = {
  20. [3] = true,
  21. [4] = true,
  22. [5] = true,
  23. [6] = true,
  24. [7] = true,
  25. [8] = true,
  26. [10] = true,
  27. [11] = true,
  28. [15] = true,
  29. [23] = true,
  30. };
  31. static ARAL *judy_sizes_aral[MAX_JUDY_SIZE_TO_ARAL + 1] = {};
  32. struct aral_statistics judy_sizes_aral_statistics = {};
  33. void aral_judy_init(void) {
  34. for(size_t Words = 0; Words <= MAX_JUDY_SIZE_TO_ARAL; Words++)
  35. if(judy_sizes_config[Words]) {
  36. char buf[30+1];
  37. snprintfz(buf, 30, "judy-%zu", Words * sizeof(Word_t));
  38. judy_sizes_aral[Words] = aral_create(
  39. buf,
  40. Words * sizeof(Word_t),
  41. 0,
  42. 65536,
  43. &judy_sizes_aral_statistics,
  44. NULL, NULL, false, false);
  45. }
  46. }
  47. size_t judy_aral_overhead(void) {
  48. return aral_overhead_from_stats(&judy_sizes_aral_statistics);
  49. }
  50. size_t judy_aral_structures(void) {
  51. return aral_structures_from_stats(&judy_sizes_aral_statistics);
  52. }
  53. static ARAL *judy_size_aral(Word_t Words) {
  54. if(Words <= MAX_JUDY_SIZE_TO_ARAL && judy_sizes_aral[Words])
  55. return judy_sizes_aral[Words];
  56. return NULL;
  57. }
  58. inline Word_t JudyMalloc(Word_t Words) {
  59. Word_t Addr;
  60. ARAL *ar = judy_size_aral(Words);
  61. if(ar)
  62. Addr = (Word_t) aral_mallocz(ar);
  63. else
  64. Addr = (Word_t) mallocz(Words * sizeof(Word_t));
  65. return(Addr);
  66. }
  67. inline void JudyFree(void * PWord, Word_t Words) {
  68. ARAL *ar = judy_size_aral(Words);
  69. if(ar)
  70. aral_freez(ar, PWord);
  71. else
  72. freez(PWord);
  73. }
  74. Word_t JudyMallocVirtual(Word_t Words) {
  75. return JudyMalloc(Words);
  76. }
  77. void JudyFreeVirtual(void * PWord, Word_t Words) {
  78. JudyFree(PWord, Words);
  79. }
  80. // ----------------------------------------------------------------------------
  81. // memory allocation functions that handle failures
  82. // although netdata does not use memory allocations too often (netdata tries to
  83. // maintain its memory footprint stable during runtime, i.e. all buffers are
  84. // allocated during initialization and are adapted to current use throughout
  85. // its lifetime), these can be used to override the default system allocation
  86. // routines.
  87. #ifdef NETDATA_TRACE_ALLOCATIONS
  88. #warning NETDATA_TRACE_ALLOCATIONS ENABLED
  89. #include "Judy.h"
  90. #if defined(HAVE_DLSYM) && defined(ENABLE_DLSYM)
  91. #include <dlfcn.h>
  92. typedef void (*libc_function_t)(void);
  93. static void *malloc_first_run(size_t size);
  94. static void *(*libc_malloc)(size_t) = malloc_first_run;
  95. static void *calloc_first_run(size_t n, size_t size);
  96. static void *(*libc_calloc)(size_t, size_t) = calloc_first_run;
  97. static void *realloc_first_run(void *ptr, size_t size);
  98. static void *(*libc_realloc)(void *, size_t) = realloc_first_run;
  99. static void free_first_run(void *ptr);
  100. static void (*libc_free)(void *) = free_first_run;
  101. static char *strdup_first_run(const char *s);
  102. static char *(*libc_strdup)(const char *) = strdup_first_run;
  103. static size_t malloc_usable_size_first_run(void *ptr);
  104. #ifdef HAVE_MALLOC_USABLE_SIZE
  105. static size_t (*libc_malloc_usable_size)(void *) = malloc_usable_size_first_run;
  106. #else
  107. static size_t (*libc_malloc_usable_size)(void *) = NULL;
  108. #endif
  109. static void link_system_library_function(libc_function_t *func_pptr, const char *name, bool required) {
  110. *func_pptr = dlsym(RTLD_NEXT, name);
  111. if(!*func_pptr && required) {
  112. fprintf(stderr, "FATAL: Cannot find system's %s() function.\n", name);
  113. abort();
  114. }
  115. }
  116. static void *malloc_first_run(size_t size) {
  117. link_system_library_function((libc_function_t *) &libc_malloc, "malloc", true);
  118. return libc_malloc(size);
  119. }
  120. static void *calloc_first_run(size_t n, size_t size) {
  121. link_system_library_function((libc_function_t *) &libc_calloc, "calloc", true);
  122. return libc_calloc(n, size);
  123. }
  124. static void *realloc_first_run(void *ptr, size_t size) {
  125. link_system_library_function((libc_function_t *) &libc_realloc, "realloc", true);
  126. return libc_realloc(ptr, size);
  127. }
  128. static void free_first_run(void *ptr) {
  129. link_system_library_function((libc_function_t *) &libc_free, "free", true);
  130. libc_free(ptr);
  131. }
  132. static char *strdup_first_run(const char *s) {
  133. link_system_library_function((libc_function_t *) &libc_strdup, "strdup", true);
  134. return libc_strdup(s);
  135. }
  136. static size_t malloc_usable_size_first_run(void *ptr) {
  137. link_system_library_function((libc_function_t *) &libc_malloc_usable_size, "malloc_usable_size", false);
  138. if(libc_malloc_usable_size)
  139. return libc_malloc_usable_size(ptr);
  140. else
  141. return 0;
  142. }
  143. void *malloc(size_t size) {
  144. return mallocz(size);
  145. }
  146. void *calloc(size_t n, size_t size) {
  147. return callocz(n, size);
  148. }
  149. void *realloc(void *ptr, size_t size) {
  150. return reallocz(ptr, size);
  151. }
  152. void *reallocarray(void *ptr, size_t n, size_t size) {
  153. return reallocz(ptr, n * size);
  154. }
  155. void free(void *ptr) {
  156. freez(ptr);
  157. }
  158. char *strdup(const char *s) {
  159. return strdupz(s);
  160. }
  161. size_t malloc_usable_size(void *ptr) {
  162. return mallocz_usable_size(ptr);
  163. }
  164. #else // !HAVE_DLSYM
  165. static void *(*libc_malloc)(size_t) = malloc;
  166. static void *(*libc_calloc)(size_t, size_t) = calloc;
  167. static void *(*libc_realloc)(void *, size_t) = realloc;
  168. static void (*libc_free)(void *) = free;
  169. #ifdef HAVE_MALLOC_USABLE_SIZE
  170. static size_t (*libc_malloc_usable_size)(void *) = malloc_usable_size;
  171. #else
  172. static size_t (*libc_malloc_usable_size)(void *) = NULL;
  173. #endif
  174. #endif // HAVE_DLSYM
  175. void posix_memfree(void *ptr) {
  176. libc_free(ptr);
  177. }
  178. struct malloc_header_signature {
  179. uint32_t magic;
  180. uint32_t size;
  181. struct malloc_trace *trace;
  182. };
  183. struct malloc_header {
  184. struct malloc_header_signature signature;
  185. uint8_t padding[(sizeof(struct malloc_header_signature) % MALLOC_ALIGNMENT) ? MALLOC_ALIGNMENT - (sizeof(struct malloc_header_signature) % MALLOC_ALIGNMENT) : 0];
  186. uint8_t data[];
  187. };
  188. static size_t malloc_header_size = sizeof(struct malloc_header);
  189. int malloc_trace_compare(void *A, void *B) {
  190. struct malloc_trace *a = A;
  191. struct malloc_trace *b = B;
  192. return strcmp(a->function, b->function);
  193. }
  194. static avl_tree_lock malloc_trace_index = {
  195. .avl_tree = {
  196. .root = NULL,
  197. .compar = malloc_trace_compare},
  198. .rwlock = NETDATA_RWLOCK_INITIALIZER
  199. };
  200. int malloc_trace_walkthrough(int (*callback)(void *item, void *data), void *data) {
  201. return avl_traverse_lock(&malloc_trace_index, callback, data);
  202. }
  203. NEVERNULL WARNUNUSED
  204. static struct malloc_trace *malloc_trace_find_or_create(const char *file, const char *function, size_t line) {
  205. struct malloc_trace tmp = {
  206. .line = line,
  207. .function = function,
  208. .file = file,
  209. };
  210. struct malloc_trace *t = (struct malloc_trace *)avl_search_lock(&malloc_trace_index, (avl_t *)&tmp);
  211. if(!t) {
  212. t = libc_calloc(1, sizeof(struct malloc_trace));
  213. if(!t) fatal("No memory");
  214. t->line = line;
  215. t->function = function;
  216. t->file = file;
  217. struct malloc_trace *t2 = (struct malloc_trace *)avl_insert_lock(&malloc_trace_index, (avl_t *)t);
  218. if(t2 != t)
  219. free(t);
  220. t = t2;
  221. }
  222. if(!t)
  223. fatal("Cannot insert to AVL");
  224. return t;
  225. }
  226. void malloc_trace_mmap(size_t size) {
  227. struct malloc_trace *p = malloc_trace_find_or_create("unknown", "netdata_mmap", 1);
  228. size_t_atomic_count(add, p->mmap_calls, 1);
  229. size_t_atomic_count(add, p->allocations, 1);
  230. size_t_atomic_bytes(add, p->bytes, size);
  231. }
  232. void malloc_trace_munmap(size_t size) {
  233. struct malloc_trace *p = malloc_trace_find_or_create("unknown", "netdata_mmap", 1);
  234. size_t_atomic_count(add, p->munmap_calls, 1);
  235. size_t_atomic_count(sub, p->allocations, 1);
  236. size_t_atomic_bytes(sub, p->bytes, size);
  237. }
  238. void *mallocz_int(size_t size, const char *file, const char *function, size_t line) {
  239. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  240. size_t_atomic_count(add, p->malloc_calls, 1);
  241. size_t_atomic_count(add, p->allocations, 1);
  242. size_t_atomic_bytes(add, p->bytes, size);
  243. struct malloc_header *t = (struct malloc_header *)libc_malloc(malloc_header_size + size);
  244. if (unlikely(!t)) fatal("mallocz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  245. t->signature.magic = 0x0BADCAFE;
  246. t->signature.trace = p;
  247. t->signature.size = size;
  248. #ifdef NETDATA_INTERNAL_CHECKS
  249. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  250. t->padding[i] = 0xFF;
  251. #endif
  252. return (void *)&t->data;
  253. }
  254. void *callocz_int(size_t nmemb, size_t size, const char *file, const char *function, size_t line) {
  255. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  256. size = nmemb * size;
  257. size_t_atomic_count(add, p->calloc_calls, 1);
  258. size_t_atomic_count(add, p->allocations, 1);
  259. size_t_atomic_bytes(add, p->bytes, size);
  260. struct malloc_header *t = (struct malloc_header *)libc_calloc(1, malloc_header_size + size);
  261. if (unlikely(!t)) fatal("mallocz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  262. t->signature.magic = 0x0BADCAFE;
  263. t->signature.trace = p;
  264. t->signature.size = size;
  265. #ifdef NETDATA_INTERNAL_CHECKS
  266. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  267. t->padding[i] = 0xFF;
  268. #endif
  269. return &t->data;
  270. }
  271. char *strdupz_int(const char *s, const char *file, const char *function, size_t line) {
  272. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  273. size_t size = strlen(s) + 1;
  274. size_t_atomic_count(add, p->strdup_calls, 1);
  275. size_t_atomic_count(add, p->allocations, 1);
  276. size_t_atomic_bytes(add, p->bytes, size);
  277. struct malloc_header *t = (struct malloc_header *)libc_malloc(malloc_header_size + size);
  278. if (unlikely(!t)) fatal("strdupz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  279. t->signature.magic = 0x0BADCAFE;
  280. t->signature.trace = p;
  281. t->signature.size = size;
  282. #ifdef NETDATA_INTERNAL_CHECKS
  283. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  284. t->padding[i] = 0xFF;
  285. #endif
  286. memcpy(&t->data, s, size);
  287. return (char *)&t->data;
  288. }
  289. static struct malloc_header *malloc_get_header(void *ptr, const char *caller, const char *file, const char *function, size_t line) {
  290. uint8_t *ret = (uint8_t *)ptr - malloc_header_size;
  291. struct malloc_header *t = (struct malloc_header *)ret;
  292. if(t->signature.magic != 0x0BADCAFE) {
  293. error("pointer %p is not our pointer (called %s() from %zu@%s, %s()).", ptr, caller, line, file, function);
  294. return NULL;
  295. }
  296. return t;
  297. }
  298. void *reallocz_int(void *ptr, size_t size, const char *file, const char *function, size_t line) {
  299. if(!ptr) return mallocz_int(size, file, function, line);
  300. struct malloc_header *t = malloc_get_header(ptr, __FUNCTION__, file, function, line);
  301. if(!t)
  302. return libc_realloc(ptr, size);
  303. if(t->signature.size == size) return ptr;
  304. size_t_atomic_count(add, t->signature.trace->free_calls, 1);
  305. size_t_atomic_count(sub, t->signature.trace->allocations, 1);
  306. size_t_atomic_bytes(sub, t->signature.trace->bytes, t->signature.size);
  307. struct malloc_trace *p = malloc_trace_find_or_create(file, function, line);
  308. size_t_atomic_count(add, p->realloc_calls, 1);
  309. size_t_atomic_count(add, p->allocations, 1);
  310. size_t_atomic_bytes(add, p->bytes, size);
  311. t = (struct malloc_header *)libc_realloc(t, malloc_header_size + size);
  312. if (unlikely(!t)) fatal("reallocz() cannot allocate %zu bytes of memory (%zu with header).", size, malloc_header_size + size);
  313. t->signature.magic = 0x0BADCAFE;
  314. t->signature.trace = p;
  315. t->signature.size = size;
  316. #ifdef NETDATA_INTERNAL_CHECKS
  317. for(ssize_t i = 0; i < (ssize_t)sizeof(t->padding) ;i++) // signed to avoid compiler warning when zero-padded
  318. t->padding[i] = 0xFF;
  319. #endif
  320. return (void *)&t->data;
  321. }
  322. size_t mallocz_usable_size_int(void *ptr, const char *file, const char *function, size_t line) {
  323. if(unlikely(!ptr)) return 0;
  324. struct malloc_header *t = malloc_get_header(ptr, __FUNCTION__, file, function, line);
  325. if(!t) {
  326. if(libc_malloc_usable_size)
  327. return libc_malloc_usable_size(ptr);
  328. else
  329. return 0;
  330. }
  331. return t->signature.size;
  332. }
  333. void freez_int(void *ptr, const char *file, const char *function, size_t line) {
  334. if(unlikely(!ptr)) return;
  335. struct malloc_header *t = malloc_get_header(ptr, __FUNCTION__, file, function, line);
  336. if(!t) {
  337. libc_free(ptr);
  338. return;
  339. }
  340. size_t_atomic_count(add, t->signature.trace->free_calls, 1);
  341. size_t_atomic_count(sub, t->signature.trace->allocations, 1);
  342. size_t_atomic_bytes(sub, t->signature.trace->bytes, t->signature.size);
  343. #ifdef NETDATA_INTERNAL_CHECKS
  344. // it should crash if it is used after freeing it
  345. memset(t, 0, malloc_header_size + t->signature.size);
  346. #endif
  347. libc_free(t);
  348. }
  349. #else
  350. char *strdupz(const char *s) {
  351. char *t = strdup(s);
  352. if (unlikely(!t)) fatal("Cannot strdup() string '%s'", s);
  353. return t;
  354. }
  355. // If ptr is NULL, no operation is performed.
  356. void freez(void *ptr) {
  357. free(ptr);
  358. }
  359. void *mallocz(size_t size) {
  360. void *p = malloc(size);
  361. if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", size);
  362. return p;
  363. }
  364. void *callocz(size_t nmemb, size_t size) {
  365. void *p = calloc(nmemb, size);
  366. if (unlikely(!p)) fatal("Cannot allocate %zu bytes of memory.", nmemb * size);
  367. return p;
  368. }
  369. void *reallocz(void *ptr, size_t size) {
  370. void *p = realloc(ptr, size);
  371. if (unlikely(!p)) fatal("Cannot re-allocate memory to %zu bytes.", size);
  372. return p;
  373. }
  374. void posix_memfree(void *ptr) {
  375. free(ptr);
  376. }
  377. #endif
  378. // --------------------------------------------------------------------------------------------------------------------
  379. void json_escape_string(char *dst, const char *src, size_t size) {
  380. const char *t;
  381. char *d = dst, *e = &dst[size - 1];
  382. for(t = src; *t && d < e ;t++) {
  383. if(unlikely(*t == '\\' || *t == '"')) {
  384. if(unlikely(d + 1 >= e)) break;
  385. *d++ = '\\';
  386. }
  387. *d++ = *t;
  388. }
  389. *d = '\0';
  390. }
  391. void json_fix_string(char *s) {
  392. unsigned char c;
  393. while((c = (unsigned char)*s)) {
  394. if(unlikely(c == '\\'))
  395. *s++ = '/';
  396. else if(unlikely(c == '"'))
  397. *s++ = '\'';
  398. else if(unlikely(isspace(c) || iscntrl(c)))
  399. *s++ = ' ';
  400. else if(unlikely(!isprint(c) || c > 127))
  401. *s++ = '_';
  402. else
  403. s++;
  404. }
  405. }
  406. unsigned char netdata_map_chart_names[256] = {
  407. [0] = '\0', //
  408. [1] = '_', //
  409. [2] = '_', //
  410. [3] = '_', //
  411. [4] = '_', //
  412. [5] = '_', //
  413. [6] = '_', //
  414. [7] = '_', //
  415. [8] = '_', //
  416. [9] = '_', //
  417. [10] = '_', //
  418. [11] = '_', //
  419. [12] = '_', //
  420. [13] = '_', //
  421. [14] = '_', //
  422. [15] = '_', //
  423. [16] = '_', //
  424. [17] = '_', //
  425. [18] = '_', //
  426. [19] = '_', //
  427. [20] = '_', //
  428. [21] = '_', //
  429. [22] = '_', //
  430. [23] = '_', //
  431. [24] = '_', //
  432. [25] = '_', //
  433. [26] = '_', //
  434. [27] = '_', //
  435. [28] = '_', //
  436. [29] = '_', //
  437. [30] = '_', //
  438. [31] = '_', //
  439. [32] = '_', //
  440. [33] = '_', // !
  441. [34] = '_', // "
  442. [35] = '_', // #
  443. [36] = '_', // $
  444. [37] = '_', // %
  445. [38] = '_', // &
  446. [39] = '_', // '
  447. [40] = '_', // (
  448. [41] = '_', // )
  449. [42] = '_', // *
  450. [43] = '_', // +
  451. [44] = '.', // ,
  452. [45] = '-', // -
  453. [46] = '.', // .
  454. [47] = '/', // /
  455. [48] = '0', // 0
  456. [49] = '1', // 1
  457. [50] = '2', // 2
  458. [51] = '3', // 3
  459. [52] = '4', // 4
  460. [53] = '5', // 5
  461. [54] = '6', // 6
  462. [55] = '7', // 7
  463. [56] = '8', // 8
  464. [57] = '9', // 9
  465. [58] = '_', // :
  466. [59] = '_', // ;
  467. [60] = '_', // <
  468. [61] = '_', // =
  469. [62] = '_', // >
  470. [63] = '_', // ?
  471. [64] = '_', // @
  472. [65] = 'a', // A
  473. [66] = 'b', // B
  474. [67] = 'c', // C
  475. [68] = 'd', // D
  476. [69] = 'e', // E
  477. [70] = 'f', // F
  478. [71] = 'g', // G
  479. [72] = 'h', // H
  480. [73] = 'i', // I
  481. [74] = 'j', // J
  482. [75] = 'k', // K
  483. [76] = 'l', // L
  484. [77] = 'm', // M
  485. [78] = 'n', // N
  486. [79] = 'o', // O
  487. [80] = 'p', // P
  488. [81] = 'q', // Q
  489. [82] = 'r', // R
  490. [83] = 's', // S
  491. [84] = 't', // T
  492. [85] = 'u', // U
  493. [86] = 'v', // V
  494. [87] = 'w', // W
  495. [88] = 'x', // X
  496. [89] = 'y', // Y
  497. [90] = 'z', // Z
  498. [91] = '_', // [
  499. [92] = '/', // backslash
  500. [93] = '_', // ]
  501. [94] = '_', // ^
  502. [95] = '_', // _
  503. [96] = '_', // `
  504. [97] = 'a', // a
  505. [98] = 'b', // b
  506. [99] = 'c', // c
  507. [100] = 'd', // d
  508. [101] = 'e', // e
  509. [102] = 'f', // f
  510. [103] = 'g', // g
  511. [104] = 'h', // h
  512. [105] = 'i', // i
  513. [106] = 'j', // j
  514. [107] = 'k', // k
  515. [108] = 'l', // l
  516. [109] = 'm', // m
  517. [110] = 'n', // n
  518. [111] = 'o', // o
  519. [112] = 'p', // p
  520. [113] = 'q', // q
  521. [114] = 'r', // r
  522. [115] = 's', // s
  523. [116] = 't', // t
  524. [117] = 'u', // u
  525. [118] = 'v', // v
  526. [119] = 'w', // w
  527. [120] = 'x', // x
  528. [121] = 'y', // y
  529. [122] = 'z', // z
  530. [123] = '_', // {
  531. [124] = '_', // |
  532. [125] = '_', // }
  533. [126] = '_', // ~
  534. [127] = '_', //
  535. [128] = '_', //
  536. [129] = '_', //
  537. [130] = '_', //
  538. [131] = '_', //
  539. [132] = '_', //
  540. [133] = '_', //
  541. [134] = '_', //
  542. [135] = '_', //
  543. [136] = '_', //
  544. [137] = '_', //
  545. [138] = '_', //
  546. [139] = '_', //
  547. [140] = '_', //
  548. [141] = '_', //
  549. [142] = '_', //
  550. [143] = '_', //
  551. [144] = '_', //
  552. [145] = '_', //
  553. [146] = '_', //
  554. [147] = '_', //
  555. [148] = '_', //
  556. [149] = '_', //
  557. [150] = '_', //
  558. [151] = '_', //
  559. [152] = '_', //
  560. [153] = '_', //
  561. [154] = '_', //
  562. [155] = '_', //
  563. [156] = '_', //
  564. [157] = '_', //
  565. [158] = '_', //
  566. [159] = '_', //
  567. [160] = '_', //
  568. [161] = '_', //
  569. [162] = '_', //
  570. [163] = '_', //
  571. [164] = '_', //
  572. [165] = '_', //
  573. [166] = '_', //
  574. [167] = '_', //
  575. [168] = '_', //
  576. [169] = '_', //
  577. [170] = '_', //
  578. [171] = '_', //
  579. [172] = '_', //
  580. [173] = '_', //
  581. [174] = '_', //
  582. [175] = '_', //
  583. [176] = '_', //
  584. [177] = '_', //
  585. [178] = '_', //
  586. [179] = '_', //
  587. [180] = '_', //
  588. [181] = '_', //
  589. [182] = '_', //
  590. [183] = '_', //
  591. [184] = '_', //
  592. [185] = '_', //
  593. [186] = '_', //
  594. [187] = '_', //
  595. [188] = '_', //
  596. [189] = '_', //
  597. [190] = '_', //
  598. [191] = '_', //
  599. [192] = '_', //
  600. [193] = '_', //
  601. [194] = '_', //
  602. [195] = '_', //
  603. [196] = '_', //
  604. [197] = '_', //
  605. [198] = '_', //
  606. [199] = '_', //
  607. [200] = '_', //
  608. [201] = '_', //
  609. [202] = '_', //
  610. [203] = '_', //
  611. [204] = '_', //
  612. [205] = '_', //
  613. [206] = '_', //
  614. [207] = '_', //
  615. [208] = '_', //
  616. [209] = '_', //
  617. [210] = '_', //
  618. [211] = '_', //
  619. [212] = '_', //
  620. [213] = '_', //
  621. [214] = '_', //
  622. [215] = '_', //
  623. [216] = '_', //
  624. [217] = '_', //
  625. [218] = '_', //
  626. [219] = '_', //
  627. [220] = '_', //
  628. [221] = '_', //
  629. [222] = '_', //
  630. [223] = '_', //
  631. [224] = '_', //
  632. [225] = '_', //
  633. [226] = '_', //
  634. [227] = '_', //
  635. [228] = '_', //
  636. [229] = '_', //
  637. [230] = '_', //
  638. [231] = '_', //
  639. [232] = '_', //
  640. [233] = '_', //
  641. [234] = '_', //
  642. [235] = '_', //
  643. [236] = '_', //
  644. [237] = '_', //
  645. [238] = '_', //
  646. [239] = '_', //
  647. [240] = '_', //
  648. [241] = '_', //
  649. [242] = '_', //
  650. [243] = '_', //
  651. [244] = '_', //
  652. [245] = '_', //
  653. [246] = '_', //
  654. [247] = '_', //
  655. [248] = '_', //
  656. [249] = '_', //
  657. [250] = '_', //
  658. [251] = '_', //
  659. [252] = '_', //
  660. [253] = '_', //
  661. [254] = '_', //
  662. [255] = '_' //
  663. };
  664. // make sure the supplied string
  665. // is good for a netdata chart/dimension ID/NAME
  666. void netdata_fix_chart_name(char *s) {
  667. while ((*s = netdata_map_chart_names[(unsigned char) *s])) s++;
  668. }
  669. unsigned char netdata_map_chart_ids[256] = {
  670. [0] = '\0', //
  671. [1] = '_', //
  672. [2] = '_', //
  673. [3] = '_', //
  674. [4] = '_', //
  675. [5] = '_', //
  676. [6] = '_', //
  677. [7] = '_', //
  678. [8] = '_', //
  679. [9] = '_', //
  680. [10] = '_', //
  681. [11] = '_', //
  682. [12] = '_', //
  683. [13] = '_', //
  684. [14] = '_', //
  685. [15] = '_', //
  686. [16] = '_', //
  687. [17] = '_', //
  688. [18] = '_', //
  689. [19] = '_', //
  690. [20] = '_', //
  691. [21] = '_', //
  692. [22] = '_', //
  693. [23] = '_', //
  694. [24] = '_', //
  695. [25] = '_', //
  696. [26] = '_', //
  697. [27] = '_', //
  698. [28] = '_', //
  699. [29] = '_', //
  700. [30] = '_', //
  701. [31] = '_', //
  702. [32] = '_', //
  703. [33] = '_', // !
  704. [34] = '_', // "
  705. [35] = '_', // #
  706. [36] = '_', // $
  707. [37] = '_', // %
  708. [38] = '_', // &
  709. [39] = '_', // '
  710. [40] = '_', // (
  711. [41] = '_', // )
  712. [42] = '_', // *
  713. [43] = '_', // +
  714. [44] = '.', // ,
  715. [45] = '-', // -
  716. [46] = '.', // .
  717. [47] = '_', // /
  718. [48] = '0', // 0
  719. [49] = '1', // 1
  720. [50] = '2', // 2
  721. [51] = '3', // 3
  722. [52] = '4', // 4
  723. [53] = '5', // 5
  724. [54] = '6', // 6
  725. [55] = '7', // 7
  726. [56] = '8', // 8
  727. [57] = '9', // 9
  728. [58] = '_', // :
  729. [59] = '_', // ;
  730. [60] = '_', // <
  731. [61] = '_', // =
  732. [62] = '_', // >
  733. [63] = '_', // ?
  734. [64] = '_', // @
  735. [65] = 'a', // A
  736. [66] = 'b', // B
  737. [67] = 'c', // C
  738. [68] = 'd', // D
  739. [69] = 'e', // E
  740. [70] = 'f', // F
  741. [71] = 'g', // G
  742. [72] = 'h', // H
  743. [73] = 'i', // I
  744. [74] = 'j', // J
  745. [75] = 'k', // K
  746. [76] = 'l', // L
  747. [77] = 'm', // M
  748. [78] = 'n', // N
  749. [79] = 'o', // O
  750. [80] = 'p', // P
  751. [81] = 'q', // Q
  752. [82] = 'r', // R
  753. [83] = 's', // S
  754. [84] = 't', // T
  755. [85] = 'u', // U
  756. [86] = 'v', // V
  757. [87] = 'w', // W
  758. [88] = 'x', // X
  759. [89] = 'y', // Y
  760. [90] = 'z', // Z
  761. [91] = '_', // [
  762. [92] = '_', // backslash
  763. [93] = '_', // ]
  764. [94] = '_', // ^
  765. [95] = '_', // _
  766. [96] = '_', // `
  767. [97] = 'a', // a
  768. [98] = 'b', // b
  769. [99] = 'c', // c
  770. [100] = 'd', // d
  771. [101] = 'e', // e
  772. [102] = 'f', // f
  773. [103] = 'g', // g
  774. [104] = 'h', // h
  775. [105] = 'i', // i
  776. [106] = 'j', // j
  777. [107] = 'k', // k
  778. [108] = 'l', // l
  779. [109] = 'm', // m
  780. [110] = 'n', // n
  781. [111] = 'o', // o
  782. [112] = 'p', // p
  783. [113] = 'q', // q
  784. [114] = 'r', // r
  785. [115] = 's', // s
  786. [116] = 't', // t
  787. [117] = 'u', // u
  788. [118] = 'v', // v
  789. [119] = 'w', // w
  790. [120] = 'x', // x
  791. [121] = 'y', // y
  792. [122] = 'z', // z
  793. [123] = '_', // {
  794. [124] = '_', // |
  795. [125] = '_', // }
  796. [126] = '_', // ~
  797. [127] = '_', //
  798. [128] = '_', //
  799. [129] = '_', //
  800. [130] = '_', //
  801. [131] = '_', //
  802. [132] = '_', //
  803. [133] = '_', //
  804. [134] = '_', //
  805. [135] = '_', //
  806. [136] = '_', //
  807. [137] = '_', //
  808. [138] = '_', //
  809. [139] = '_', //
  810. [140] = '_', //
  811. [141] = '_', //
  812. [142] = '_', //
  813. [143] = '_', //
  814. [144] = '_', //
  815. [145] = '_', //
  816. [146] = '_', //
  817. [147] = '_', //
  818. [148] = '_', //
  819. [149] = '_', //
  820. [150] = '_', //
  821. [151] = '_', //
  822. [152] = '_', //
  823. [153] = '_', //
  824. [154] = '_', //
  825. [155] = '_', //
  826. [156] = '_', //
  827. [157] = '_', //
  828. [158] = '_', //
  829. [159] = '_', //
  830. [160] = '_', //
  831. [161] = '_', //
  832. [162] = '_', //
  833. [163] = '_', //
  834. [164] = '_', //
  835. [165] = '_', //
  836. [166] = '_', //
  837. [167] = '_', //
  838. [168] = '_', //
  839. [169] = '_', //
  840. [170] = '_', //
  841. [171] = '_', //
  842. [172] = '_', //
  843. [173] = '_', //
  844. [174] = '_', //
  845. [175] = '_', //
  846. [176] = '_', //
  847. [177] = '_', //
  848. [178] = '_', //
  849. [179] = '_', //
  850. [180] = '_', //
  851. [181] = '_', //
  852. [182] = '_', //
  853. [183] = '_', //
  854. [184] = '_', //
  855. [185] = '_', //
  856. [186] = '_', //
  857. [187] = '_', //
  858. [188] = '_', //
  859. [189] = '_', //
  860. [190] = '_', //
  861. [191] = '_', //
  862. [192] = '_', //
  863. [193] = '_', //
  864. [194] = '_', //
  865. [195] = '_', //
  866. [196] = '_', //
  867. [197] = '_', //
  868. [198] = '_', //
  869. [199] = '_', //
  870. [200] = '_', //
  871. [201] = '_', //
  872. [202] = '_', //
  873. [203] = '_', //
  874. [204] = '_', //
  875. [205] = '_', //
  876. [206] = '_', //
  877. [207] = '_', //
  878. [208] = '_', //
  879. [209] = '_', //
  880. [210] = '_', //
  881. [211] = '_', //
  882. [212] = '_', //
  883. [213] = '_', //
  884. [214] = '_', //
  885. [215] = '_', //
  886. [216] = '_', //
  887. [217] = '_', //
  888. [218] = '_', //
  889. [219] = '_', //
  890. [220] = '_', //
  891. [221] = '_', //
  892. [222] = '_', //
  893. [223] = '_', //
  894. [224] = '_', //
  895. [225] = '_', //
  896. [226] = '_', //
  897. [227] = '_', //
  898. [228] = '_', //
  899. [229] = '_', //
  900. [230] = '_', //
  901. [231] = '_', //
  902. [232] = '_', //
  903. [233] = '_', //
  904. [234] = '_', //
  905. [235] = '_', //
  906. [236] = '_', //
  907. [237] = '_', //
  908. [238] = '_', //
  909. [239] = '_', //
  910. [240] = '_', //
  911. [241] = '_', //
  912. [242] = '_', //
  913. [243] = '_', //
  914. [244] = '_', //
  915. [245] = '_', //
  916. [246] = '_', //
  917. [247] = '_', //
  918. [248] = '_', //
  919. [249] = '_', //
  920. [250] = '_', //
  921. [251] = '_', //
  922. [252] = '_', //
  923. [253] = '_', //
  924. [254] = '_', //
  925. [255] = '_' //
  926. };
  927. // make sure the supplied string
  928. // is good for a netdata chart/dimension ID/NAME
  929. void netdata_fix_chart_id(char *s) {
  930. while ((*s = netdata_map_chart_ids[(unsigned char) *s])) s++;
  931. }
  932. static int memory_file_open(const char *filename, size_t size) {
  933. // info("memory_file_open('%s', %zu", filename, size);
  934. int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
  935. if (fd != -1) {
  936. if (lseek(fd, size, SEEK_SET) == (off_t) size) {
  937. if (write(fd, "", 1) == 1) {
  938. if (ftruncate(fd, size))
  939. error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
  940. }
  941. else error("Cannot write to file '%s' at position %zu.", filename, size);
  942. }
  943. else error("Cannot seek file '%s' to size %zu.", filename, size);
  944. }
  945. else error("Cannot create/open file '%s'.", filename);
  946. return fd;
  947. }
  948. inline int madvise_sequential(void *mem, size_t len) {
  949. static int logger = 1;
  950. int ret = madvise(mem, len, MADV_SEQUENTIAL);
  951. if (ret != 0 && logger-- > 0) error("madvise(MADV_SEQUENTIAL) failed.");
  952. return ret;
  953. }
  954. inline int madvise_random(void *mem, size_t len) {
  955. static int logger = 1;
  956. int ret = madvise(mem, len, MADV_RANDOM);
  957. if (ret != 0 && logger-- > 0) error("madvise(MADV_RANDOM) failed.");
  958. return ret;
  959. }
  960. inline int madvise_dontfork(void *mem, size_t len) {
  961. static int logger = 1;
  962. int ret = madvise(mem, len, MADV_DONTFORK);
  963. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTFORK) failed.");
  964. return ret;
  965. }
  966. inline int madvise_willneed(void *mem, size_t len) {
  967. static int logger = 1;
  968. int ret = madvise(mem, len, MADV_WILLNEED);
  969. if (ret != 0 && logger-- > 0) error("madvise(MADV_WILLNEED) failed.");
  970. return ret;
  971. }
  972. inline int madvise_dontneed(void *mem, size_t len) {
  973. static int logger = 1;
  974. int ret = madvise(mem, len, MADV_DONTNEED);
  975. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTNEED) failed.");
  976. return ret;
  977. }
  978. inline int madvise_dontdump(void *mem __maybe_unused, size_t len __maybe_unused) {
  979. #if __linux__
  980. static int logger = 1;
  981. int ret = madvise(mem, len, MADV_DONTDUMP);
  982. if (ret != 0 && logger-- > 0) error("madvise(MADV_DONTDUMP) failed.");
  983. return ret;
  984. #else
  985. return 0;
  986. #endif
  987. }
  988. inline int madvise_mergeable(void *mem __maybe_unused, size_t len __maybe_unused) {
  989. #ifdef MADV_MERGEABLE
  990. static int logger = 1;
  991. int ret = madvise(mem, len, MADV_MERGEABLE);
  992. if (ret != 0 && logger-- > 0) error("madvise(MADV_MERGEABLE) failed.");
  993. return ret;
  994. #else
  995. return 0;
  996. #endif
  997. }
  998. void *netdata_mmap(const char *filename, size_t size, int flags, int ksm, bool read_only, int *open_fd)
  999. {
  1000. // info("netdata_mmap('%s', %zu", filename, size);
  1001. // MAP_SHARED is used in memory mode map
  1002. // MAP_PRIVATE is used in memory mode ram and save
  1003. if(unlikely(!(flags & MAP_SHARED) && !(flags & MAP_PRIVATE)))
  1004. fatal("Neither MAP_SHARED or MAP_PRIVATE were given to netdata_mmap()");
  1005. if(unlikely((flags & MAP_SHARED) && (flags & MAP_PRIVATE)))
  1006. fatal("Both MAP_SHARED and MAP_PRIVATE were given to netdata_mmap()");
  1007. if(unlikely((flags & MAP_SHARED) && (!filename || !*filename)))
  1008. fatal("MAP_SHARED requested, without a filename to netdata_mmap()");
  1009. // don't enable ksm is the global setting is disabled
  1010. if(unlikely(!enable_ksm)) ksm = 0;
  1011. // KSM only merges anonymous (private) pages, never pagecache (file) pages
  1012. // but MAP_PRIVATE without MAP_ANONYMOUS it fails too, so we need it always
  1013. if((flags & MAP_PRIVATE)) flags |= MAP_ANONYMOUS;
  1014. int fd = -1;
  1015. void *mem = MAP_FAILED;
  1016. if(filename && *filename) {
  1017. // open/create the file to be used
  1018. fd = memory_file_open(filename, size);
  1019. if(fd == -1) goto cleanup;
  1020. }
  1021. int fd_for_mmap = fd;
  1022. if(fd != -1 && (flags & MAP_PRIVATE)) {
  1023. // this is MAP_PRIVATE allocation
  1024. // no need for mmap() to use our fd
  1025. // we will copy the file into the memory allocated
  1026. fd_for_mmap = -1;
  1027. }
  1028. mem = mmap(NULL, size, read_only ? PROT_READ : PROT_READ | PROT_WRITE, flags, fd_for_mmap, 0);
  1029. if (mem != MAP_FAILED) {
  1030. #ifdef NETDATA_TRACE_ALLOCATIONS
  1031. malloc_trace_mmap(size);
  1032. #endif
  1033. // if we have a file open, but we didn't give it to mmap(),
  1034. // we have to read the file into the memory block we allocated
  1035. if(fd != -1 && fd_for_mmap == -1) {
  1036. if (lseek(fd, 0, SEEK_SET) == 0) {
  1037. if (read(fd, mem, size) != (ssize_t) size)
  1038. info("Cannot read from file '%s'", filename);
  1039. }
  1040. else info("Cannot seek to beginning of file '%s'.", filename);
  1041. }
  1042. // madvise_sequential(mem, size);
  1043. madvise_dontfork(mem, size);
  1044. madvise_dontdump(mem, size);
  1045. // if(flags & MAP_SHARED) madvise_willneed(mem, size);
  1046. if(ksm) madvise_mergeable(mem, size);
  1047. }
  1048. cleanup:
  1049. if(fd != -1) {
  1050. if (open_fd)
  1051. *open_fd = fd;
  1052. else
  1053. close(fd);
  1054. }
  1055. if(mem == MAP_FAILED) return NULL;
  1056. errno = 0;
  1057. return mem;
  1058. }
  1059. int netdata_munmap(void *ptr, size_t size) {
  1060. #ifdef NETDATA_TRACE_ALLOCATIONS
  1061. malloc_trace_munmap(size);
  1062. #endif
  1063. return munmap(ptr, size);
  1064. }
  1065. int memory_file_save(const char *filename, void *mem, size_t size) {
  1066. char tmpfilename[FILENAME_MAX + 1];
  1067. snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
  1068. int fd = open(tmpfilename, O_RDWR | O_CREAT | O_NOATIME, 0664);
  1069. if (fd < 0) {
  1070. error("Cannot create/open file '%s'.", filename);
  1071. return -1;
  1072. }
  1073. if (write(fd, mem, size) != (ssize_t) size) {
  1074. error("Cannot write to file '%s' %ld bytes.", filename, (long) size);
  1075. close(fd);
  1076. return -1;
  1077. }
  1078. close(fd);
  1079. if (rename(tmpfilename, filename)) {
  1080. error("Cannot rename '%s' to '%s'", tmpfilename, filename);
  1081. return -1;
  1082. }
  1083. return 0;
  1084. }
  1085. int fd_is_valid(int fd) {
  1086. return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
  1087. }
  1088. char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len) {
  1089. char *s = fgets(buf, (int)buf_size, fp);
  1090. if (!s) return NULL;
  1091. char *t = s;
  1092. if (*t != '\0') {
  1093. // find the string end
  1094. while (*++t != '\0');
  1095. // trim trailing spaces/newlines/tabs
  1096. while (--t > s && *t == '\n')
  1097. *t = '\0';
  1098. }
  1099. if (len)
  1100. *len = t - s + 1;
  1101. return s;
  1102. }
  1103. int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args) {
  1104. if(unlikely(!n)) return 0;
  1105. int size = vsnprintf(dst, n, fmt, args);
  1106. dst[n - 1] = '\0';
  1107. if (unlikely((size_t) size > n)) size = (int)n;
  1108. return size;
  1109. }
  1110. int snprintfz(char *dst, size_t n, const char *fmt, ...) {
  1111. va_list args;
  1112. va_start(args, fmt);
  1113. int ret = vsnprintfz(dst, n, fmt, args);
  1114. va_end(args);
  1115. return ret;
  1116. }
  1117. /*
  1118. // poor man cycle counting
  1119. static unsigned long tsc;
  1120. void begin_tsc(void) {
  1121. unsigned long a, d;
  1122. asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
  1123. tsc = ((unsigned long)d << 32) | (unsigned long)a;
  1124. }
  1125. unsigned long end_tsc(void) {
  1126. unsigned long a, d;
  1127. asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
  1128. return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
  1129. }
  1130. */
  1131. int recursively_delete_dir(const char *path, const char *reason) {
  1132. DIR *dir = opendir(path);
  1133. if(!dir) {
  1134. error("Cannot read %s directory to be deleted '%s'", reason?reason:"", path);
  1135. return -1;
  1136. }
  1137. int ret = 0;
  1138. struct dirent *de = NULL;
  1139. while((de = readdir(dir))) {
  1140. if(de->d_type == DT_DIR
  1141. && (
  1142. (de->d_name[0] == '.' && de->d_name[1] == '\0')
  1143. || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1144. ))
  1145. continue;
  1146. char fullpath[FILENAME_MAX + 1];
  1147. snprintfz(fullpath, FILENAME_MAX, "%s/%s", path, de->d_name);
  1148. if(de->d_type == DT_DIR) {
  1149. int r = recursively_delete_dir(fullpath, reason);
  1150. if(r > 0) ret += r;
  1151. continue;
  1152. }
  1153. info("Deleting %s file '%s'", reason?reason:"", fullpath);
  1154. if(unlikely(unlink(fullpath) == -1))
  1155. error("Cannot delete %s file '%s'", reason?reason:"", fullpath);
  1156. else
  1157. ret++;
  1158. }
  1159. info("Deleting empty directory '%s'", path);
  1160. if(unlikely(rmdir(path) == -1))
  1161. error("Cannot delete empty directory '%s'", path);
  1162. else
  1163. ret++;
  1164. closedir(dir);
  1165. return ret;
  1166. }
  1167. static int is_virtual_filesystem(const char *path, char **reason) {
  1168. #if defined(__APPLE__) || defined(__FreeBSD__)
  1169. (void)path;
  1170. (void)reason;
  1171. #else
  1172. struct statfs stat;
  1173. // stat.f_fsid.__val[0] is a file system id
  1174. // stat.f_fsid.__val[1] is the inode
  1175. // so their combination uniquely identifies the file/dir
  1176. if (statfs(path, &stat) == -1) {
  1177. if(reason) *reason = "failed to statfs()";
  1178. return -1;
  1179. }
  1180. if(stat.f_fsid.__val[0] != 0 || stat.f_fsid.__val[1] != 0) {
  1181. errno = EINVAL;
  1182. if(reason) *reason = "is not a virtual file system";
  1183. return -1;
  1184. }
  1185. #endif
  1186. return 0;
  1187. }
  1188. int verify_netdata_host_prefix() {
  1189. if(!netdata_configured_host_prefix)
  1190. netdata_configured_host_prefix = "";
  1191. if(!*netdata_configured_host_prefix)
  1192. return 0;
  1193. char buffer[FILENAME_MAX + 1];
  1194. char *path = netdata_configured_host_prefix;
  1195. char *reason = "unknown reason";
  1196. errno = 0;
  1197. struct stat sb;
  1198. if (stat(path, &sb) == -1) {
  1199. reason = "failed to stat()";
  1200. goto failed;
  1201. }
  1202. if((sb.st_mode & S_IFMT) != S_IFDIR) {
  1203. errno = EINVAL;
  1204. reason = "is not a directory";
  1205. goto failed;
  1206. }
  1207. path = buffer;
  1208. snprintfz(path, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
  1209. if(is_virtual_filesystem(path, &reason) == -1)
  1210. goto failed;
  1211. snprintfz(path, FILENAME_MAX, "%s/sys", netdata_configured_host_prefix);
  1212. if(is_virtual_filesystem(path, &reason) == -1)
  1213. goto failed;
  1214. if(netdata_configured_host_prefix && *netdata_configured_host_prefix)
  1215. info("Using host prefix directory '%s'", netdata_configured_host_prefix);
  1216. return 0;
  1217. failed:
  1218. error("Ignoring host prefix '%s': path '%s' %s", netdata_configured_host_prefix, path, reason);
  1219. netdata_configured_host_prefix = "";
  1220. return -1;
  1221. }
  1222. char *strdupz_path_subpath(const char *path, const char *subpath) {
  1223. if(unlikely(!path || !*path)) path = ".";
  1224. if(unlikely(!subpath)) subpath = "";
  1225. // skip trailing slashes in path
  1226. size_t len = strlen(path);
  1227. while(len > 0 && path[len - 1] == '/') len--;
  1228. // skip leading slashes in subpath
  1229. while(subpath[0] == '/') subpath++;
  1230. // if the last character in path is / and (there is a subpath or path is now empty)
  1231. // keep the trailing slash in path and remove the additional slash
  1232. char *slash = "/";
  1233. if(path[len] == '/' && (*subpath || len == 0)) {
  1234. slash = "";
  1235. len++;
  1236. }
  1237. else if(!*subpath) {
  1238. // there is no subpath
  1239. // no need for trailing slash
  1240. slash = "";
  1241. }
  1242. char buffer[FILENAME_MAX + 1];
  1243. snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, subpath);
  1244. return strdupz(buffer);
  1245. }
  1246. int path_is_dir(const char *path, const char *subpath) {
  1247. char *s = strdupz_path_subpath(path, subpath);
  1248. size_t max_links = 100;
  1249. int is_dir = 0;
  1250. struct stat statbuf;
  1251. while(max_links-- && stat(s, &statbuf) == 0) {
  1252. if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
  1253. is_dir = 1;
  1254. break;
  1255. }
  1256. else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
  1257. char buffer[FILENAME_MAX + 1];
  1258. ssize_t l = readlink(s, buffer, FILENAME_MAX);
  1259. if(l > 0) {
  1260. buffer[l] = '\0';
  1261. freez(s);
  1262. s = strdupz(buffer);
  1263. continue;
  1264. }
  1265. else {
  1266. is_dir = 0;
  1267. break;
  1268. }
  1269. }
  1270. else {
  1271. is_dir = 0;
  1272. break;
  1273. }
  1274. }
  1275. freez(s);
  1276. return is_dir;
  1277. }
  1278. int path_is_file(const char *path, const char *subpath) {
  1279. char *s = strdupz_path_subpath(path, subpath);
  1280. size_t max_links = 100;
  1281. int is_file = 0;
  1282. struct stat statbuf;
  1283. while(max_links-- && stat(s, &statbuf) == 0) {
  1284. if((statbuf.st_mode & S_IFMT) == S_IFREG) {
  1285. is_file = 1;
  1286. break;
  1287. }
  1288. else if((statbuf.st_mode & S_IFMT) == S_IFLNK) {
  1289. char buffer[FILENAME_MAX + 1];
  1290. ssize_t l = readlink(s, buffer, FILENAME_MAX);
  1291. if(l > 0) {
  1292. buffer[l] = '\0';
  1293. freez(s);
  1294. s = strdupz(buffer);
  1295. continue;
  1296. }
  1297. else {
  1298. is_file = 0;
  1299. break;
  1300. }
  1301. }
  1302. else {
  1303. is_file = 0;
  1304. break;
  1305. }
  1306. }
  1307. freez(s);
  1308. return is_file;
  1309. }
  1310. void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath, int (*callback)(const char *filename, void *data), void *data, size_t depth) {
  1311. if(depth > 3) {
  1312. error("CONFIG: Max directory depth reached while reading user path '%s', stock path '%s', subpath '%s'", user_path, stock_path, subpath);
  1313. return;
  1314. }
  1315. char *udir = strdupz_path_subpath(user_path, subpath);
  1316. char *sdir = strdupz_path_subpath(stock_path, subpath);
  1317. debug(D_HEALTH, "CONFIG traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
  1318. DIR *dir = opendir(udir);
  1319. if (!dir) {
  1320. error("CONFIG cannot open user-config directory '%s'.", udir);
  1321. }
  1322. else {
  1323. struct dirent *de = NULL;
  1324. while((de = readdir(dir))) {
  1325. if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
  1326. if( !de->d_name[0] ||
  1327. (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
  1328. (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1329. ) {
  1330. debug(D_HEALTH, "CONFIG ignoring user-config directory '%s/%s'", udir, de->d_name);
  1331. continue;
  1332. }
  1333. if(path_is_dir(udir, de->d_name)) {
  1334. recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
  1335. continue;
  1336. }
  1337. }
  1338. if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
  1339. size_t len = strlen(de->d_name);
  1340. if(path_is_file(udir, de->d_name) &&
  1341. len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
  1342. char *filename = strdupz_path_subpath(udir, de->d_name);
  1343. debug(D_HEALTH, "CONFIG calling callback for user file '%s'", filename);
  1344. callback(filename, data);
  1345. freez(filename);
  1346. continue;
  1347. }
  1348. }
  1349. debug(D_HEALTH, "CONFIG ignoring user-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
  1350. }
  1351. closedir(dir);
  1352. }
  1353. debug(D_HEALTH, "CONFIG traversing stock config directory '%s', user config directory '%s'", sdir, udir);
  1354. dir = opendir(sdir);
  1355. if (!dir) {
  1356. error("CONFIG cannot open stock config directory '%s'.", sdir);
  1357. }
  1358. else {
  1359. if (strcmp(udir, sdir)) {
  1360. struct dirent *de = NULL;
  1361. while((de = readdir(dir))) {
  1362. if(de->d_type == DT_DIR || de->d_type == DT_LNK) {
  1363. if( !de->d_name[0] ||
  1364. (de->d_name[0] == '.' && de->d_name[1] == '\0') ||
  1365. (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
  1366. ) {
  1367. debug(D_HEALTH, "CONFIG ignoring stock config directory '%s/%s'", sdir, de->d_name);
  1368. continue;
  1369. }
  1370. if(path_is_dir(sdir, de->d_name)) {
  1371. // we recurse in stock subdirectory, only when there is no corresponding
  1372. // user subdirectory - to avoid reading the files twice
  1373. if(!path_is_dir(udir, de->d_name))
  1374. recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data, depth + 1);
  1375. continue;
  1376. }
  1377. }
  1378. if(de->d_type == DT_UNKNOWN || de->d_type == DT_REG || de->d_type == DT_LNK) {
  1379. size_t len = strlen(de->d_name);
  1380. if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) &&
  1381. len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
  1382. char *filename = strdupz_path_subpath(sdir, de->d_name);
  1383. debug(D_HEALTH, "CONFIG calling callback for stock file '%s'", filename);
  1384. callback(filename, data);
  1385. freez(filename);
  1386. continue;
  1387. }
  1388. }
  1389. debug(D_HEALTH, "CONFIG ignoring stock-config file '%s/%s' of type %d", udir, de->d_name, (int)de->d_type);
  1390. }
  1391. }
  1392. closedir(dir);
  1393. }
  1394. debug(D_HEALTH, "CONFIG done traversing user-config directory '%s', stock config directory '%s'", udir, sdir);
  1395. freez(udir);
  1396. freez(sdir);
  1397. }
  1398. // Returns the number of bytes read from the file if file_size is not NULL.
  1399. // The actual buffer has an extra byte set to zero (not included in the count).
  1400. char *read_by_filename(char *filename, long *file_size)
  1401. {
  1402. FILE *f = fopen(filename, "r");
  1403. if (!f)
  1404. return NULL;
  1405. if (fseek(f, 0, SEEK_END) < 0) {
  1406. fclose(f);
  1407. return NULL;
  1408. }
  1409. long size = ftell(f);
  1410. if (size <= 0 || fseek(f, 0, SEEK_END) < 0) {
  1411. fclose(f);
  1412. return NULL;
  1413. }
  1414. char *contents = callocz(size + 1, 1);
  1415. if (!contents) {
  1416. fclose(f);
  1417. return NULL;
  1418. }
  1419. if (fseek(f, 0, SEEK_SET) < 0) {
  1420. fclose(f);
  1421. freez(contents);
  1422. return NULL;
  1423. }
  1424. size_t res = fread(contents, 1, size, f);
  1425. if ( res != (size_t)size) {
  1426. freez(contents);
  1427. fclose(f);
  1428. return NULL;
  1429. }
  1430. fclose(f);
  1431. if (file_size)
  1432. *file_size = size;
  1433. return contents;
  1434. }
  1435. char *find_and_replace(const char *src, const char *find, const char *replace, const char *where)
  1436. {
  1437. size_t size = strlen(src) + 1;
  1438. size_t find_len = strlen(find);
  1439. size_t repl_len = strlen(replace);
  1440. char *value, *dst;
  1441. if (likely(where))
  1442. size += (repl_len - find_len);
  1443. value = mallocz(size);
  1444. dst = value;
  1445. if (likely(where)) {
  1446. size_t count = where - src;
  1447. memmove(dst, src, count);
  1448. src += count;
  1449. dst += count;
  1450. memmove(dst, replace, repl_len);
  1451. src += find_len;
  1452. dst += repl_len;
  1453. }
  1454. strcpy(dst, src);
  1455. return value;
  1456. }
  1457. inline int pluginsd_space(char c) {
  1458. switch(c) {
  1459. case ' ':
  1460. case '\t':
  1461. case '\r':
  1462. case '\n':
  1463. case '=':
  1464. return 1;
  1465. default:
  1466. return 0;
  1467. }
  1468. }
  1469. inline int config_isspace(char c)
  1470. {
  1471. switch (c) {
  1472. case ' ':
  1473. case '\t':
  1474. case '\r':
  1475. case '\n':
  1476. case ',':
  1477. return 1;
  1478. default:
  1479. return 0;
  1480. }
  1481. }
  1482. // split a text into words, respecting quotes
  1483. inline size_t quoted_strings_splitter(char *str, char **words, size_t max_words, int (*custom_isspace)(char))
  1484. {
  1485. char *s = str, quote = 0;
  1486. size_t i = 0;
  1487. // skip all white space
  1488. while (unlikely(custom_isspace(*s)))
  1489. s++;
  1490. if(unlikely(!*s)) {
  1491. words[i] = NULL;
  1492. return 0;
  1493. }
  1494. // check for quote
  1495. if (unlikely(*s == '\'' || *s == '"')) {
  1496. quote = *s; // remember the quote
  1497. s++; // skip the quote
  1498. }
  1499. // store the first word
  1500. words[i++] = s;
  1501. // while we have something
  1502. while (likely(*s)) {
  1503. // if it is an escape
  1504. if (unlikely(*s == '\\' && s[1])) {
  1505. s += 2;
  1506. continue;
  1507. }
  1508. // if it is a quote
  1509. else if (unlikely(*s == quote)) {
  1510. quote = 0;
  1511. *s = ' ';
  1512. continue;
  1513. }
  1514. // if it is a space
  1515. else if (unlikely(quote == 0 && custom_isspace(*s))) {
  1516. // terminate the word
  1517. *s++ = '\0';
  1518. // skip all white space
  1519. while (likely(custom_isspace(*s)))
  1520. s++;
  1521. // check for a quote
  1522. if (unlikely(*s == '\'' || *s == '"')) {
  1523. quote = *s; // remember the quote
  1524. s++; // skip the quote
  1525. }
  1526. // if we reached the end, stop
  1527. if (unlikely(!*s))
  1528. break;
  1529. // store the next word
  1530. if (likely(i < max_words))
  1531. words[i++] = s;
  1532. else
  1533. break;
  1534. }
  1535. // anything else
  1536. else
  1537. s++;
  1538. }
  1539. if (i < max_words)
  1540. words[i] = NULL;
  1541. return i;
  1542. }
  1543. inline size_t pluginsd_split_words(char *str, char **words, size_t max_words)
  1544. {
  1545. return quoted_strings_splitter(str, words, max_words, pluginsd_space);
  1546. }
  1547. bool bitmap256_get_bit(BITMAP256 *ptr, uint8_t idx) {
  1548. if (unlikely(!ptr))
  1549. return false;
  1550. return (ptr->data[idx / 64] & (1ULL << (idx % 64)));
  1551. }
  1552. void bitmap256_set_bit(BITMAP256 *ptr, uint8_t idx, bool value) {
  1553. if (unlikely(!ptr))
  1554. return;
  1555. if (likely(value))
  1556. ptr->data[idx / 64] |= (1ULL << (idx % 64));
  1557. else
  1558. ptr->data[idx / 64] &= ~(1ULL << (idx % 64));
  1559. }
  1560. bool run_command_and_copy_output_to_stdout(const char *command, int max_line_length) {
  1561. pid_t pid;
  1562. FILE *fp = netdata_popen(command, &pid, NULL);
  1563. if(fp) {
  1564. char buffer[max_line_length + 1];
  1565. while (fgets(buffer, max_line_length, fp))
  1566. fprintf(stdout, "%s", buffer);
  1567. }
  1568. else {
  1569. error("Failed to execute command '%s'.", command);
  1570. return false;
  1571. }
  1572. netdata_pclose(NULL, fp, pid);
  1573. return true;
  1574. }
  1575. void for_each_open_fd(OPEN_FD_ACTION action, OPEN_FD_EXCLUDE excluded_fds){
  1576. int fd;
  1577. switch(action){
  1578. case OPEN_FD_ACTION_CLOSE:
  1579. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDIN)) (void)close(STDIN_FILENO);
  1580. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDOUT)) (void)close(STDOUT_FILENO);
  1581. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDERR)) (void)close(STDERR_FILENO);
  1582. #if defined(HAVE_CLOSE_RANGE)
  1583. if(close_range(STDERR_FILENO + 1, ~0U, 0) == 0) return;
  1584. error("close_range() failed, will try to close fds one by one");
  1585. #endif
  1586. break;
  1587. case OPEN_FD_ACTION_FD_CLOEXEC:
  1588. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDIN)) (void)fcntl(STDIN_FILENO, F_SETFD, FD_CLOEXEC);
  1589. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDOUT)) (void)fcntl(STDOUT_FILENO, F_SETFD, FD_CLOEXEC);
  1590. if(!(excluded_fds & OPEN_FD_EXCLUDE_STDERR)) (void)fcntl(STDERR_FILENO, F_SETFD, FD_CLOEXEC);
  1591. #if defined(HAVE_CLOSE_RANGE) && defined(CLOSE_RANGE_CLOEXEC) // Linux >= 5.11, FreeBSD >= 13.1
  1592. if(close_range(STDERR_FILENO + 1, ~0U, CLOSE_RANGE_CLOEXEC) == 0) return;
  1593. error("close_range() failed, will try to mark fds for closing one by one");
  1594. #endif
  1595. break;
  1596. default:
  1597. break; // do nothing
  1598. }
  1599. DIR *dir = opendir("/proc/self/fd");
  1600. if (dir == NULL) {
  1601. struct rlimit rl;
  1602. int open_max = -1;
  1603. if(getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) open_max = rl.rlim_max;
  1604. #ifdef _SC_OPEN_MAX
  1605. else open_max = sysconf(_SC_OPEN_MAX);
  1606. #endif
  1607. if (open_max == -1) open_max = 65535; // 65535 arbitrary default if everything else fails
  1608. for (fd = STDERR_FILENO + 1; fd < open_max; fd++) {
  1609. switch(action){
  1610. case OPEN_FD_ACTION_CLOSE:
  1611. if(fd_is_valid(fd)) (void)close(fd);
  1612. break;
  1613. case OPEN_FD_ACTION_FD_CLOEXEC:
  1614. (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
  1615. break;
  1616. default:
  1617. break; // do nothing
  1618. }
  1619. }
  1620. } else {
  1621. struct dirent *entry;
  1622. while ((entry = readdir(dir)) != NULL) {
  1623. fd = str2i(entry->d_name);
  1624. if(unlikely((fd == STDIN_FILENO ) || (fd == STDOUT_FILENO) || (fd == STDERR_FILENO) )) continue;
  1625. switch(action){
  1626. case OPEN_FD_ACTION_CLOSE:
  1627. if(fd_is_valid(fd)) (void)close(fd);
  1628. break;
  1629. case OPEN_FD_ACTION_FD_CLOEXEC:
  1630. (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
  1631. break;
  1632. default:
  1633. break; // do nothing
  1634. }
  1635. }
  1636. closedir(dir);
  1637. }
  1638. }
  1639. struct timing_steps {
  1640. const char *name;
  1641. usec_t time;
  1642. size_t count;
  1643. } timing_steps[TIMING_STEP_MAX + 1] = {
  1644. [TIMING_STEP_INTERNAL] = { .name = "internal", .time = 0, },
  1645. [TIMING_STEP_BEGIN2_PREPARE] = { .name = "BEGIN2 prepare", .time = 0, },
  1646. [TIMING_STEP_BEGIN2_FIND_CHART] = { .name = "BEGIN2 find chart", .time = 0, },
  1647. [TIMING_STEP_BEGIN2_PARSE] = { .name = "BEGIN2 parse", .time = 0, },
  1648. [TIMING_STEP_BEGIN2_ML] = { .name = "BEGIN2 ml", .time = 0, },
  1649. [TIMING_STEP_BEGIN2_PROPAGATE] = { .name = "BEGIN2 propagate", .time = 0, },
  1650. [TIMING_STEP_BEGIN2_STORE] = { .name = "BEGIN2 store", .time = 0, },
  1651. [TIMING_STEP_SET2_PREPARE] = { .name = "SET2 prepare", .time = 0, },
  1652. [TIMING_STEP_SET2_LOOKUP_DIMENSION] = { .name = "SET2 find dimension", .time = 0, },
  1653. [TIMING_STEP_SET2_PARSE] = { .name = "SET2 parse", .time = 0, },
  1654. [TIMING_STEP_SET2_ML] = { .name = "SET2 ml", .time = 0, },
  1655. [TIMING_STEP_SET2_PROPAGATE] = { .name = "SET2 propagate", .time = 0, },
  1656. [TIMING_STEP_RRDSET_STORE_METRIC] = { .name = "SET2 rrdset store", .time = 0, },
  1657. [TIMING_STEP_DBENGINE_FIRST_CHECK] = { .name = "db 1st check", .time = 0, },
  1658. [TIMING_STEP_DBENGINE_CHECK_DATA] = { .name = "db check data", .time = 0, },
  1659. [TIMING_STEP_DBENGINE_PACK] = { .name = "db pack", .time = 0, },
  1660. [TIMING_STEP_DBENGINE_PAGE_FIN] = { .name = "db page fin", .time = 0, },
  1661. [TIMING_STEP_DBENGINE_MRG_UPDATE] = { .name = "db mrg update", .time = 0, },
  1662. [TIMING_STEP_DBENGINE_PAGE_ALLOC] = { .name = "db page alloc", .time = 0, },
  1663. [TIMING_STEP_DBENGINE_CREATE_NEW_PAGE] = { .name = "db new page", .time = 0, },
  1664. [TIMING_STEP_DBENGINE_FLUSH_PAGE] = { .name = "db page flush", .time = 0, },
  1665. [TIMING_STEP_SET2_STORE] = { .name = "SET2 store", .time = 0, },
  1666. [TIMING_STEP_END2_PREPARE] = { .name = "END2 prepare", .time = 0, },
  1667. [TIMING_STEP_END2_PUSH_V1] = { .name = "END2 push v1", .time = 0, },
  1668. [TIMING_STEP_END2_ML] = { .name = "END2 ml", .time = 0, },
  1669. [TIMING_STEP_END2_RRDSET] = { .name = "END2 rrdset", .time = 0, },
  1670. [TIMING_STEP_END2_PROPAGATE] = { .name = "END2 propagate", .time = 0, },
  1671. [TIMING_STEP_END2_STORE] = { .name = "END2 store", .time = 0, },
  1672. // terminator
  1673. [TIMING_STEP_MAX] = { .name = NULL, .time = 0, },
  1674. };
  1675. void timing_action(TIMING_ACTION action, TIMING_STEP step) {
  1676. static __thread usec_t last_action_time = 0;
  1677. static struct timing_steps timings2[TIMING_STEP_MAX + 1] = {};
  1678. switch(action) {
  1679. case TIMING_ACTION_INIT:
  1680. last_action_time = now_monotonic_usec();
  1681. break;
  1682. case TIMING_ACTION_STEP: {
  1683. if(!last_action_time)
  1684. return;
  1685. usec_t now = now_monotonic_usec();
  1686. __atomic_add_fetch(&timing_steps[step].time, now - last_action_time, __ATOMIC_RELAXED);
  1687. __atomic_add_fetch(&timing_steps[step].count, 1, __ATOMIC_RELAXED);
  1688. last_action_time = now;
  1689. break;
  1690. }
  1691. case TIMING_ACTION_FINISH: {
  1692. if(!last_action_time)
  1693. return;
  1694. usec_t expected = __atomic_load_n(&timing_steps[TIMING_STEP_INTERNAL].time, __ATOMIC_RELAXED);
  1695. if(last_action_time - expected < 10 * USEC_PER_SEC) {
  1696. last_action_time = 0;
  1697. return;
  1698. }
  1699. if(!__atomic_compare_exchange_n(&timing_steps[TIMING_STEP_INTERNAL].time, &expected, last_action_time, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
  1700. last_action_time = 0;
  1701. return;
  1702. }
  1703. struct timing_steps timings3[TIMING_STEP_MAX + 1];
  1704. memcpy(timings3, timing_steps, sizeof(timings3));
  1705. size_t total_reqs = 0;
  1706. usec_t total_usec = 0;
  1707. for(size_t t = 1; t < TIMING_STEP_MAX ; t++) {
  1708. total_usec += timings3[t].time - timings2[t].time;
  1709. total_reqs += timings3[t].count - timings2[t].count;
  1710. }
  1711. BUFFER *wb = buffer_create(1024, NULL);
  1712. for(size_t t = 1; t < TIMING_STEP_MAX ; t++) {
  1713. size_t requests = timings3[t].count - timings2[t].count;
  1714. if(!requests) continue;
  1715. buffer_sprintf(wb, "TIMINGS REPORT: [%3zu. %-20s]: # %10zu, t %11.2f ms (%6.2f %%), avg %6.2f usec/run\n",
  1716. t,
  1717. timing_steps[t].name ? timing_steps[t].name : "x",
  1718. requests,
  1719. (double) (timings3[t].time - timings2[t].time) / (double)USEC_PER_MS,
  1720. (double) (timings3[t].time - timings2[t].time) * 100.0 / (double) total_usec,
  1721. (double) (timings3[t].time - timings2[t].time) / (double)requests
  1722. );
  1723. }
  1724. info("TIMINGS REPORT:\n%sTIMINGS REPORT: total # %10zu, t %11.2f ms",
  1725. buffer_tostring(wb), total_reqs, (double)total_usec / USEC_PER_MS);
  1726. memcpy(timings2, timings3, sizeof(timings2));
  1727. last_action_time = 0;
  1728. buffer_free(wb);
  1729. }
  1730. }
  1731. }
  1732. int hash256_string(const unsigned char *string, size_t size, char *hash) {
  1733. EVP_MD_CTX *ctx;
  1734. ctx = EVP_MD_CTX_create();
  1735. if (!ctx)
  1736. return 0;
  1737. if (!EVP_DigestInit(ctx, EVP_sha256())) {
  1738. EVP_MD_CTX_destroy(ctx);
  1739. return 0;
  1740. }
  1741. if (!EVP_DigestUpdate(ctx, string, size)) {
  1742. EVP_MD_CTX_destroy(ctx);
  1743. return 0;
  1744. }
  1745. if (!EVP_DigestFinal(ctx, (unsigned char *)hash, NULL)) {
  1746. EVP_MD_CTX_destroy(ctx);
  1747. return 0;
  1748. }
  1749. return 1;
  1750. }