You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rrd.h 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright 2024 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef RRD_H_
  17. #define RRD_H_
  18. #include "config.h"
  19. /**
  20. * This file contains basic structure and functions to operate with round-robin databases
  21. */
  22. #define RRD_COOKIE "RRD"
  23. #define RRD_VERSION "0003"
  24. #define RRD_FLOAT_COOKIE ((double) 8.642135E130)
  25. #ifdef __cplusplus
  26. extern "C" {
  27. #endif
  28. typedef union {
  29. unsigned long lv;
  30. double dv;
  31. } rrd_value_t;
  32. struct rrd_file_head {
  33. /* Data Base Identification Section ** */
  34. char cookie[4]; /* RRD */
  35. char version[5]; /* version of the format */
  36. double float_cookie; /* is it the correct double representation ? */
  37. /* Data Base Structure Definition **** */
  38. gulong ds_cnt; /* how many different ds provide input to the rrd */
  39. gulong rra_cnt; /* how many rras will be maintained in the rrd */
  40. gulong pdp_step; /* pdp interval in seconds */
  41. rrd_value_t par[10]; /* global parameters ... unused
  42. at the moment */
  43. };
  44. enum rrd_dst_type {
  45. RRD_DST_INVALID = -1,
  46. RRD_DST_COUNTER = 0, /* data source types available */
  47. RRD_DST_ABSOLUTE,
  48. RRD_DST_GAUGE,
  49. RRD_DST_DERIVE,
  50. RRD_DST_CDEF
  51. };
  52. enum rrd_ds_param {
  53. RRD_DS_mrhb_cnt = 0, /* minimum required heartbeat */
  54. RRD_DS_min_val, /* the processed input of a ds must */
  55. RRD_DS_max_val, /* be between max_val and min_val
  56. * both can be set to UNKNOWN if you
  57. * do not care. Data outside the limits
  58. * set to UNKNOWN */
  59. RRD_DS_cdef = RRD_DS_mrhb_cnt
  60. }; /* pointer to encoded rpn expression only applies to DST_CDEF */
  61. /* The magic number here is one less than DS_NAM_SIZE */
  62. #define RRD_DS_NAM_SIZE 20
  63. #define RRD_DST_SIZE 20
  64. struct rrd_ds_def {
  65. char ds_nam[RRD_DS_NAM_SIZE]; /* Name of the data source (null terminated) */
  66. char dst[RRD_DST_SIZE]; /* Type of data source (null terminated) */
  67. rrd_value_t par[10]; /* index of this array see ds_param_en */
  68. };
  69. /* RRA definition */
  70. enum rrd_cf_type {
  71. RRD_CF_INVALID = -1,
  72. RRD_CF_AVERAGE = 0, /* data consolidation functions */
  73. RRD_CF_MINIMUM,
  74. RRD_CF_MAXIMUM,
  75. RRD_CF_LAST,
  76. };
  77. #define MAX_RRA_PAR_EN 10
  78. enum rrd_rra_param {
  79. RRA_cdp_xff_val = 0, /* what part of the consolidated
  80. * datapoint must be known, to produce a
  81. * valid entry in the rra */
  82. };
  83. #define RRD_CF_NAM_SIZE 20
  84. struct rrd_rra_def {
  85. char cf_nam[RRD_CF_NAM_SIZE]; /* consolidation function (null term) */
  86. gulong row_cnt; /* number of entries in the store */
  87. gulong pdp_cnt; /* how many primary data points are
  88. * required for a consolidated data point?*/
  89. rrd_value_t par[MAX_RRA_PAR_EN]; /* index see rra_param_en */
  90. };
  91. struct rrd_live_head {
  92. time_t last_up; /* when was rrd last updated */
  93. glong last_up_usec; /* micro seconds part of the update timestamp. Always >= 0 */
  94. };
  95. #define RRD_LAST_DS_LEN 30
  96. enum rrd_pdp_param {
  97. PDP_unkn_sec_cnt = 0, /* how many seconds of the current
  98. * pdp value is unknown data? */
  99. PDP_val
  100. }; /* current value of the pdp.
  101. this depends on dst */
  102. struct rrd_pdp_prep {
  103. char last_ds[RRD_LAST_DS_LEN]; /* the last reading from the data
  104. * source. this is stored in ASCII
  105. * to cater for very large counters
  106. * we might encounter in connection
  107. * with SNMP. */
  108. rrd_value_t scratch[10]; /* contents according to pdp_par_en */
  109. };
  110. #define RRD_MAX_CDP_PAR_EN 10
  111. #define RRD_MAX_CDP_FAILURES_IDX 8
  112. /* max CDP scratch entries avail to record violations for a FAILURES RRA */
  113. #define RRD_MAX_FAILURES_WINDOW_LEN 28
  114. enum rrd_cdp_param {
  115. CDP_val = 0,
  116. /* the base_interval is always an
  117. * average */
  118. CDP_unkn_pdp_cnt,
  119. /* how many unknown pdp were
  120. * integrated. This and the cdp_xff
  121. * will decide if this is going to
  122. * be a UNKNOWN or a valid value */
  123. CDP_hw_intercept,
  124. /* Current intercept coefficient for the Holt-Winters
  125. * prediction algorithm. */
  126. CDP_hw_last_intercept,
  127. /* Last iteration intercept coefficient for the Holt-Winters
  128. * prediction algorithm. */
  129. CDP_hw_slope,
  130. /* Current slope coefficient for the Holt-Winters
  131. * prediction algorithm. */
  132. CDP_hw_last_slope,
  133. /* Last iteration slope coefficient. */
  134. CDP_null_count,
  135. /* Number of sequential Unknown (DNAN) values + 1 preceding
  136. * the current prediction.
  137. * */
  138. CDP_last_null_count,
  139. /* Last iteration count of Unknown (DNAN) values. */
  140. CDP_primary_val = 8,
  141. /* optimization for bulk updates: the value of the first CDP
  142. * value to be written in the bulk update. */
  143. CDP_secondary_val = 9,
  144. /* optimization for bulk updates: the value of subsequent
  145. * CDP values to be written in the bulk update. */
  146. CDP_hw_seasonal = CDP_hw_intercept,
  147. /* Current seasonal coefficient for the Holt-Winters
  148. * prediction algorithm. This is stored in CDP prep to avoid
  149. * redundant seek operations. */
  150. CDP_hw_last_seasonal = CDP_hw_last_intercept,
  151. /* Last iteration seasonal coefficient. */
  152. CDP_seasonal_deviation = CDP_hw_intercept,
  153. CDP_last_seasonal_deviation = CDP_hw_last_intercept,
  154. CDP_init_seasonal = CDP_null_count
  155. };
  156. struct rrd_cdp_prep {
  157. rrd_value_t scratch[RRD_MAX_CDP_PAR_EN];
  158. /* contents according to cdp_par_en *
  159. * init state should be NAN */
  160. };
  161. struct rrd_rra_ptr {
  162. gulong cur_row; /* current row in the rra */
  163. };
  164. /* Final rrd file structure */
  165. struct rspamd_rrd_file {
  166. struct rrd_file_head *stat_head; /* the static header */
  167. struct rrd_ds_def *ds_def; /* list of data source definitions */
  168. struct rrd_rra_def *rra_def; /* list of round robin archive def */
  169. struct rrd_live_head *live_head; /* rrd v >= 3 last_up with us */
  170. struct rrd_pdp_prep *pdp_prep; /* pdp data prep area */
  171. struct rrd_cdp_prep *cdp_prep; /* cdp prep area */
  172. struct rrd_rra_ptr *rra_ptr; /* list of rra pointers */
  173. double *rrd_value; /* list of rrd values */
  174. char *filename;
  175. uint8_t *map; /* mmapped area */
  176. gsize size; /* its size */
  177. gboolean finalized;
  178. char *id;
  179. int fd;
  180. };
  181. /* Public API */
  182. /**
  183. * Open (and mmap) existing RRD file
  184. * @param filename path
  185. * @param err error pointer
  186. * @return rrd file structure
  187. */
  188. struct rspamd_rrd_file *rspamd_rrd_open(const char *filename, GError **err);
  189. /**
  190. * Create basic header for rrd file
  191. * @param filename file path
  192. * @param ds_count number of data sources
  193. * @param rra_count number of round robin archives
  194. * @param pdp_step step of primary data points
  195. * @param err error pointer
  196. * @return TRUE if file has been created
  197. */
  198. struct rspamd_rrd_file *rspamd_rrd_create(const char *filename,
  199. gulong ds_count,
  200. gulong rra_count,
  201. gulong pdp_step,
  202. double initial_ticks,
  203. GError **err);
  204. /**
  205. * Add data sources to rrd file
  206. * @param filename path to file
  207. * @param ds array of struct rrd_ds_def
  208. * @param err error pointer
  209. * @return TRUE if data sources were added
  210. */
  211. gboolean rspamd_rrd_add_ds(struct rspamd_rrd_file *file,
  212. GArray *ds,
  213. GError **err);
  214. /**
  215. * Add round robin archives to rrd file
  216. * @param filename path to file
  217. * @param ds array of struct rrd_rra_def
  218. * @param err error pointer
  219. * @return TRUE if archives were added
  220. */
  221. gboolean rspamd_rrd_add_rra(struct rspamd_rrd_file *file,
  222. GArray *rra,
  223. GError **err);
  224. /**
  225. * Finalize rrd file header and initialize all RRA in the file
  226. * @param filename file path
  227. * @param err error pointer
  228. * @return TRUE if rrd file is ready for use
  229. */
  230. gboolean rspamd_rrd_finalize(struct rspamd_rrd_file *file, GError **err);
  231. /**
  232. * Add record to rrd file
  233. * @param file rrd file object
  234. * @param points points (must be row suitable for this RRA, depending on ds count)
  235. * @param err error pointer
  236. * @return TRUE if a row has been added
  237. */
  238. gboolean rspamd_rrd_add_record(struct rspamd_rrd_file *file,
  239. GArray *points,
  240. double ticks,
  241. GError **err);
  242. /**
  243. * Close rrd file
  244. * @param file
  245. * @return
  246. */
  247. int rspamd_rrd_close(struct rspamd_rrd_file *file);
  248. /*
  249. * Conversion functions
  250. */
  251. /**
  252. * Convert rrd dst type from string to numeric value
  253. */
  254. enum rrd_dst_type rrd_dst_from_string(const char *str);
  255. /**
  256. * Convert numeric presentation of dst to string
  257. */
  258. const char *rrd_dst_to_string(enum rrd_dst_type type);
  259. /**
  260. * Convert rrd consolidation function type from string to numeric value
  261. */
  262. enum rrd_cf_type rrd_cf_from_string(const char *str);
  263. /**
  264. * Convert numeric presentation of cf to string
  265. */
  266. const char *rrd_cf_to_string(enum rrd_cf_type type);
  267. /* Default RRA and DS */
  268. /**
  269. * Create default RRA
  270. */
  271. void rrd_make_default_rra(const char *cf_name,
  272. gulong pdp_cnt,
  273. gulong rows,
  274. struct rrd_rra_def *rra);
  275. /**
  276. * Create default DS
  277. */
  278. void rrd_make_default_ds(const char *name,
  279. const char *type,
  280. gulong pdp_step,
  281. struct rrd_ds_def *ds);
  282. /**
  283. * Open or create the default rspamd rrd file
  284. */
  285. struct rspamd_rrd_file *rspamd_rrd_file_default(const char *path,
  286. GError **err);
  287. /**
  288. * Returned by querying rrd database
  289. */
  290. struct rspamd_rrd_query_result {
  291. gulong rra_rows;
  292. gulong pdp_per_cdp;
  293. gulong ds_count;
  294. double last_update;
  295. gulong cur_row;
  296. const double *data;
  297. };
  298. /**
  299. * Return RRA data
  300. * @param file rrd file
  301. * @param rra_num number of rra to return data for
  302. * @return query result structure, that should be freed (using g_slice_free1) after usage
  303. */
  304. struct rspamd_rrd_query_result *rspamd_rrd_query(struct rspamd_rrd_file *file,
  305. gulong rra_num);
  306. #ifdef __cplusplus
  307. }
  308. #endif
  309. #endif /* RRD_H_ */