aboutsummaryrefslogtreecommitdiffstats
path: root/src/rrd.h
blob: ff690289410bf84d69b6e3a73897594d1daa786c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
/* Copyright (c) 2010-2012, Vsevolod Stakhov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *       * Redistributions of source code must retain the above copyright
 *         notice, this list of conditions and the following disclaimer.
 *       * Redistributions in binary form must reproduce the above copyright
 *         notice, this list of conditions and the following disclaimer in the
 *         documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#ifndef RRD_H_
#define RRD_H_

#include "config.h"

/**
 * This file contains basic structure and functions to operate with round-robin databases
 */

#define RRD_COOKIE    "RRD"
#define RRD_VERSION   "0003"
#define RRD_FLOAT_COOKIE  ((double)8.642135E130)

typedef union {
	unsigned long lv;
	double dv;
} rrd_value_t;

struct rrd_file_head {
	/* Data Base Identification Section ** */
	gchar      cookie[4];    /* RRD */
	gchar      version[5];   /* version of the format */
	gdouble    float_cookie; /* is it the correct double representation ?  */

	/* Data Base Structure Definition **** */
	gulong ds_cnt;   /* how many different ds provid input to the rrd */
	gulong rra_cnt;  /* how many rras will be maintained in the rrd */
	gulong pdp_step; /* pdp interval in seconds */

	rrd_value_t   par[10];  /* global parameters ... unused
                           at the moment */
};

enum rrd_dst_type {
	RRD_DST_COUNTER = 0,  /* data source types available */
	RRD_DST_ABSOLUTE,
	RRD_DST_GAUGE,
	RRD_DST_DERIVE,
	RRD_DST_CDEF
};
enum rrd_ds_param {
	RRD_DS_mrhb_cnt = 0, /* minimum required heartbeat */
	RRD_DS_min_val,         /* the processed input of a ds must */
	RRD_DS_max_val,         /* be between max_val and min_val
	 	 	 	 	 	 * both can be set to UNKNOWN if you
	 	 	 	 	 	 * do not care. Data outside the limits
	 	 	 	 	 	 * set to UNKNOWN */
	RRD_DS_cdef = RRD_DS_mrhb_cnt
};                      /* pointer to encoded rpn expression only applies to DST_CDEF */


/* The magic number here is one less than DS_NAM_SIZE */
#define RRD_DS_NAM_SIZE   20

#define RRD_DST_SIZE   20

struct rrd_ds_def {
	gchar ds_nam[RRD_DS_NAM_SIZE];  /* Name of the data source (null terminated) */
	gchar dst[RRD_DST_SIZE];    /* Type of data source (null terminated) */
	rrd_value_t par[10];  /* index of this array see ds_param_en */
};

/* RRA definition */

enum rrd_cf_type {
	RRD_CF_AVERAGE = 0,    /* data consolidation functions */
	RRD_CF_MINIMUM,
	RRD_CF_MAXIMUM,
	RRD_CF_LAST,
	RRD_CF_HWPREDICT,
	/* An array of predictions using the seasonal
	 * Holt-Winters algorithm. Requires an RRA of type
	 * CF_SEASONAL for this data source. */
	RRD_CF_SEASONAL,
	/* An array of seasonal effects. Requires an RRA of
	 * type CF_HWPREDICT for this data source. */
	RRD_CF_DEVPREDICT,
	/* An array of deviation predictions based upon
	 * smoothed seasonal deviations. Requires an RRA of
	 * type CF_DEVSEASONAL for this data source. */
	RRD_CF_DEVSEASONAL,
	/* An array of smoothed seasonal deviations. Requires
	 * an RRA of type CF_HWPREDICT for this data source.
	 * */
	RRD_CF_FAILURES,
	/* HWPREDICT that follows a moving baseline */
	RRD_CF_MHWPREDICT
	/* new entries must come last !!! */
};


#define MAX_RRA_PAR_EN 10

enum rrd_rra_param {
	RRA_cdp_xff_val = 0,  /* what part of the consolidated
 * datapoint must be known, to produce a
 * valid entry in the rra */
	/* CF_HWPREDICT: */
	RRA_hw_alpha = 1,
	/* exponential smoothing parameter for the intercept in
	 * the Holt-Winters prediction algorithm. */
	RRA_hw_beta = 2,
	/* exponential smoothing parameter for the slope in
	 * the Holt-Winters prediction algorithm. */

	RRA_dependent_rra_idx = 3,
	/* For CF_HWPREDICT: index of the RRA with the seasonal
	 * effects of the Holt-Winters algorithm (of type
	 * CF_SEASONAL).
	 * For CF_DEVPREDICT: index of the RRA with the seasonal
	 * deviation predictions (of type CF_DEVSEASONAL).
	 * For CF_SEASONAL: index of the RRA with the Holt-Winters
	 * intercept and slope coefficient (of type CF_HWPREDICT).
	 * For CF_DEVSEASONAL: index of the RRA with the
	 * Holt-Winters prediction (of type CF_HWPREDICT).
	 * For CF_FAILURES: index of the CF_DEVSEASONAL array.
	 * */

	/* CF_SEASONAL and CF_DEVSEASONAL: */
	RRA_seasonal_gamma = 1,
	/* exponential smoothing parameter for seasonal effects. */

	RRA_seasonal_smoothing_window = 2,
	/* fraction of the season to include in the running average
	 * smoother */

	/* RRA_dependent_rra_idx = 3, */

	RRA_seasonal_smooth_idx = 4,
	/* an integer between 0 and row_count - 1 which
	 * is index in the seasonal cycle for applying
	 * the period smoother. */

	/* CF_FAILURES: */
	RRA_delta_pos = 1,  /* confidence bound scaling parameters */
	RRA_delta_neg = 2,
	/* RRA_dependent_rra_idx = 3, */
	RRA_window_len = 4,
	RRA_failure_threshold = 5
	/* For CF_FAILURES, number of violations within the last
	 * window required to mark a failure. */
};


#define RRD_CF_NAM_SIZE   20

struct rrd_rra_def {
	gchar  cf_nam[RRD_CF_NAM_SIZE];  /* consolidation function (null term) */
	gulong row_cnt;  /* number of entries in the store */
	gulong pdp_cnt;  /* how many primary data points are
	 	 	 	 	  * required for a consolidated data point?*/
	rrd_value_t par[MAX_RRA_PAR_EN];  /* index see rra_param_en */

};

struct rrd_live_head {
	time_t last_up;  /* when was rrd last updated */
	glong last_up_usec; /* micro seconds part of the update timestamp. Always >= 0 */
};

#define RRD_LAST_DS_LEN 30

enum rrd_pdp_param {
	PDP_unkn_sec_cnt = 0, /* how many seconds of the current
	 * pdp value is unknown data? */
	PDP_val
};                      /* current value of the pdp.
                           this depends on dst */

struct rrd_pdp_prep {
	gchar last_ds[RRD_LAST_DS_LEN]; /* the last reading from the data
	 	 	 	 	 	 	 	 	 * source.  this is stored in ASCII
	 	 	 	 	 	 	 	 	 * to cater for very large counters
	 	 	 	 	 	 	 	 	 * we might encounter in connection
	 	 	 	 	 	 	 	 	 * with SNMP. */
	rrd_value_t scratch[10];  /* contents according to pdp_par_en */
};

#define RRD_MAX_CDP_PAR_EN 10
#define RRD_MAX_CDP_FAILURES_IDX 8
/* max CDP scratch entries avail to record violations for a FAILURES RRA */
#define RRD_MAX_FAILURES_WINDOW_LEN 28

enum rrd_cdp_param {
	CDP_val = 0,
	/* the base_interval is always an
	 * average */
	CDP_unkn_pdp_cnt,
	/* how many unknown pdp were
	 * integrated. This and the cdp_xff
	 * will decide if this is going to
	 * be a UNKNOWN or a valid value */
	CDP_hw_intercept,
	/* Current intercept coefficient for the Holt-Winters
	 * prediction algorithm. */
	CDP_hw_last_intercept,
	/* Last iteration intercept coefficient for the Holt-Winters
	 * prediction algorihtm. */
	CDP_hw_slope,
	/* Current slope coefficient for the Holt-Winters
	 * prediction algorithm. */
	CDP_hw_last_slope,
	/* Last iteration slope coeffient. */
	CDP_null_count,
	/* Number of sequential Unknown (DNAN) values + 1 preceding
	 * the current prediction.
	 * */
	CDP_last_null_count,
	/* Last iteration count of Unknown (DNAN) values. */
	CDP_primary_val = 8,
	/* optimization for bulk updates: the value of the first CDP
	 * value to be written in the bulk update. */
	CDP_secondary_val = 9,
	/* optimization for bulk updates: the value of subsequent
	 * CDP values to be written in the bulk update. */
	CDP_hw_seasonal = CDP_hw_intercept,
	/* Current seasonal coefficient for the Holt-Winters
	 * prediction algorithm. This is stored in CDP prep to avoid
	 * redundant seek operations. */
	CDP_hw_last_seasonal = CDP_hw_last_intercept,
	/* Last iteration seasonal coefficient. */
	CDP_seasonal_deviation = CDP_hw_intercept,
	CDP_last_seasonal_deviation = CDP_hw_last_intercept,
	CDP_init_seasonal = CDP_null_count
};

struct rrd_cdp_prep {
    rrd_value_t scratch[RRD_MAX_CDP_PAR_EN];
    /* contents according to cdp_par_en *
     * init state should be NAN */
};

struct rrd_rra_ptr {
	gulong cur_row;  /* current row in the rra */
};

/* Final rrd file structure */
struct rspamd_rrd_file {
	struct rrd_file_head *stat_head; /* the static header */
	struct rrd_ds_def *ds_def;   /* list of data source definitions */
	struct rrd_rra_def *rra_def; /* list of round robin archive def */
	struct rrd_live_head *live_head; /* rrd v >= 3 last_up with us */
	struct rrd_pdp_prep *pdp_prep;   /* pdp data prep area */
	struct rrd_cdp_prep *cdp_prep;   /* cdp prep area */
	struct rrd_rra_ptr *rra_ptr; /* list of rra pointers */
	gdouble *rrd_value; /* list of rrd values */

	gchar *filename;
	guint8* map; /* mmapped area */
	gsize size; /* its size */
	gboolean finalized;
};


/* Public API */

/**
 * Open (and mmap) existing RRD file
 * @param filename path
 * @param err error pointer
 * @return rrd file structure
 */
struct rspamd_rrd_file* rspamd_rrd_open (const gchar *filename, GError **err);

/**
 * Create basic header for rrd file
 * @param filename file path
 * @param ds_count number of data sources
 * @param rra_count number of round robin archives
 * @param pdp_step step of primary data points
 * @param err error pointer
 * @return TRUE if file has been created
 */
struct rspamd_rrd_file* rspamd_rrd_create (const gchar *filename, gulong ds_count, gulong rra_count, gulong pdp_step, GError **err);

/**
 * Add data sources to rrd file
 * @param filename path to file
 * @param ds array of struct rrd_ds_def
 * @param err error pointer
 * @return TRUE if data sources were added
 */
gboolean rspamd_rrd_add_ds (struct rspamd_rrd_file* file, GArray *ds, GError **err);

/**
 * Add round robin archives to rrd file
 * @param filename path to file
 * @param ds array of struct rrd_rra_def
 * @param err error pointer
 * @return TRUE if archives were added
 */
gboolean rspamd_rrd_add_rra (struct rspamd_rrd_file *file, GArray *rra, GError **err);

/**
 * Finalize rrd file header and initialize all RRA in the file
 * @param filename file path
 * @param err error pointer
 * @return TRUE if rrd file is ready for use
 */
gboolean rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err);

/**
 * Add record to rrd file
 * @param file rrd file object
 * @param points points (must be row suitable for this RRA, depending on ds count)
 * @param err error pointer
 * @return TRUE if a row has been added
 */
gboolean rspamd_rrd_add_record (struct rspamd_rrd_file* file, GArray *points, GError **err);

/**
 * Close rrd file
 * @param file
 * @return
 */
gint rspamd_rrd_close (struct rspamd_rrd_file* file);

/*
 * Conversion functions
 */

/**
 * Convert rrd dst type from string to numeric value
 */
enum rrd_dst_type rrd_dst_from_string (const gchar *str);
/**
 * Convert numeric presentation of dst to string
 */
const gchar* rrd_dst_to_string (enum rrd_dst_type type);
/**
 * Convert rrd consolidation function type from string to numeric value
 */
enum rrd_cf_type rrd_cf_from_string (const gchar *str);
/**
 * Convert numeric presentation of cf to string
 */
const gchar* rrd_cf_to_string (enum rrd_cf_type type);

/* Default RRA and DS */

/**
 * Create default RRA
 */
void rrd_make_default_rra (const gchar *cf_name, gulong pdp_cnt, gulong rows, struct rrd_rra_def *rra);

/**
 * Create default DS
 */
void rrd_make_default_ds (const gchar *name, gulong pdp_step, struct rrd_ds_def *ds);
#endif /* RRD_H_ */