sdb_ast_node_t * sdb_ast_store_create(int obj_type, char *hostname, int parent_type, char *parent, char *name, sdb_time_t last_update, char *store_type, char *store_id, sdb_time_t store_last_update, sdb_data_t value) { sdb_ast_store_t *store; store = SDB_AST_STORE(sdb_object_create("STORE", st_type)); if (! store) return NULL; store->super.type = SDB_AST_TYPE_STORE; store->obj_type = obj_type; store->hostname = hostname; store->parent_type = parent_type; store->parent = parent; store->name = name; store->last_update = last_update; store->store_type = store_type; store->store_id = store_id; store->store_last_update = store_last_update; store->value = value; return SDB_AST_NODE(store); } /* sdb_ast_store_create */
sdb_llist_t * sdb_parser_parse(const char *query, int len, sdb_strbuf_t *errbuf) { sdb_parser_yyscan_t scanner; sdb_parser_yyextra_t yyextra; sdb_llist_iter_t *iter; int yyres; if (scanner_init(query, len, &scanner, &yyextra, errbuf)) return NULL; yyres = sdb_parser_yyparse(scanner); sdb_parser_scanner_destroy(scanner); if (yyres) { sdb_llist_destroy(yyextra.parsetree); return NULL; } iter = sdb_llist_get_iter(yyextra.parsetree); while (sdb_llist_iter_has_next(iter)) { sdb_ast_node_t *node; node = SDB_AST_NODE(sdb_llist_iter_get_next(iter)); if (sdb_parser_analyze(node, errbuf) < 0) { sdb_llist_iter_destroy(iter); sdb_llist_destroy(yyextra.parsetree); return NULL; } } sdb_llist_iter_destroy(iter); return yyextra.parsetree; } /* sdb_parser_parse */
static int analyze_arith(int context, sdb_ast_op_t *op, sdb_strbuf_t *errbuf) { if (analyze_node(context, op->left, errbuf)) return -1; if (analyze_node(context, op->right, errbuf)) return -1; SDB_AST_NODE(op)->data_type = sdb_data_expr_type(SDB_AST_OP_TO_DATA_OP(op->kind), op->left->data_type, op->right->data_type); if ((op->left->data_type > 0) && (op->right->data_type > 0) && (SDB_AST_NODE(op)->data_type <= 0)) { op_error(errbuf, op, "type mismatch"); return -1; } /* TODO: replace constant arithmetic operations with a constant value */ return 0; } /* analyze_arith */
sdb_ast_node_t * sdb_ast_const_create(sdb_data_t value) { sdb_ast_const_t *c; c = SDB_AST_CONST(sdb_object_create("CONST", const_type)); if (! c) return NULL; c->super.type = SDB_AST_TYPE_CONST; c->value = value; return SDB_AST_NODE(c); } /* sdb_ast_const_create */
sdb_ast_node_t * sdb_ast_list_create(int obj_type, sdb_ast_node_t *filter) { sdb_ast_list_t *list; list = SDB_AST_LIST(sdb_object_create("LIST", list_type)); if (! list) return NULL; list->super.type = SDB_AST_TYPE_LIST; list->obj_type = obj_type; list->filter = filter; return SDB_AST_NODE(list); } /* sdb_ast_list_create */
sdb_ast_node_t * sdb_ast_value_create(int type, char *name) { sdb_ast_value_t *value; value = SDB_AST_VALUE(sdb_object_create("VALUE", value_type)); if (! value) return NULL; value->super.type = SDB_AST_TYPE_VALUE; value->type = type; value->name = name; return SDB_AST_NODE(value); } /* sdb_ast_value_create */
sdb_ast_node_t * sdb_ast_iter_create(int kind, sdb_ast_node_t *iter, sdb_ast_node_t *expr) { sdb_ast_iter_t *i; i = SDB_AST_ITER(sdb_object_create(SDB_AST_OP_TO_STRING(kind), iter_type)); if (! i) return NULL; i->super.type = SDB_AST_TYPE_ITERATOR; i->kind = kind; i->iter = iter; i->expr = expr; return SDB_AST_NODE(i); } /* sdb_ast_iter_create */
sdb_ast_node_t * sdb_ast_op_create(int kind, sdb_ast_node_t *left, sdb_ast_node_t *right) { sdb_ast_op_t *op; op = SDB_AST_OP(sdb_object_create(SDB_AST_OP_TO_STRING(kind), op_type)); if (! op) return NULL; op->super.type = SDB_AST_TYPE_OPERATOR; op->kind = kind; op->left = left; op->right = right; return SDB_AST_NODE(op); } /* sdb_ast_op_create */
sdb_ast_node_t * sdb_ast_lookup_create(int obj_type, sdb_ast_node_t *matcher, sdb_ast_node_t *filter) { sdb_ast_lookup_t *lookup; lookup = SDB_AST_LOOKUP(sdb_object_create("LOOKUP", lookup_type)); if (! lookup) return NULL; lookup->super.type = SDB_AST_TYPE_LOOKUP; lookup->obj_type = obj_type; lookup->matcher = matcher; lookup->filter = filter; return SDB_AST_NODE(lookup); } /* sdb_ast_lookup_create */
sdb_ast_node_t * sdb_ast_timeseries_create(char *hostname, char *metric, char **data_names, size_t data_names_len, sdb_time_t start, sdb_time_t end) { sdb_ast_timeseries_t *timeseries; timeseries = SDB_AST_TIMESERIES(sdb_object_create("TIMESERIES", ts_type)); if (! timeseries) return NULL; timeseries->super.type = SDB_AST_TYPE_TIMESERIES; timeseries->hostname = hostname; timeseries->metric = metric; timeseries->data_names = data_names; timeseries->data_names_len = data_names_len; timeseries->start = start; timeseries->end = end; return SDB_AST_NODE(timeseries); } /* sdb_ast_timeseries_create */
sdb_ast_node_t * sdb_ast_typed_create(int type, sdb_ast_node_t *expr) { char name[32]; sdb_ast_typed_t *typed; size_t i; strncpy(name, SDB_STORE_TYPE_TO_NAME(type), sizeof(name)); for (i = 0; i < strlen(name); ++i) name[i] = (char)toupper((int)name[i]); typed = SDB_AST_TYPED(sdb_object_create(name, typed_type)); if (! typed) return NULL; typed->super.type = SDB_AST_TYPE_TYPED; typed->type = type; typed->expr = expr; return SDB_AST_NODE(typed); } /* sdb_ast_typed_create */
sdb_ast_node_t * sdb_ast_fetch_create(int obj_type, char *hostname, int parent_type, char *parent, char *name, bool full, sdb_ast_node_t *filter) { sdb_ast_fetch_t *fetch; fetch = SDB_AST_FETCH(sdb_object_create("FETCH", fetch_type)); if (! fetch) return NULL; fetch->super.type = SDB_AST_TYPE_FETCH; fetch->obj_type = obj_type; fetch->hostname = hostname; fetch->parent_type = parent_type; fetch->parent = parent; fetch->name = name; fetch->full = full; fetch->filter = filter; return SDB_AST_NODE(fetch); } /* sdb_ast_fetch_create */
sdb_ast_node_t * sdb_parser_parse_arith(const char *expr, int len, sdb_strbuf_t *errbuf) { sdb_parser_yyscan_t scanner; sdb_parser_yyextra_t yyextra; sdb_ast_node_t *node; int yyres; if (scanner_init(expr, len, &scanner, &yyextra, errbuf)) return NULL; yyextra.mode = SDB_PARSE_ARITH; yyres = sdb_parser_yyparse(scanner); sdb_parser_scanner_destroy(scanner); if (yyres) { sdb_llist_destroy(yyextra.parsetree); return NULL; } node = SDB_AST_NODE(sdb_llist_get(yyextra.parsetree, 0)); if (! node) { sdb_strbuf_sprintf(errbuf, "Empty expression '%s'", expr); sdb_llist_destroy(yyextra.parsetree); return NULL; } assert(SDB_AST_IS_ARITHMETIC(node)); sdb_llist_destroy(yyextra.parsetree); if (sdb_parser_analyze_arith(node, errbuf)) { sdb_object_deref(SDB_OBJ(node)); return NULL; } return node; } /* sdb_parser_parse_arith */
sdb_ast_node_t * sdb_parser_parse_conditional(const char *cond, int len, sdb_strbuf_t *errbuf) { sdb_parser_yyscan_t scanner; sdb_parser_yyextra_t yyextra; sdb_ast_node_t *node; int yyres; if (scanner_init(cond, len, &scanner, &yyextra, errbuf)) return NULL; yyextra.mode = SDB_PARSE_COND; yyres = sdb_parser_yyparse(scanner); sdb_parser_scanner_destroy(scanner); if (yyres) { sdb_llist_destroy(yyextra.parsetree); return NULL; } node = SDB_AST_NODE(sdb_llist_get(yyextra.parsetree, 0)); if (! node) { sdb_strbuf_sprintf(errbuf, "Empty conditional expression '%s'", cond); sdb_llist_destroy(yyextra.parsetree); return NULL; } assert(SDB_AST_IS_LOGICAL(node)); sdb_llist_destroy(yyextra.parsetree); if (sdb_parser_analyze_conditional(node, errbuf)) { sdb_object_deref(SDB_OBJ(node)); return NULL; } return node; } /* sdb_parser_parse_conditional */
static int analyze_iter(int context, sdb_ast_iter_t *iter, sdb_strbuf_t *errbuf) { sdb_ast_const_t c = SDB_AST_CONST_INIT; int iter_context = context; int status; if (iter->iter->type == SDB_AST_TYPE_TYPED) iter_context = SDB_AST_TYPED(iter->iter)->type; if (analyze_node(iter_context, iter->iter, errbuf)) return -1; /* TODO: support other setups as well */ assert((iter->expr->type == SDB_AST_TYPE_OPERATOR) && (! SDB_AST_OP(iter->expr)->left)); /* determine the data-type for better error messages */ analyze_node(iter_context, SDB_AST_OP(iter->expr)->right, NULL); if (iter->iter->type == SDB_AST_TYPE_TYPED) { int iter_type = SDB_AST_TYPED(iter->iter)->type; c.value.type = iter->iter->data_type; if (iter_type == SDB_ATTRIBUTE) { /* attributes are always iterable */ } else if ((context != SDB_HOST) && (context != SDB_SERVICE) && (context != SDB_METRIC) && (context != UNSPEC_CONTEXT)) { iter_error(errbuf, iter, "%s not iterable in %s context", SDB_STORE_TYPE_TO_NAME(iter_type), SDB_STORE_TYPE_TO_NAME(context)); return -1; } if ((context == iter_type) || ((iter_type != SDB_SERVICE) && (iter_type != SDB_METRIC) && (iter_type != SDB_ATTRIBUTE)) || ((context == SDB_SERVICE) && (iter_type == SDB_METRIC)) || ((context == SDB_METRIC) && (iter_type == SDB_SERVICE))) { iter_error(errbuf, iter, "%s not iterable in %s context", SDB_STORE_TYPE_TO_NAME(iter_type), SDB_STORE_TYPE_TO_NAME(context)); return -1; } } else if (iter->iter->type == SDB_AST_TYPE_VALUE) { int iter_type = SDB_AST_VALUE(iter->iter)->type; c.value.type = iter->iter->data_type & 0xff; if (iter_type != SDB_FIELD_BACKEND) { iter_error(errbuf, iter, "%s not iterable in %s context", (iter_type == SDB_ATTRIBUTE) ? "attribute" : SDB_FIELD_TO_NAME(iter_type), SDB_STORE_TYPE_TO_NAME(context)); return -1; } } else if (iter->iter->type == SDB_AST_TYPE_CONST) { c.value.type = iter->iter->data_type & 0xff; if (! (SDB_AST_CONST(iter->iter)->value.type & SDB_TYPE_ARRAY)) { iter_error(errbuf, iter, "%s not iterable", SDB_TYPE_TO_STRING(SDB_AST_CONST(iter->iter)->value.type)); return -1; } } else { /* TODO: if we know the data-type of iter->iter and it's an array, * we should support an iterator for it as well */ iter_error(errbuf, iter, "%s expression not iterable", SDB_AST_TYPE_TO_STRING(iter->iter)); return -1; } SDB_AST_OP(iter->expr)->left = SDB_AST_NODE(&c); status = analyze_node(context, iter->expr, errbuf); SDB_AST_OP(iter->expr)->left = NULL; if (status) return -1; return 0; } /* analyze_iter */