extern int (*cf_read_hook)(byte *buf, uint max, int fd);
+struct stats_term_config;
struct symbol {
node n; /* In list of symbols in config */
struct symbol *next;
struct f_val *val; /* For SYM_CONSTANT */
uint offset; /* For SYM_VARIABLE */
struct channel_config *ch_config; /* For SYM_COUNTER */
+ struct stats_term_config *term; /* For SYM_COUNTER_TERM */
};
char name[0];
#define SYM_TABLE 5
#define SYM_ATTRIBUTE 6
#define SYM_COUNTER 7
+#define SYM_COUNTER_TERM 8
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
#define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff)
case SYM_COUNTER:
$$ = f_new_inst(FI_COUNTER, $1);
break;
+ case SYM_COUNTER_TERM:
+ $$ = f_new_inst(FI_COUNTER_TERM, $1);
+ break;
default:
cf_error("Can't get value of symbol %s", $1->name);
}
INST(FI_COUNTER, 0, 1) {
SYMBOL;
NEVER_CONSTANT;
- RESULT(T_INT, i, get_stats_counter(sym));
+ RESULT(T_INT, i, stats_get_counter(sym));
+ }
+
+ INST(FI_COUNTER_TERM, 0, 1) {
+ SYMBOL;
+ NEVER_CONSTANT;
+
+ RESULT_TYPE(stats_get_type(sym->term));
+ RESULT_VAL(stats_eval_term(sym->term));
}
INST(FI_CONSTANT, 0, 1) {
#include "filter/filter.h"
#include "filter/f-inst.h"
#include "filter/data.h"
-#include "proto/stats/stats.h" /* provides function get_stats_counter() used in f-inst.c */
+#include "proto/stats/stats-pub.h" /* provides function get_stats_counter() used in f-inst.c */
/* Exception bits */
CF_DEFINES
+#define STATS_CFG ((struct stats_config *) this_proto)
#define STATS_CC ((struct stats_channel_config *) this_channel)
CF_DECLS
-CF_KEYWORDS(STATS, TABLE, MAX, GENERATION, SETTLE, TIME)
+CF_KEYWORDS(STATS, TABLE, MAX, MIN, SETTLE, TIME)
%type <cc> stats_channel_start
stats_proto_start: proto_start STATS
{
this_proto = proto_config_new(&proto_stats, $1);
+ init_list(&STATS_CFG->terms);
}
proto_name ;
stats_opt:
type symbol '=' term {
- struct f_val val;
- if (f_eval(f_linearize($4), &val) > F_RETURN) cf_error("Runtime error");
+
+ struct stats_term_config *tc = cfg_alloc(sizeof(struct stats_term_config));
+ tc->code = (const struct f_line *) f_linearize($4);
+ tc->type = $1;
+ tc->name = $2->name;
+
+ struct f_val val;
+ /* greater then F_RETURN, therefore 2 */
+ if (f_eval(f_linearize($4), &val) > 2) cf_error("Runtime error");
if (val.type != $1) cf_error("The expresion does not match defined type");
- /* cf_define_symbol($2, SYM_VARIABLE | $1, val )*/
+
+ add_tail(&STATS_CFG->terms, (node *) tc);
+
+ $2 = cf_define_symbol($2, SYM_COUNTER_TERM, term, tc);
}
| MIN SETTLE TIME expr_us { STATS_CC->min_settle_time = $4; }
| MAX SETTLE TIME expr_us { STATS_CC->max_settle_time = $4; }
--- /dev/null
+#ifndef _BIRD_STATS_PUB_H_
+#define _BIRD_STATS_PUB_H_
+
+extern int stats_get_counter(struct symbol *sym);
+extern struct f_val stats_eval_term(struct stats_term_config *tc);
+extern int stats_get_type(struct stats_term_config *tc);
+#endif
{
log(L_INFO "stats_start() ");
stats_configure_channels(P, P->cf);
+
+ struct stats_term_config *tc;
+ WALK_LIST(tc, ((struct stats_config *) P->cf)->terms)
+ {
+ log(L_INFO "term %s", tc->name);
+ f_eval(tc->code, &tc->val);
+ log(L_INFO "content: %s, matches %s", val_dump(&tc->val),
+ tc->type == tc->val.type ? "yes" : "no");
+ }
+
return PS_UP;
}
cli_msg(-1006, " Settle time: %4u s", (*(sc->settle_timer->max_settle_time)) TO_S);
}
}
+
+ cli_msg(-1006, " Terms:");
+ cli_msg(-1006, "terms list: %p", ((struct stats_config *) p->c)->terms);
}
void
c->pool = NULL;
}
+int
+stats_get_counter(struct symbol *sym)
+{
+ if (sym->ch_config->channel)
+ return (int) ((struct stats_channel *) sym->ch_config->channel)->counter;
+ else
+ return 0;
+}
+
+struct f_val
+stats_eval_term(struct stats_term_config *tc)
+{
+ log(L_INFO "stats_eval_term() evaluating value of %s",
+ tc->name);
+ enum filter_return fret = f_eval(tc->code, &tc->val);
+
+ if (fret > F_RETURN)
+ tc->val.type = T_VOID;
+
+ if (tc->type != tc->val.type)
+ tc->val.type = T_VOID;
+
+ log(L_INFO " stats_eval_term() returning %s", val_dump(&tc->val));
+ return tc->val;
+}
+
+int
+stats_get_type(struct stats_term_config *tc)
+{
+ log(L_INFO "stats_get_type()");
+ return tc->type;
+}
+
+
struct channel_class channel_stats = {
.channel_size = sizeof(struct stats_channel),
.config_size = sizeof(struct stats_channel_config),
#ifndef _BIRD_STATS_H_
#define _BIRD_STATS_H_
#include "lib/timer.h"
+#include "filter/data.h"
struct stats_channel;
+struct stats_term_config {
+ node n;
+ const struct f_line *code;
+ struct f_val val;
+ int type; /* type declared in configuration */
+ const char *name;
+};
+
struct stats_config {
struct proto_config c;
+ list terms; /* list of counter terms */
};
struct stats_proto {
btime max_settle_time;
};
+int stats_get_counter(struct symbol *sym);
+struct f_val stats_eval_term(struct stats_term_config *tc);
+int stats_get_type(struct stats_term_config *tc);
+
+#if 0
/*
* get_stats_counter() - extract last notified counter
* for specific stats channel if it runs
*
*/
-static inline int
-get_stats_counter(struct symbol *sym)
+inline int
+stats_get_counter(struct symbol *sym)
{
if (sym->ch_config->channel)
return (int) ((struct stats_channel *) sym->ch_config->channel)->counter;
return 0;
}
+/*
+ * stats_eval_term() - evaluate stats term
+ *
+ */
+inline struct f_val
+stats_eval_term(struct stats_term_config *tc)
+{
+ enum filter_return fret = f_eval(tc->code, &tc->val);
+
+ if (fret > F_RETURN)
+ tc->val.type = T_VOID;
+
+ if (tc->type != tc->val.type)
+ tc->val.type = T_VOID;
+
+ return tc->val;
+}
+
+int
+stats_get_type(struct stats_term_config *tc)
+{
+ return tc->type;
+}
+
+#endif // if 0
+
#endif