1 /*
2 * SysDB - src/include/core/memstore.h
3 * Copyright (C) 2012-2015 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #ifndef SDB_CORE_MEMSTORE_H
29 #define SDB_CORE_MEMSTORE_H 1
31 #include "sysdb.h"
32 #include "core/object.h"
33 #include "core/data.h"
34 #include "core/store.h"
35 #include "core/time.h"
36 #include "parser/ast.h"
37 #include "utils/strbuf.h"
39 #include <stdbool.h>
40 #include <stdio.h>
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
46 /*
47 * sdb_memstore_t represents an in-memory store. It inherits from sdb_object_t
48 * and may safely be case to a generic object.
49 */
50 struct sdb_memstore;
51 typedef struct sdb_memstore sdb_memstore_t;
52 #define SDB_MEMSTORE(obj) ((sdb_memstore_t *)(obj))
54 /*
55 * sdb_memstore_obj_t represents the super-class of any stored object. It
56 * inherits from sdb_object_t and may safely be cast to a generic object to
57 * access its name.
58 */
59 struct sdb_memstore_obj;
60 typedef struct sdb_memstore_obj sdb_memstore_obj_t;
62 /*
63 * Expressions represent arithmetic expressions based on stored objects and
64 * their various attributes.
65 *
66 * An expression object inherits from sdb_object_t and, thus, may safely be
67 * cast to a generic object.
68 */
69 struct sdb_memstore_expr;
70 typedef struct sdb_memstore_expr sdb_memstore_expr_t;
71 #define SDB_MEMSTORE_EXPR(obj) ((sdb_memstore_expr_t *)(obj))
73 /*
74 * An expression iterator iterates over the values of an iterable expression.
75 */
76 struct sdb_memstore_expr_iter;
77 typedef struct sdb_memstore_expr_iter sdb_memstore_expr_iter_t;
79 /*
80 * Store matchers may be used to lookup hosts from the store based on their
81 * various attributes. Service and attribute matchers are applied to a host's
82 * services and attributes and evaluate to true if *any* service or attribute
83 * matches.
84 *
85 * A store matcher object inherits from sdb_object_t and, thus, may safely be
86 * cast to a generic object.
87 */
88 struct sdb_memstore_matcher;
89 typedef struct sdb_memstore_matcher sdb_memstore_matcher_t;
90 #define SDB_MEMSTORE_MATCHER(obj) ((sdb_memstore_matcher_t *)(obj))
92 /*
93 * sdb_memstore_writer:
94 * A store writer implementation that provides an in-memory object store. It
95 * expects a store object as its user-data argument.
96 */
97 extern sdb_store_writer_t sdb_memstore_writer;
99 /*
100 * sdb_memstore_reader:
101 * A store reader implementation that uses an in-memory object store. It
102 * expects a store object as its user-data argument.
103 */
104 extern sdb_store_reader_t sdb_memstore_reader;
106 /*
107 * sdb_memstore_create:
108 * Allocate a new in-memory store.
109 */
110 sdb_memstore_t *
111 sdb_memstore_create(void);
113 /*
114 * sdb_memstore_host, sdb_memstore_service, sdb_memstore_metric,
115 * sdb_memstore_attribute, sdb_memstore_metric_attr:
116 * Store an object in the specified store. The hostname is expected to be
117 * canonical.
118 */
119 int
120 sdb_memstore_host(sdb_memstore_t *store, const char *name,
121 sdb_time_t last_update, sdb_time_t interval);
122 int
123 sdb_memstore_service(sdb_memstore_t *store, const char *hostname, const char *name,
124 sdb_time_t last_update, sdb_time_t interval);
125 int
126 sdb_memstore_metric(sdb_memstore_t *store, const char *hostname, const char *name,
127 sdb_metric_store_t *metric_store,
128 sdb_time_t last_update, sdb_time_t interval);
129 int
130 sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname,
131 const char *key, const sdb_data_t *value,
132 sdb_time_t last_update, sdb_time_t interval);
133 int
134 sdb_memstore_service_attr(sdb_memstore_t *store, const char *hostname,
135 const char *service, const char *key, const sdb_data_t *value,
136 sdb_time_t last_update, sdb_time_t interval);
137 int
138 sdb_memstore_metric_attr(sdb_memstore_t *store, const char *hostname,
139 const char *metric, const char *key, const sdb_data_t *value,
140 sdb_time_t last_update, sdb_time_t interval);
142 /*
143 * sdb_memstore_get_host:
144 * Query the specified store for a host by its (canonicalized) name.
145 *
146 * The function increments the ref count of the host object. The caller needs
147 * to deref it when no longer using it.
148 */
149 sdb_memstore_obj_t *
150 sdb_memstore_get_host(sdb_memstore_t *store, const char *name);
152 /*
153 * sdb_memstore_get_child:
154 * Retrieve an object's child object of the specified type and name. The
155 * reference count of the child object will be incremented before returning
156 * it. The caller is responsible for releasing the object once it's no longer
157 * used.
158 *
159 * Returns:
160 * - the child object on success
161 * - NULL else
162 */
163 sdb_memstore_obj_t *
164 sdb_memstore_get_child(sdb_memstore_obj_t *obj, int type, const char *name);
166 /*
167 * sdb_memstore_get_field:
168 * Get the value of a stored object's queryable field. The caller is
169 * responsible for freeing any dynamically allocated memory possibly stored in
170 * the returned value. If 'res' is NULL, the function will return whether the
171 * field exists.
172 *
173 * Returns:
174 * - 0 on success
175 * - a negative value else
176 */
177 int
178 sdb_memstore_get_field(sdb_memstore_obj_t *obj, int field, sdb_data_t *res);
180 /*
181 * sdb_memstore_get_attr:
182 * Get the value of a stored object's attribute. The caller is responsible for
183 * freeing any dynamically allocated memory possibly stored in the returned
184 * value. If 'res' is NULL, the function will return whether the attribute
185 * exists. If specified, only attributes matching the filter will be
186 * considered.
187 *
188 * Returns:
189 * - 0 if the attribute exists
190 * - a negative value else
191 */
192 int
193 sdb_memstore_get_attr(sdb_memstore_obj_t *obj, const char *name, sdb_data_t *res,
194 sdb_memstore_matcher_t *filter);
196 /*
197 * Querying a store:
198 *
199 * - Query interface: A query is a formal description of an interaction with
200 * the store. It can be used, both, for read and write access. The query is
201 * described by its abstract syntax tree (AST). The parser package provides
202 * means to parse a string (SysQL) representation of the query into an AST.
203 *
204 * - Matcher / expression interface: This low-level interface provides direct
205 * control over how to access the store. It is used by the query
206 * implementation internally and can only be used for read access.
207 */
209 /*
210 * sdb_memstore_query_t:
211 * A parsed query readily prepared for execution.
212 */
213 struct sdb_memstore_query;
214 typedef struct sdb_memstore_query sdb_memstore_query_t;
216 /*
217 * sdb_memstore_query_prepare:
218 * Prepare the query described by 'ast' for execution in a store.
219 *
220 * Returns:
221 * - a store query on success
222 * - NULL else
223 */
224 sdb_memstore_query_t *
225 sdb_memstore_query_prepare(sdb_ast_node_t *ast);
227 /*
228 * sdb_memstore_query_prepare_matcher:
229 * Prepare the logical expression described by 'ast' for execution as a store
230 * matcher.
231 *
232 * Returns:
233 * - a matcher on success
234 * - NULL else
235 */
236 sdb_memstore_matcher_t *
237 sdb_memstore_query_prepare_matcher(sdb_ast_node_t *ast);
239 /*
240 * sdb_memstore_query_execute:
241 * Execute a previously prepared query in the specified store. The query
242 * result will be written to 'buf' and any errors to 'errbuf'.
243 *
244 * Returns:
245 * - the result type (to be used by the server reply)
246 * - a negative value on error
247 */
248 int
249 sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *m,
250 sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf);
252 /*
253 * sdb_memstore_expr_create:
254 * Creates an arithmetic expression implementing the specified operator on the
255 * specified left and right operand.
256 *
257 * Returns:
258 * - an expression object on success
259 * - NULL else
260 */
261 sdb_memstore_expr_t *
262 sdb_memstore_expr_create(int op,
263 sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
265 /*
266 * sdb_memstore_expr_typed:
267 * Creates an expression which evaluates in the context of an object's sibling
268 * as specified by the given type.
269 *
270 * Returns:
271 * - an expression object on success
272 * - NULL else
273 */
274 sdb_memstore_expr_t *
275 sdb_memstore_expr_typed(int typ, sdb_memstore_expr_t *expr);
277 /*
278 * sdb_memstore_expr_fieldvalue:
279 * Creates an expression which evaluates to the value of the specified
280 * queryable field of a stored object.
281 *
282 * Returns:
283 * - an expression object on success
284 * - NULL else
285 */
286 sdb_memstore_expr_t *
287 sdb_memstore_expr_fieldvalue(int field);
289 /*
290 * sdb_memstore_expr_attrvalue:
291 * Creates an expression which evaluates to the value of the specified
292 * attribute of a stored object. Evaluates to a NULL value if the attribute
293 * does not exist.
294 *
295 * Returns:
296 * - an expression object on success
297 * - NULL else
298 */
299 sdb_memstore_expr_t *
300 sdb_memstore_expr_attrvalue(const char *name);
302 /*
303 * sdb_memstore_expr_constvalue:
304 * Creates an expression which evaluates to the specified constant value.
305 *
306 * Returns:
307 * - an expression object on success
308 * - NULL else
309 */
310 sdb_memstore_expr_t *
311 sdb_memstore_expr_constvalue(const sdb_data_t *value);
313 /*
314 * sdb_memstore_expr_eval:
315 * Evaluate an expression for the specified stored object and stores the
316 * result in 'res'. The result's value will be allocated dynamically if
317 * necessary and, thus, should be free'd by the caller (e.g. using
318 * sdb_data_free_datum). The object may be NULL, in which case the expression
319 * needs to evaluate to a constant value. If specified, only objects matching
320 * the filter will be used during the evaluation.
321 *
322 * Returns:
323 * - 0 on success
324 * - a negative value else
325 */
326 int
327 sdb_memstore_expr_eval(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj,
328 sdb_data_t *res, sdb_memstore_matcher_t *filter);
330 /*
331 * sdb_memstore_expr_iter:
332 * Iterate over the elements of an iterable expression. sdb_memstore_expr_iter
333 * returns NULL if the expression is not iterable (for the specified object).
334 *
335 * sdb_memstore_expr_iter_get_next returns NULL if there is no next element.
336 */
337 sdb_memstore_expr_iter_t *
338 sdb_memstore_expr_iter(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj,
339 sdb_memstore_matcher_t *filter);
340 void
341 sdb_memstore_expr_iter_destroy(sdb_memstore_expr_iter_t *iter);
343 bool
344 sdb_memstore_expr_iter_has_next(sdb_memstore_expr_iter_t *iter);
345 sdb_data_t
346 sdb_memstore_expr_iter_get_next(sdb_memstore_expr_iter_t *iter);
348 /*
349 * sdb_memstore_dis_matcher:
350 * Creates a matcher matching the disjunction (logical OR) of two matchers.
351 */
352 sdb_memstore_matcher_t *
353 sdb_memstore_dis_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right);
355 /*
356 * sdb_memstore_con_matcher:
357 * Creates a matcher matching the conjunction (logical AND) of two matchers.
358 */
359 sdb_memstore_matcher_t *
360 sdb_memstore_con_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right);
362 /*
363 * sdb_memstore_inv_matcher:
364 * Creates a matcher matching the inverse (logical NOT) of a matcher.
365 */
366 sdb_memstore_matcher_t *
367 sdb_memstore_inv_matcher(sdb_memstore_matcher_t *m);
369 /*
370 * sdb_memstore_any_matcher:
371 * Creates a matcher iterating over values of the first expression (which has
372 * to be iterable). It matches if *any* of those elements match 'm'. 'm' has
373 * to be an ary operation with the left operand unset.
374 */
375 sdb_memstore_matcher_t *
376 sdb_memstore_any_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m);
378 /*
379 * sdb_memstore_all_matcher:
380 * Creates a matcher iterating over values of the first expression (which has
381 * to be iterable). It matches if *all* of those elements match 'm'. 'm' has
382 * to be an ary operation with the left operand unset.
383 */
384 sdb_memstore_matcher_t *
385 sdb_memstore_all_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m);
387 /*
388 * sdb_memstore_in_matcher:
389 * Creates a matcher which matches if the right value evaluates to an array
390 * value and the left value is included in that array. See sdb_data_inarray
391 * for more details.
392 */
393 sdb_memstore_matcher_t *
394 sdb_memstore_in_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
396 /*
397 * sdb_memstore_lt_matcher, sdb_memstore_le_matcher, sdb_memstore_eq_matcher,
398 * sdb_memstore_ge_matcher, sdb_memstore_gt_matcher:
399 * Create conditional matchers comparing the values of two expressions. The
400 * matcher matches if the left expression compres less than, less or equal
401 * than, equal to, not equal to, greater or equal than, or greater than the
402 * right expression.
403 */
404 sdb_memstore_matcher_t *
405 sdb_memstore_lt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
406 sdb_memstore_matcher_t *
407 sdb_memstore_le_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
408 sdb_memstore_matcher_t *
409 sdb_memstore_eq_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
410 sdb_memstore_matcher_t *
411 sdb_memstore_ne_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
412 sdb_memstore_matcher_t *
413 sdb_memstore_ge_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
414 sdb_memstore_matcher_t *
415 sdb_memstore_gt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
417 /*
418 * sdb_memstore_regex_matcher:
419 * Creates a matcher which matches the string value the left expression
420 * evaluates to against the regular expression the right expression evaluates
421 * to. The right expression may either be a constant value regular expression
422 * or string or a dynamic value evaluating to a string. In the latter case,
423 * the string is compiled to a regex every time the matcher is executed.
424 */
425 sdb_memstore_matcher_t *
426 sdb_memstore_regex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
428 /*
429 * sdb_memstore_nregex_matcher:
430 * Creates a regex matcher just like sdb_memstore_regex_matcher except that it
431 * matches in case the regular expression does not match.
432 */
433 sdb_memstore_matcher_t *
434 sdb_memstore_nregex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right);
436 /*
437 * sdb_memstore_isnull_matcher:
438 * Creates a matcher matching NULL values.
439 */
440 sdb_memstore_matcher_t *
441 sdb_memstore_isnull_matcher(sdb_memstore_expr_t *expr);
443 /*
444 * sdb_memstore_istrue_matcher, sdb_memstore_isfalse_matcher:
445 * Creates a matcher matching boolean values.
446 */
447 sdb_memstore_matcher_t *
448 sdb_memstore_istrue_matcher(sdb_memstore_expr_t *expr);
449 sdb_memstore_matcher_t *
450 sdb_memstore_isfalse_matcher(sdb_memstore_expr_t *expr);
452 /*
453 * sdb_memstore_matcher_matches:
454 * Check whether the specified matcher matches the specified store object. If
455 * specified, the filter will be used to preselect objects for further
456 * evaluation. It is applied to any object that's used during the evaluation
457 * of the matcher. Only those objects matching the filter will be considered.
458 *
459 * Note that the filter is applied to all object types (hosts, service,
460 * metric, attribute). Thus, any object-specific matchers are mostly unsuited
461 * for this purpose and, if used, may result in unexpected behavior.
462 *
463 * Returns:
464 * - 1 if the object matches
465 * - 0 else
466 */
467 int
468 sdb_memstore_matcher_matches(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj,
469 sdb_memstore_matcher_t *filter);
471 /*
472 * sdb_memstore_matcher_op_cb:
473 * Callback constructing a matcher operator.
474 */
475 typedef sdb_memstore_matcher_t *(*sdb_memstore_matcher_op_cb)
476 (sdb_memstore_expr_t *, sdb_memstore_expr_t *);
478 /*
479 * sdb_memstore_lookup_cb:
480 * Lookup callback. It is called for each matching object when looking up data
481 * in the store passing on the lookup filter and the specified user-data. The
482 * lookup aborts early if the callback returns non-zero.
483 */
484 typedef int (*sdb_memstore_lookup_cb)(sdb_memstore_obj_t *obj,
485 sdb_memstore_matcher_t *filter, void *user_data);
487 /*
488 * sdb_memstore_scan:
489 * Look up objects of the specified type in the specified store. The specified
490 * callback function is called for each object in the store matching 'm'. The
491 * function performs a full scan of all stored objects. If specified, the
492 * filter will be used to preselect objects for further evaluation. See the
493 * description of 'sdb_memstore_matcher_matches' for details.
494 *
495 * Returns:
496 * - 0 on success
497 * - a negative value else
498 */
499 int
500 sdb_memstore_scan(sdb_memstore_t *store, int type,
501 sdb_memstore_matcher_t *m, sdb_memstore_matcher_t *filter,
502 sdb_memstore_lookup_cb cb, void *user_data);
504 /*
505 * sdb_memstore_emit:
506 * Send a single object to the specified store writer. Attributes or any child
507 * objects are not included. Use sdb_memstore_emit_full() to emit a full
508 * (filtered) object.
509 *
510 * Returns:
511 * - 0 on success
512 * - a negative value else
513 */
514 int
515 sdb_memstore_emit(sdb_memstore_obj_t *obj, sdb_store_writer_t *w, sdb_object_t *wd);
517 /*
518 * sdb_memstore_emit_full:
519 * Send a single object and its attributes and all children to the specified
520 * store writer. The filter, if specified, is applied to each attribute and
521 * child object. Only matching objects will be emitted.
522 *
523 * Returns:
524 * - 0 on success
525 * - a negative value else
526 */
527 int
528 sdb_memstore_emit_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter,
529 sdb_store_writer_t *w, sdb_object_t *wd);
531 #ifdef __cplusplus
532 } /* extern "C" */
533 #endif
535 #endif /* ! SDB_CORE_MEMSTORE_H */
537 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */