sqlite_context.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "sqlite_functions.h"
  3. #include "sqlite_context.h"
  4. #include "sqlite_db_migration.h"
  5. #define DB_CONTEXT_METADATA_VERSION 1
  6. const char *database_context_config[] = {
  7. "CREATE TABLE IF NOT EXISTS context (host_id BLOB, id TEXT NOT NULL, version INT NOT NULL, title TEXT NOT NULL, " \
  8. "chart_type TEXT NOT NULL, unit TEXT NOT NULL, priority INT NOT NULL, first_time_t INT NOT NULL, "
  9. "last_time_t INT NOT NULL, deleted INT NOT NULL, "
  10. "family TEXT, PRIMARY KEY (host_id, id));",
  11. NULL
  12. };
  13. const char *database_context_cleanup[] = {
  14. "VACUUM;",
  15. NULL
  16. };
  17. sqlite3 *db_context_meta = NULL;
  18. /*
  19. * Initialize the SQLite database
  20. * Return 0 on success
  21. */
  22. int sql_init_context_database(int memory)
  23. {
  24. char sqlite_database[FILENAME_MAX + 1];
  25. int rc;
  26. if (likely(!memory))
  27. snprintfz(sqlite_database, FILENAME_MAX, "%s/context-meta.db", netdata_configured_cache_dir);
  28. else
  29. strcpy(sqlite_database, ":memory:");
  30. rc = sqlite3_open(sqlite_database, &db_context_meta);
  31. if (rc != SQLITE_OK) {
  32. error_report("Failed to initialize database at %s, due to \"%s\"", sqlite_database, sqlite3_errstr(rc));
  33. sqlite3_close(db_context_meta);
  34. db_context_meta = NULL;
  35. return 1;
  36. }
  37. info("SQLite database %s initialization", sqlite_database);
  38. char buf[1024 + 1] = "";
  39. const char *list[2] = { buf, NULL };
  40. int target_version = DB_CONTEXT_METADATA_VERSION;
  41. if (likely(!memory))
  42. target_version = perform_context_database_migration(db_context_meta, DB_CONTEXT_METADATA_VERSION);
  43. // https://www.sqlite.org/pragma.html#pragma_auto_vacuum
  44. // PRAGMA schema.auto_vacuum = 0 | NONE | 1 | FULL | 2 | INCREMENTAL;
  45. snprintfz(buf, 1024, "PRAGMA auto_vacuum=%s;", config_get(CONFIG_SECTION_SQLITE, "auto vacuum", "INCREMENTAL"));
  46. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  47. // https://www.sqlite.org/pragma.html#pragma_synchronous
  48. // PRAGMA schema.synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL | 3 | EXTRA;
  49. snprintfz(buf, 1024, "PRAGMA synchronous=%s;", config_get(CONFIG_SECTION_SQLITE, "synchronous", "NORMAL"));
  50. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  51. // https://www.sqlite.org/pragma.html#pragma_journal_mode
  52. // PRAGMA schema.journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF
  53. snprintfz(buf, 1024, "PRAGMA journal_mode=%s;", config_get(CONFIG_SECTION_SQLITE, "journal mode", "WAL"));
  54. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  55. // https://www.sqlite.org/pragma.html#pragma_temp_store
  56. // PRAGMA temp_store = 0 | DEFAULT | 1 | FILE | 2 | MEMORY;
  57. snprintfz(buf, 1024, "PRAGMA temp_store=%s;", config_get(CONFIG_SECTION_SQLITE, "temp store", "MEMORY"));
  58. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  59. // https://www.sqlite.org/pragma.html#pragma_journal_size_limit
  60. // PRAGMA schema.journal_size_limit = N ;
  61. snprintfz(buf, 1024, "PRAGMA journal_size_limit=%lld;", config_get_number(CONFIG_SECTION_SQLITE, "journal size limit", 16777216));
  62. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  63. // https://www.sqlite.org/pragma.html#pragma_cache_size
  64. // PRAGMA schema.cache_size = pages;
  65. // PRAGMA schema.cache_size = -kibibytes;
  66. snprintfz(buf, 1024, "PRAGMA cache_size=%lld;", config_get_number(CONFIG_SECTION_SQLITE, "cache size", -2000));
  67. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  68. snprintfz(buf, 1024, "PRAGMA user_version=%d;", target_version);
  69. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  70. snprintfz(buf, 1024, "ATTACH DATABASE \"%s/netdata-meta.db\" as meta;", netdata_configured_cache_dir);
  71. if(init_database_batch(db_context_meta, DB_CHECK_NONE, 0, list)) return 1;
  72. if (init_database_batch(db_context_meta, DB_CHECK_NONE, 0, &database_context_config[0]))
  73. return 1;
  74. if (init_database_batch(db_context_meta, DB_CHECK_NONE, 0, &database_context_cleanup[0]))
  75. return 1;
  76. return 0;
  77. }
  78. /*
  79. * Close the sqlite database
  80. */
  81. void sql_close_context_database(void)
  82. {
  83. int rc;
  84. if (unlikely(!db_context_meta))
  85. return;
  86. info("Closing context SQLite database");
  87. rc = sqlite3_close_v2(db_context_meta);
  88. if (unlikely(rc != SQLITE_OK))
  89. error_report("Error %d while closing the context SQLite database, %s", rc, sqlite3_errstr(rc));
  90. return;
  91. }
  92. //
  93. // Fetching data
  94. //
  95. #define CTX_GET_CHART_LIST "SELECT c.chart_id, c.type||'.'||c.id, c.name, c.context, c.title, c.unit, c.priority, " \
  96. "c.update_every, c.chart_type, c.family FROM meta.chart c WHERE c.host_id = @host_id; "
  97. void ctx_get_chart_list(uuid_t *host_uuid, void (*dict_cb)(SQL_CHART_DATA *, void *), void *data)
  98. {
  99. int rc;
  100. sqlite3_stmt *res = NULL;
  101. if (unlikely(!host_uuid)) {
  102. internal_error(true, "Requesting context chart list without host_id");
  103. return;
  104. }
  105. rc = sqlite3_prepare_v2(db_context_meta, CTX_GET_CHART_LIST, -1, &res, 0);
  106. if (unlikely(rc != SQLITE_OK)) {
  107. error_report("Failed to prepare statement to fetch chart list");
  108. return;
  109. }
  110. if (likely(host_uuid))
  111. rc = sqlite3_bind_blob(res, 1, host_uuid, sizeof(*host_uuid), SQLITE_STATIC);
  112. else
  113. rc = sqlite3_bind_null(res, 1);
  114. if (unlikely(rc != SQLITE_OK)) {
  115. error_report("Failed to bind host_id to fetch the chart list");
  116. goto failed;
  117. }
  118. SQL_CHART_DATA chart_data = { 0 };
  119. while (sqlite3_step(res) == SQLITE_ROW) {
  120. uuid_copy(chart_data.chart_id, *((uuid_t *)sqlite3_column_blob(res, 0)));
  121. chart_data.id = (char *) sqlite3_column_text(res, 1);
  122. chart_data.name = (char *) sqlite3_column_text(res, 2);
  123. chart_data.context = (char *) sqlite3_column_text(res, 3);
  124. chart_data.title = (char *) sqlite3_column_text(res, 4);
  125. chart_data.units = (char *) sqlite3_column_text(res, 5);
  126. chart_data.priority = sqlite3_column_int(res, 6);
  127. chart_data.update_every = sqlite3_column_int(res, 7);
  128. chart_data.chart_type = sqlite3_column_int(res, 8);
  129. chart_data.family = (char *) sqlite3_column_text(res, 9);
  130. dict_cb(&chart_data, data);
  131. }
  132. failed:
  133. rc = sqlite3_finalize(res);
  134. if (rc != SQLITE_OK)
  135. error_report("Failed to finalize statement that fetches chart label data, rc = %d", rc);
  136. }
  137. // Dimension list
  138. #define CTX_GET_DIMENSION_LIST "SELECT d.dim_id, d.id, d.name FROM meta.dimension d WHERE d.chart_id = @id;"
  139. void ctx_get_dimension_list(uuid_t *chart_uuid, void (*dict_cb)(SQL_DIMENSION_DATA *, void *), void *data)
  140. {
  141. int rc;
  142. sqlite3_stmt *res = NULL;
  143. rc = sqlite3_prepare_v2(db_context_meta, CTX_GET_DIMENSION_LIST, -1, &res, 0);
  144. if (unlikely(rc != SQLITE_OK)) {
  145. error_report("Failed to prepare statement to fetch chart dimension data");
  146. return;
  147. }
  148. rc = sqlite3_bind_blob(res, 1, chart_uuid, sizeof(*chart_uuid), SQLITE_STATIC);
  149. if (unlikely(rc != SQLITE_OK)) {
  150. error_report("Failed to bind chart_id to fetch dimension list");
  151. goto failed;
  152. }
  153. SQL_DIMENSION_DATA dimension_data;
  154. while (sqlite3_step(res) == SQLITE_ROW) {
  155. uuid_copy(dimension_data.dim_id, *((uuid_t *)sqlite3_column_blob(res, 0)));
  156. dimension_data.id = (char *) sqlite3_column_text(res, 1);
  157. dimension_data.name = (char *) sqlite3_column_text(res, 2);
  158. dict_cb(&dimension_data, data);
  159. }
  160. failed:
  161. rc = sqlite3_finalize(res);
  162. if (rc != SQLITE_OK)
  163. error_report("Failed to finalize statement that fetches the chart dimension list, rc = %d", rc);
  164. }
  165. // LABEL LIST
  166. #define CTX_GET_LABEL_LIST "SELECT l.label_key, l.label_value, l.source_type FROM meta.chart_label l WHERE l.chart_id = @id;"
  167. void ctx_get_label_list(uuid_t *chart_uuid, void (*dict_cb)(SQL_CLABEL_DATA *, void *), void *data)
  168. {
  169. int rc;
  170. sqlite3_stmt *res = NULL;
  171. rc = sqlite3_prepare_v2(db_context_meta, CTX_GET_LABEL_LIST, -1, &res, 0);
  172. if (unlikely(rc != SQLITE_OK)) {
  173. error_report("Failed to prepare statement to fetch chart lanbels");
  174. return;
  175. }
  176. rc = sqlite3_bind_blob(res, 1, chart_uuid, sizeof(*chart_uuid), SQLITE_STATIC);
  177. if (unlikely(rc != SQLITE_OK)) {
  178. error_report("Failed to bind chart_id to fetch chart labels");
  179. goto failed;
  180. }
  181. SQL_CLABEL_DATA label_data;
  182. while (sqlite3_step(res) == SQLITE_ROW) {
  183. label_data.label_key = (char *) sqlite3_column_text(res, 0);
  184. label_data.label_value = (char *) sqlite3_column_text(res, 1);
  185. label_data.label_source = sqlite3_column_int(res, 2);
  186. dict_cb(&label_data, data);
  187. }
  188. failed:
  189. rc = sqlite3_finalize(res);
  190. if (rc != SQLITE_OK)
  191. error_report("Failed to finalize statement that fetches chart label data, rc = %d", rc);
  192. return;
  193. }
  194. // CONTEXT LIST
  195. #define CTX_GET_CONTEXT_LIST "SELECT id, version, title, chart_type, unit, priority, first_time_t, " \
  196. "last_time_t, deleted, family FROM context c WHERE c.host_id = @host_id;"
  197. void ctx_get_context_list(uuid_t *host_uuid, void (*dict_cb)(VERSIONED_CONTEXT_DATA *, void *), void *data)
  198. {
  199. if (unlikely(!host_uuid))
  200. return;
  201. int rc;
  202. sqlite3_stmt *res = NULL;
  203. rc = sqlite3_prepare_v2(db_context_meta, CTX_GET_CONTEXT_LIST, -1, &res, 0);
  204. if (unlikely(rc != SQLITE_OK)) {
  205. error_report("Failed to prepare statement to fetch stored context list");
  206. return;
  207. }
  208. VERSIONED_CONTEXT_DATA context_data = {0};
  209. rc = sqlite3_bind_blob(res, 1, host_uuid, sizeof(*host_uuid), SQLITE_STATIC);
  210. if (unlikely(rc != SQLITE_OK)) {
  211. error_report("Failed to bind host_id to fetch versioned context data");
  212. goto failed;
  213. }
  214. while (sqlite3_step(res) == SQLITE_ROW) {
  215. context_data.id = (char *) sqlite3_column_text(res, 0);
  216. context_data.version = sqlite3_column_int64(res, 1);
  217. context_data.title = (char *) sqlite3_column_text(res, 2);
  218. context_data.chart_type = (char *) sqlite3_column_text(res, 3);
  219. context_data.units = (char *) sqlite3_column_text(res, 4);
  220. context_data.priority = sqlite3_column_int64(res, 5);
  221. context_data.first_time_t = sqlite3_column_int64(res, 6);
  222. context_data.last_time_t = sqlite3_column_int64(res, 7);
  223. context_data.deleted = sqlite3_column_int(res, 8);
  224. context_data.family = (char *) sqlite3_column_text(res, 9);
  225. dict_cb(&context_data, data);
  226. }
  227. failed:
  228. rc = sqlite3_finalize(res);
  229. if (rc != SQLITE_OK)
  230. error_report("Failed to finalize statement that fetches stored context versioned data, rc = %d", rc);
  231. }
  232. //
  233. // Storing Data
  234. //
  235. #define CTX_STORE_CONTEXT "INSERT OR REPLACE INTO context " \
  236. "(host_id, id, version, title, chart_type, unit, priority, first_time_t, last_time_t, deleted, family) " \
  237. "VALUES (@host_id, @context, @version, @title, @chart_type, @unit, @priority, @first_time_t, @last_time_t, @deleted, @family);"
  238. int ctx_store_context(uuid_t *host_uuid, VERSIONED_CONTEXT_DATA *context_data)
  239. {
  240. int rc, rc_stored = 1;
  241. sqlite3_stmt *res = NULL;
  242. if (unlikely(!host_uuid || !context_data || !context_data->id))
  243. return 0;
  244. rc = sqlite3_prepare_v2(db_context_meta, CTX_STORE_CONTEXT, -1, &res, 0);
  245. if (unlikely(rc != SQLITE_OK)) {
  246. error_report("Failed to prepare statement to store context");
  247. return 1;
  248. }
  249. rc = sqlite3_bind_blob(res, 1, host_uuid, sizeof(*host_uuid), SQLITE_STATIC);
  250. if (unlikely(rc != SQLITE_OK)) {
  251. error_report("Failed to bind host_uuid to store context details");
  252. goto skip_store;
  253. }
  254. rc = bind_text_null(res, 2, context_data->id, 0);
  255. if (unlikely(rc != SQLITE_OK)) {
  256. error_report("Failed to bind context to store details");
  257. goto skip_store;
  258. }
  259. rc = sqlite3_bind_int64(res, 3, (time_t) context_data->version);
  260. if (unlikely(rc != SQLITE_OK)) {
  261. error_report("Failed to bind first_time_t to store context details");
  262. goto skip_store;
  263. }
  264. rc = bind_text_null(res, 4, context_data->title, 0);
  265. if (unlikely(rc != SQLITE_OK)) {
  266. error_report("Failed to bind context to store details");
  267. goto skip_store;
  268. }
  269. rc = bind_text_null(res, 5, context_data->chart_type, 0);
  270. if (unlikely(rc != SQLITE_OK)) {
  271. error_report("Failed to bind context to store details");
  272. goto skip_store;
  273. }
  274. rc = bind_text_null(res, 6, context_data->units, 0);
  275. if (unlikely(rc != SQLITE_OK)) {
  276. error_report("Failed to bind context to store details");
  277. goto skip_store;
  278. }
  279. rc = sqlite3_bind_int64(res, 7, (time_t) context_data->priority);
  280. if (unlikely(rc != SQLITE_OK)) {
  281. error_report("Failed to bind first_time_t to store context details");
  282. goto skip_store;
  283. }
  284. rc = sqlite3_bind_int64(res, 8, (time_t) context_data->first_time_t);
  285. if (unlikely(rc != SQLITE_OK)) {
  286. error_report("Failed to bind first_time_t to store context details");
  287. goto skip_store;
  288. }
  289. rc = sqlite3_bind_int64(res, 9, (time_t) context_data->last_time_t);
  290. if (unlikely(rc != SQLITE_OK)) {
  291. error_report("Failed to bind last_time_t to store context details");
  292. goto skip_store;
  293. }
  294. rc = sqlite3_bind_int(res, 10, (time_t) context_data->deleted);
  295. if (unlikely(rc != SQLITE_OK)) {
  296. error_report("Failed to bind last_time_t to store context details");
  297. goto skip_store;
  298. }
  299. rc = bind_text_null(res, 11, context_data->family, 1);
  300. if (unlikely(rc != SQLITE_OK)) {
  301. error_report("Failed to bind context to store details");
  302. goto skip_store;
  303. }
  304. rc_stored = execute_insert(res);
  305. if (rc_stored != SQLITE_DONE)
  306. error_report("Failed store context details for context %s, rc = %d", context_data->id, rc_stored);
  307. skip_store:
  308. rc = sqlite3_finalize(res);
  309. if (rc != SQLITE_OK)
  310. error_report("Failed to finalize statement that stores context details, rc = %d", rc);
  311. return (rc_stored != SQLITE_DONE);
  312. }
  313. // Delete a context
  314. #define CTX_DELETE_CONTEXT "DELETE FROM context WHERE host_id = @host_id AND id = @context;"
  315. int ctx_delete_context(uuid_t *host_uuid, VERSIONED_CONTEXT_DATA *context_data)
  316. {
  317. int rc, rc_stored = 1;
  318. sqlite3_stmt *res = NULL;
  319. if (unlikely(!context_data || !context_data->id))
  320. return 0;
  321. rc = sqlite3_prepare_v2(db_context_meta, CTX_DELETE_CONTEXT, -1, &res, 0);
  322. if (unlikely(rc != SQLITE_OK)) {
  323. error_report("Failed to prepare statement to delete context");
  324. return 1;
  325. }
  326. rc = sqlite3_bind_blob(res, 1, host_uuid, sizeof(*host_uuid), SQLITE_STATIC);
  327. if (unlikely(rc != SQLITE_OK)) {
  328. error_report("Failed to bind host_id to delete context data");
  329. goto skip_delete;
  330. }
  331. rc = sqlite3_bind_text(res, 2, context_data->id, -1, SQLITE_STATIC);
  332. if (unlikely(rc != SQLITE_OK)) {
  333. error_report("Failed to bind context id for data deletion");
  334. goto skip_delete;
  335. }
  336. rc_stored = execute_insert(res);
  337. if (rc_stored != SQLITE_DONE)
  338. error_report("Failed to delete context %s, rc = %d", context_data->id, rc_stored);
  339. #ifdef NETDATA_INTERNAL_CHECKS
  340. else {
  341. char host_uuid_str[UUID_STR_LEN];
  342. uuid_unparse_lower(*host_uuid, host_uuid_str);
  343. info("%s: Deleted context %s under host %s", __FUNCTION__ , context_data->id, host_uuid_str);
  344. }
  345. #endif
  346. skip_delete:
  347. rc = sqlite3_finalize(res);
  348. if (rc != SQLITE_OK)
  349. error_report("Failed to finalize statement where deleting a context, rc = %d", rc);
  350. return (rc_stored != SQLITE_DONE);
  351. }
  352. //
  353. // TESTING FUNCTIONS
  354. //
  355. static void dict_ctx_get_label_list_cb(SQL_CLABEL_DATA *label_data_ptr, void *data)
  356. {
  357. (void)data;
  358. SQL_CLABEL_DATA *label_data = label_data_ptr;
  359. info(" LABEL %d %s = %s", label_data->label_source, label_data->label_key, label_data->label_value);
  360. }
  361. static void dict_ctx_get_dimension_list_cb(SQL_DIMENSION_DATA *dimension_data_ptr, void *data)
  362. {
  363. (void)data;
  364. SQL_DIMENSION_DATA *dimension_data = dimension_data_ptr;
  365. char uuid_str[UUID_STR_LEN];
  366. uuid_unparse_lower(dimension_data->dim_id, uuid_str);
  367. info(" Dimension %s = %s", uuid_str, dimension_data->id);
  368. }
  369. static void dict_ctx_get_chart_list_cb(SQL_CHART_DATA *chart_data, void *data)
  370. {
  371. (void)data;
  372. char uuid_str[UUID_STR_LEN];
  373. uuid_unparse_lower(chart_data->chart_id, uuid_str);
  374. info("OK GOT %s ID = %s NAME = %s CONTEXT = %s", uuid_str, chart_data->id, chart_data->name, chart_data->context);
  375. ctx_get_label_list(&chart_data->chart_id, dict_ctx_get_label_list_cb, NULL);
  376. ctx_get_dimension_list(&chart_data->chart_id, dict_ctx_get_dimension_list_cb, NULL);
  377. }
  378. static void dict_ctx_get_context_list_cb(VERSIONED_CONTEXT_DATA *context_data, void *data)
  379. {
  380. (void)data;
  381. info(" Context id = %s "
  382. "version = %lu "
  383. "title = %s "
  384. "chart_type = %s "
  385. "units = %s "
  386. "priority = %lu "
  387. "first time = %lu "
  388. "last time = %lu "
  389. "deleted = %d"
  390. "family = %s",
  391. context_data->id,
  392. context_data->version,
  393. context_data->title,
  394. context_data->chart_type,
  395. context_data->units,
  396. context_data->priority,
  397. context_data->first_time_t,
  398. context_data->last_time_t,
  399. context_data->deleted,
  400. context_data->family);
  401. }
  402. static int localhost_uuid_cb(void *data, int argc, char **argv, char **column)
  403. {
  404. uuid_t *uuid = data;
  405. UNUSED(argc);
  406. UNUSED(column);
  407. uuid_copy(*uuid, * (uuid_t *) argv[0]);
  408. return 0;
  409. }
  410. #define SQL_FIND_LOCALHOST "SELECT host_id FROM meta.host WHERE hops = 0;"
  411. int ctx_unittest(void)
  412. {
  413. uuid_t host_uuid;
  414. uuid_t host_uuid1;
  415. uuid_generate(host_uuid1);
  416. char *err_msg;
  417. sql_init_context_database(1);
  418. int rc = sqlite3_exec(db_context_meta, SQL_FIND_LOCALHOST, localhost_uuid_cb, (void *) &host_uuid, &err_msg);
  419. if (rc != SQLITE_OK) {
  420. info("Failed to discover localhost UUID rc = %d -- %s", rc, err_msg);
  421. sqlite3_free(err_msg);
  422. }
  423. ctx_get_chart_list(&host_uuid, dict_ctx_get_chart_list_cb, NULL);
  424. // Store a context
  425. VERSIONED_CONTEXT_DATA context_data;
  426. context_data.id = strdupz("cpu.cpu");
  427. context_data.title = strdupz("TestContextTitle");
  428. context_data.units= strdupz("TestContextUnits");
  429. context_data.chart_type = strdupz("TestContextChartType");
  430. context_data.family = strdupz("TestContextFamily");
  431. context_data.priority = 50000;
  432. context_data.deleted = 0;
  433. context_data.first_time_t = 1657781000;
  434. context_data.last_time_t = 1657781100;
  435. context_data.version = now_realtime_usec();
  436. if (likely(!ctx_store_context(&host_uuid, &context_data)))
  437. info("Entry %s inserted", context_data.id);
  438. else
  439. info("Entry %s not inserted", context_data.id);
  440. if (likely(!ctx_store_context(&host_uuid1, &context_data)))
  441. info("Entry %s inserted", context_data.id);
  442. else
  443. info("Entry %s not inserted", context_data.id);
  444. // This will change end time
  445. context_data.first_time_t = 1657781000;
  446. context_data.last_time_t = 1657782001;
  447. if (likely(!ctx_update_context(&host_uuid, &context_data)))
  448. info("Entry %s updated", context_data.id);
  449. else
  450. info("Entry %s not updated", context_data.id);
  451. info("List context start after insert");
  452. ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
  453. info("List context end after insert");
  454. // This will change start time
  455. context_data.first_time_t = 1657782000;
  456. context_data.last_time_t = 1657782001;
  457. if (likely(!ctx_update_context(&host_uuid, &context_data)))
  458. info("Entry %s updated", context_data.id);
  459. else
  460. info("Entry %s not updated", context_data.id);
  461. // This will list one entry
  462. info("List context start after insert");
  463. ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
  464. info("List context end after insert");
  465. info("List context start after insert");
  466. ctx_get_context_list(&host_uuid1, dict_ctx_get_context_list_cb, NULL);
  467. info("List context end after insert");
  468. // This will delete the entry
  469. if (likely(!ctx_delete_context(&host_uuid, &context_data)))
  470. info("Entry %s deleted", context_data.id);
  471. else
  472. info("Entry %s not deleted", context_data.id);
  473. freez((void *)context_data.id);
  474. freez((void *)context_data.title);
  475. freez((void *)context_data.chart_type);
  476. freez((void *)context_data.family);
  477. // The list should be empty
  478. info("List context start after delete");
  479. ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
  480. info("List context end after delete");
  481. sql_close_context_database();
  482. return 0;
  483. }