#include "stdafx.h"
#include "evtengine.h"
#include "list.h"
#include "array.h"
#include "spinlock.h"
#include "hashset.h"
#include "hash.h"
#include "jhash.h"
#include "strutil.h"
#include "fileutil.h"
#include "scew.h"
#if 0
O
M
D
#endif
#define BIT_MASK(bit) (1 << (bit))
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
typedef struct evt_filter_key_t evt_filter_key_t;
typedef struct evt_filter_t evt_filter_t;
typedef struct evt_expire_t evt_expire_t;
typedef struct evt_slot_key_t evt_slot_key_t;
typedef struct evt_slot_t evt_slot_t;
typedef struct evt_sysvar_rule_t evt_sysvar_rule_t;
typedef struct evt_sysvar_key_t evt_sysvar_key_t;
typedef struct evt_sysvar_t evt_sysvar_t;
typedef struct evt_slot_rule_t evt_slot_rule_t;
typedef struct evt_trigger_t evt_trigger_t;
typedef struct evt_slotvar_t evt_slotvar_t;
static int nIslog = 1;
struct evt_filter_key_t
{
unsigned long long listen_id; // id
};
struct evt_filter_t
{
evt_filter_key_t key;
int log_type;
int ent_id;
int severity;
int sys_code;
int user_code;
char *entity;
evt_slotvar_t *content_to_var;
evt_slot_t *owner;
struct hlist_node hentry;
};
struct evt_expire_t
{
int timer_id;
int timeout;
evt_slot_t *parent;
};
struct evt_slot_key_t
{
char *code;
unsigned int index_hash_code;
};
struct evt_slotvar_t
{
char *name;
char *init_value;
char *current_value;
};
struct evt_slot_t
{
struct hlist_node hentry;
evt_slot_key_t key;
evt_expire_t *timer;
evt_engine_t *parent;
int once;
array_header_t *arr_filter;
array_header_t *arr_rref_reset;
array_header_t *arr_ref_reset;
array_header_t *arr_reset;
array_header_t *arr_ref_trigger;
array_header_t *arr_slotvar;
int signal_state;
struct list_head use_entry;
struct list_head *use_list_ptr;
};
struct evt_sysvar_rule_t
{
struct list_head entry;
evt_trigger_t *parent;
int positive;
array_header_t *arr_state;
evt_sysvar_t *ref_sysvar;
};
struct evt_sysvar_key_t
{
char *code;
unsigned int index_hash_code;
};
struct evt_sysvar_t
{
struct hlist_node hentry;
evt_sysvar_key_t key;
array_header_t *arr_ref_rule;
struct evt_engine_t *parent;
};
struct evt_slot_rule_t
{
struct list_head entry;
evt_trigger_t *parent;
int positive;
char *code;
char *message;
evt_slot_t *ref_slot;
};
struct evt_trigger_t
{
struct list_head entry;
evt_engine_t *parent;
struct list_head sysvar_list;
struct list_head slot_rule_list;
int log_type;
int severity_level;
int sys_code;
int user_code;
int delay_ms;
int delay_timer_id; // if delay_ms != 0
char *msg;
struct list_head use_entry;
};
struct evt_engine_t
{
evt_engine_callback_t cb;
struct list_head trigger_list;
htable_t *filter_ht;
htable_t *sysvar_ht;
htable_t *slot_ht;
spinlock_t lock;
};
static __inline void env_engine_lock(evt_engine_t *engine)
{
spinlock_enter(&engine->lock, -1);
}
static __inline void env_engine_unlock(evt_engine_t *engine)
{
spinlock_leave(&engine->lock);
}
static __inline unsigned int filter_key_hasher(const evt_filter_key_t *key)
{
return (unsigned int)key->listen_id;
}
static __inline int filter_key_cmp(const evt_filter_key_t *key1, const evt_filter_key_t *key2)
{
return key1->listen_id - key2->listen_id;
}
IMPLEMENT_HTABLE_STATIC(filter, evt_filter_key_t, evt_filter_t, key, hentry, filter_key_hasher, filter_key_cmp)
static __inline unsigned int sysevt_key_hasher(const evt_sysvar_key_t *key)
{
return key->index_hash_code;
}
static __inline int sysevt_key_cmp(const evt_sysvar_key_t *key1, const evt_sysvar_key_t *key2)
{
return strcmp(key1->code, key2->code);
}
IMPLEMENT_HTABLE_STATIC(sysvar, evt_sysvar_key_t, evt_sysvar_t, key, hentry, sysevt_key_hasher, sysevt_key_cmp)
static __inline unsigned int slot_key_hasher(const evt_slot_key_t *key)
{
return key->index_hash_code;
}
static __inline int sysevt_key_cmp(const evt_slot_key_t *key1, const evt_slot_key_t *key2)
{
return strcmp(key1->code, key2->code);
}
IMPLEMENT_HTABLE_STATIC(slot, evt_slot_key_t, evt_slot_t, key, hentry, slot_key_hasher, sysevt_key_cmp)
static int process_trigger_list(evt_engine_t *engine, struct list_head *trigger_list);
static int postprocess_slot_list(evt_engine_t *engine, struct list_head *affect_list);
static void clear_slot_list(struct list_head *affect_list);
static void clear_trigger_list(struct list_head *matched_trigger_list);
static int generate_trigger_log(evt_engine_t *engine, evt_trigger_t *trigger);
static void filter_free(evt_filter_t *filter)
{
if (filter) {
if (filter->entity){
free(filter->entity);
}
free(filter);
}
}
static void slot_free(evt_slot_t *slot)
{
if (slot) {
if (slot->key.code) {
toolkit_free(slot->key.code);
}
if (slot->arr_filter) {
int i;
for (i = 0; i < slot->arr_filter->nelts; ++i) {
evt_filter_t *filter = ARRAY_IDX(slot->arr_filter, i, evt_filter_t*);
filter_free(filter);
}
array_free(slot->arr_filter);
}
if (slot->arr_reset) {
int i;
for (i = 0; i < slot->arr_reset->nelts; ++i) {
toolkit_free(ARRAY_IDX(slot->arr_reset, i, char*));
}
array_free(slot->arr_reset);
}
if (slot->arr_ref_trigger) {
array_free(slot->arr_ref_trigger);
}
if (slot->arr_rref_reset) {
array_free(slot->arr_rref_reset);
}
if (slot->arr_ref_reset) {
array_free(slot->arr_ref_reset);
}
if (slot->arr_slotvar) {
int i;
for (i = 0; i < slot->arr_slotvar->nelts; ++i) {
evt_slotvar_t *slotvar = ARRAY_IDX(slot->arr_slotvar, i, evt_slotvar_t*);
if (slotvar->name){
free(slotvar->name);
}
if (slotvar->init_value) {
free(slotvar->init_value);
}
if (slotvar->current_value){
free(slotvar->current_value);
}
free(slotvar);
}
array_free(slot->arr_slotvar);
}
if (slot->timer) {
if (slot->signal_state) {
int rc;
evt_engine_t *engine = slot->parent;
rc = engine->cb.kill_timer(engine, slot->timer->timer_id, engine->cb.user_data);
if (rc != 0)
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("kill timer %d failed!", slot->timer->timer_id);
}
slot->timer->timer_id = -1;
}
free(slot->timer);
}
free(slot);
}
}
static void sysvar_free(evt_sysvar_t *sysvar)
{
if (sysvar) {
if (sysvar->arr_ref_rule) {
array_free(sysvar->arr_ref_rule);
}
if (sysvar->key.code){
free(sysvar->key.code);
}
free(sysvar);
}
}
static void trigger_free(evt_trigger_t *trigger)
{
if (trigger) {
evt_slot_rule_t *slot_rule, *n1;
evt_sysvar_rule_t *sysvar_rule, *n2;
if (trigger->msg) {
free(trigger->msg);
}
list_for_each_entry_safe(slot_rule, n1, &trigger->slot_rule_list, evt_slot_rule_t, entry) {
list_del(&slot_rule->entry);
//if (slot_rule->code)
//free(slot_rule->code);
free(slot_rule);
}
list_for_each_entry_safe(sysvar_rule, n2, &trigger->sysvar_list, evt_sysvar_rule_t, entry) {
list_del(&sysvar_rule->entry);
if (sysvar_rule->arr_state) {
int i;
for (i = 0; i < sysvar_rule->arr_state->nelts; ++i) {
free(ARRAY_IDX(sysvar_rule->arr_state, i, char*));
}
array_free(sysvar_rule->arr_state);
}
free(sysvar_rule);
}
free(trigger);
}
}
static void slot_rule_free(evt_slot_rule_t *rule)
{
if (rule) {
if (rule->code){
free(rule->code);
}
if (rule->message) {
free(rule->message);
}
free(rule);
}
}
static void sysvar_rule_free(evt_sysvar_rule_t *rule)
{
if (rule) {
if (rule->arr_state) {
int i;
for (i = 0; i < rule->arr_state->nelts; ++i) {
free(ARRAY_IDX(rule->arr_state, i, char*));
}
array_free(rule->arr_state);
}
free(rule);
}
}
static void output_char(char **po, int *poi, int *pon, char *s, int sn)
{
char *o = *po;
int on = *pon;
int oi = *poi;
if (sn == -1)
sn = strlen(s);
while (on-oi <= sn) {
on = on * 2;
o = (char*)realloc(o, on);
}
memcpy(o+oi, s, sn);
oi += sn;
*po = o;
*poi = oi;
*pon = on;
}
static evt_slotvar_t *slot_find_var(evt_slot_t *slot, char *s)
{
int i;
for (i = 0; i < slot->arr_slotvar->nelts; ++i) {
evt_slotvar_t *slotvar = ARRAY_IDX(slot->arr_slotvar, i, evt_slotvar_t*);
if (_stricmp(slotvar->name, s) == 0)
return slotvar;
}
return NULL;
}
static char *expand_slot_rule_message(evt_slot_rule_t *slot_rule)
{
int oi = 0;
int on = 32;
char *o = (char*)malloc(on);
int m = 0;
char *s = NULL;
char *p = slot_rule->message;
while (*p) {
if (m == 0) {
if (p[0] == '$' && p[1] == '(') {
m = 1;
p++;
}
else {
output_char(&o, &oi, &on, p, 1);
}
}
else {
if (p[0] == ')') {
if (s) {
char *t = (char*)malloc(p - s + 1);
memcpy(t, s, p-s);
t[p-s] = 0;
evt_slotvar_t *slotvar = slot_find_var(slot_rule->ref_slot, t);
free(t);
if (slotvar) {
output_char(&o, &oi, &on, slotvar->current_value, -1);
}
s = NULL;
m = 0;
}
} else {
if (!s) {
s = p;
}
}
}
p++;
}
o[oi] = 0;
return o;
}
static char *expand_trigger_message(evt_trigger_t *trigger)
{
int oi = 0;
int on = 32;
char *o = (char*)malloc(on);
evt_slot_rule_t *tpos;
list_for_each_entry(tpos, &trigger->slot_rule_list, evt_slot_rule_t, entry) {
if (tpos->message) {
char *t = expand_slot_rule_message(tpos);
if (t) {
output_char(&o, &oi, &on, t, -1);
free(t);
}
}
}
if (trigger->msg) {
output_char(&o, &oi, &on, trigger->msg, -1);
}
o[oi] = 0;
return o;
}
static void get_matched_slot_list(evt_engine_t *engine, const CAutoArray &SubIDs, int log_type, int ent_id, int severity, int sys_code, int usr_code, const char *message, struct list_head *use_list)
{
#if 0
evt_filter_key_t k;
int i, j;
for (j = 0; j < 3; ++j) {
if (j == 0) {
k.user_code = usr_code; // strict match
} else if (j == 1) {
k.user_code = -2; // accept any
} else {
if (usr_code) {
k.user_code = -1; // reject ones that has no user code
} else {
continue;
}
}
for (i = 0; i < engine->masks_cnt; ++i) {
evt_filter_t *filter;
int t = engine->masks[i];
k.log_type = (t & BIT_MASK(LOG_FILTER_BIT_LOGTYPE)) ? Log_Ignore : log_type;
k.ent_id = (t & BIT_MASK(LOG_FILTER_BIT_ENTITY)) ? -1 : ent_id;
k.severity = (t & BIT_MASK(LOG_FILTER_BIT_SEVERITY)) ? Severity_None : severity;
k.sys_code = (t & BIT_MASK(LOG_FILTER_BIT_SYSCODE)) ? Error_IgnoreAll : sys_code;
k.index_hash_code = hash_filter(k.log_type, k.ent_id, k.severity, k.sys_code, k.user_code);
filter = filter_find(engine->filter_ht, &k);
while (filter) {
int ii;
for (ii = 0; ii < filter->arr_ref_slot->nelts; ++ii) {
evt_slot_t *slot = ARRAY_IDX(filter->arr_ref_slot, ii, evt_slot_t*);
if (!slot->use_entry.next) {
list_add_tail(&slot->use_entry, use_list);
slot->use_list_ptr = use_list;
}
}
filter = filter_find_continue(engine->filter_ht, &filter->hentry, &k);
}
}
}
#endif
int i;
for (i = 0; i < SubIDs.GetCount(); ++i) {
evt_filter_t *filter;
evt_filter_key_t k;
k.listen_id = (unsigned int)SubIDs[i];
filter = filter_find(engine->filter_ht, &k);
if (filter) {
evt_slot_t *slot = filter->owner;
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("filter found, usr_code:%d, listen_id:%d", usr_code, k.listen_id);
}
if (!slot->use_entry.next) {
list_add_tail(&slot->use_entry, use_list);
slot->use_list_ptr = use_list;
}
if (filter->content_to_var) {
if (filter->content_to_var->current_value) {
free(filter->content_to_var->current_value);
}
filter->content_to_var->current_value = _strdup(message);
}
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("cannot find filter, listen_id:%d", k.listen_id);
}
}
}
}
static void get_reset_slot_list(evt_engine_t *engine, struct list_head *matched_list, struct list_head *reset_list)
{
evt_slot_t *pos;
list_for_each_entry(pos, matched_list, evt_slot_t, use_entry) {
if (pos->arr_ref_reset) {
int i;
for (i = 0; i < pos->arr_ref_reset->nelts; ++i) {
evt_slot_t *t = ARRAY_IDX(pos->arr_ref_reset, i, evt_slot_t*);
if (!t->use_entry.next) {
list_add_tail(&t->use_entry, reset_list);
t->use_list_ptr = reset_list;
}
else {
if (t->use_list_ptr == matched_list) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("warning: slot %s already set, cannot reset from slot %s ", t->key.code, pos->key.code);
}
}
else if (t->use_list_ptr == reset_list) {
// already triggers by others
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("bug detected! %s%d", __FUNCTION__, __LINE__);
}
}
}
}
}
}
}
static void get_matched_trigger_list(evt_engine_t *engine, struct list_head *use_slot_list, struct list_head *use_trigger_list)
{
evt_slot_t *pos;
list_for_each_entry(pos, use_slot_list, evt_slot_t, use_entry) {
int i;
for (i = 0; i < pos->arr_ref_trigger->nelts; ++i) {
evt_trigger_t *trigger = ARRAY_IDX(pos->arr_ref_trigger, i, evt_trigger_t*);
if (!trigger->use_entry.next) {
list_add_tail(&trigger->use_entry, use_trigger_list);
}
}
}
}
static void timer_cb(int timer_id, void *user_data)
{
evt_slot_t *slot = (evt_slot_t*)user_data;
evt_engine_t *engine = slot->parent;
if (timer_id == slot->timer->timer_id) {
int rc;
struct list_head affect_list = LIST_HEAD_INIT(affect_list);
struct list_head trigger_list = LIST_HEAD_INIT(trigger_list);
list_add_tail(&slot->use_entry, &affect_list);
slot->use_list_ptr = &affect_list;
slot->signal_state = !slot->signal_state;
if (!slot->signal_state && slot->arr_slotvar) {
int i;
for (i = 0; i < slot->arr_slotvar->nelts; ++i) {
evt_slotvar_t *slotvar = ARRAY_IDX(slot->arr_slotvar, i, evt_slotvar_t *);
free(slotvar->current_value);
slotvar->current_value = _strdup(slotvar->init_value);
}
}
engine->cb.kill_timer(engine, slot->timer->timer_id, engine->cb.user_data);
slot->timer->timer_id = -1;
get_matched_trigger_list(engine, &affect_list, &trigger_list);
rc = process_trigger_list(engine, &trigger_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process trigger list failed!");
}
return;
}
rc = postprocess_slot_list(engine, &affect_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("postprocess slotlist failed!");
}
return;
}
clear_slot_list(&affect_list);
clear_trigger_list(&trigger_list);
}
}
static void trigger_timer_cb(int timer_id, void *user_data)
{
evt_trigger_t *trigger = (evt_trigger_t *)user_data;
evt_engine_t *engine = trigger->parent;
if (timer_id == trigger->delay_timer_id) {
generate_trigger_log(engine, trigger);
engine->cb.kill_timer(engine, trigger->delay_timer_id, engine->cb.user_data);
trigger->delay_timer_id = -1;
}
}
static int process_matched_slot(evt_engine_t *engine, evt_slot_t *slot, int *removed)
{
int rc = 0;
if (slot->signal_state) {
// reset timer
if (slot->timer) {
rc = engine->cb.kill_timer(engine, slot->timer->timer_id, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("kill timer failed! slot: %s, timer_id: %d", slot->key.code, slot->timer->timer_id);
}
}
else {
int new_id = engine->cb.new_timer_id(engine, engine->cb.user_data);
slot->timer->timer_id = new_id;
rc = engine->cb.set_timer(engine, new_id, slot->timer->timeout, &timer_cb, slot, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("set timer failed! slot: %s, timer_id: %d", slot->key.code, new_id);
}
}
}
}
if (removed){
*removed = 1;
}
}
else {
slot->signal_state = !slot->signal_state;
if (slot->timer) {
int new_id = engine->cb.new_timer_id(engine, engine->cb.user_data);
slot->timer->timer_id = new_id;
rc = engine->cb.set_timer(engine, new_id, slot->timer->timeout, &timer_cb, slot, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("set timer failed! slot: %s, timer_id: %d", slot->key.code, new_id);
}
}
}
if (removed) {
*removed = 0;
}
}
return rc;
}
static int process_matched_slot_list(evt_engine_t *engine, struct list_head *slot_list)
{
evt_slot_t *pos, *n;
int rc = 0;
list_for_each_entry_safe(pos, n, slot_list, evt_slot_t, use_entry) {
int removed;
rc = process_matched_slot(engine, pos, &removed);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process matched slot %s failed!", pos->key.code);
}
break;
}
if (removed) {
list_del(&pos->use_entry);
pos->use_entry.next = pos->use_entry.prev = NULL;
pos->use_list_ptr = NULL;
}
}
return rc;
}
static int process_reset_slot(evt_engine_t *engine, evt_slot_t *slot, int *removed)
{
int rc = 0;
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process reset slot: %s, current signal:%d", slot->key.code, slot->signal_state);
}
if (slot->signal_state) {
slot->signal_state = !slot->signal_state;
if (slot->timer) {
rc = engine->cb.kill_timer(engine, slot->timer->timer_id, engine->cb.user_data);
slot->timer->timer_id = -1;
}
if (removed){
*removed = 0;
}
if (slot->arr_slotvar) {
int i;
for (i = 0; i < slot->arr_slotvar->nelts; ++i) {
evt_slotvar_t* slotvar = ARRAY_IDX(slot->arr_slotvar, i, evt_slotvar_t*);
free(slotvar->current_value);
slotvar->current_value = _strdup(slotvar->init_value);
}
}
}
else {
if (removed){
*removed = 1;
}
}
return rc;
}
static int process_reset_slot_list(evt_engine_t *engine, struct list_head *reset_list)
{
evt_slot_t *pos, *n;
int rc = 0;
list_for_each_entry_safe(pos, n, reset_list, evt_slot_t, use_entry) {
int removed;
rc = process_reset_slot(engine, pos, &removed);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process reset slot %s failed!", pos->key.code);
}
break;
}
if (removed) {
list_del(&pos->use_entry);
pos->use_entry.next = pos->use_entry.prev = NULL;
pos->use_list_ptr = NULL;
}
}
return rc;
}
static int generate_trigger_log(evt_engine_t *engine, evt_trigger_t *trigger)
{
int rc = Error_Succeed;
char *msg = expand_trigger_message(trigger);
switch (trigger->log_type) {
case Log_Warning:
LogWarn((SeverityLevelEnum)trigger->severity_level,(ErrorCodeEnum)trigger->sys_code, (DWORD)trigger->user_code,msg);
break;
case Log_Debug:
LogTrace(msg, __FILE__, __LINE__);
break;
case Log_Error:
LogError((SeverityLevelEnum)trigger->severity_level, (ErrorCodeEnum)trigger->sys_code, trigger->user_code, msg);
break;
case Log_Event:
LogEvent((SeverityLevelEnum)trigger->severity_level, (DWORD)trigger->user_code, msg);
break;
default:
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("bug detected! %s %d", __FUNCTION__, __LINE__);
}
assert(0);
rc = Error_Bug;
}
free(msg);
return rc;
}
static int process_trigger(evt_engine_t *engine, evt_trigger_t *trigger)
{
int rc = 0;
int ok = 0;
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process_trigger %s begin!", trigger->msg);
}
{
evt_slot_rule_t *pos;
list_for_each_entry(pos, &trigger->slot_rule_list, evt_slot_rule_t, entry) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("slot rule, code:%s positive:%d signal:%d", pos->code, pos->positive, pos->ref_slot->signal_state);
}
if (pos->positive ^ pos->ref_slot->signal_state)
goto on_done;
}
}
{
evt_sysvar_rule_t *pos;
list_for_each_entry(pos, &trigger->sysvar_list, evt_sysvar_rule_t, entry) {
int i;
CSimpleStringA strState;
rc = engine->cb.get_sysevent(engine, pos->ref_sysvar->key.code, strState, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("get sysvar failed!");
}
goto on_done;
}
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sysvar key=%s, value=%s", pos->ref_sysvar->key.code, (LPCSTR)strState);
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sysvar rule, %s, positive:%d", pos->ref_sysvar->key.code, pos->positive);
}
if (pos->positive) {
for (i = 0; i < pos->arr_state->nelts; ++i) {
char *state = ARRAY_IDX(pos->arr_state, i, char*);
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sys var state:%s", state);
}
if (strcmp(strState, state) == 0) {
break;
}
}
if (i == pos->arr_state->nelts) {
goto on_done;
}
}
else {
for (i = 0; i < pos->arr_state->nelts; ++i) {
char *state = ARRAY_IDX(pos->arr_state, i, char*);
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sys var state:%s", state);
}
if (strcmp(strState, state) == 0) {
goto on_done;
}
}
}
}
}
ok = 1;
on_done:
if (ok) {
if (trigger->delay_ms != 0 && trigger->delay_timer_id == -1) {
trigger->delay_timer_id = engine->cb.new_timer_id(engine, engine->cb.user_data);
rc = engine->cb.set_timer(engine, trigger->delay_timer_id, trigger->delay_ms, &trigger_timer_cb, trigger, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("set timer failed!");
}
}
} else {
rc = generate_trigger_log(engine, trigger);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("generate trigger log failed!");
}
}
}
}
else {
if (trigger->delay_timer_id != -1) {
engine->cb.kill_timer(engine, trigger->delay_timer_id, engine->cb.user_data);
trigger->delay_timer_id = -1;
}
}
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("process_trigger end (ok=%d)!", ok);
}
return rc;
}
static int process_trigger_list(evt_engine_t *engine, struct list_head *trigger_list)
{
evt_trigger_t *pos;
int rc = 0;
list_for_each_entry(pos, trigger_list, evt_trigger_t, use_entry) {
rc = process_trigger(engine, pos);
if (rc != 0){
break;
}
}
return rc;
}
static int postprocess_slot_list(evt_engine_t *engine, struct list_head *affect_list)
{
int rc = 0;
evt_slot_t *pos;
list_for_each_entry(pos, affect_list, evt_slot_t, use_entry) {
if (pos->once && pos->signal_state) {
pos->signal_state = !pos->signal_state;
if (pos->timer) {
rc = engine->cb.kill_timer(engine, pos->timer->timer_id, engine->cb.user_data);
pos->timer->timer_id = -1;
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("postprocess slot %s failed!", pos->key.code);
}
return rc;
}
}
}
}
return rc;
}
static void clear_slot_list(struct list_head *affect_list)
{
evt_slot_t *pos, *n;
list_for_each_entry_safe(pos, n, affect_list, evt_slot_t, use_entry) {
list_del(&pos->use_entry);
pos->use_entry.next = pos->use_entry.prev = NULL;
pos->use_list_ptr = NULL;
}
}
static void clear_trigger_list(struct list_head *matched_trigger_list)
{
evt_trigger_t *pos, *n;
list_for_each_entry_safe(pos, n, matched_trigger_list, evt_trigger_t, use_entry) {
list_del(&pos->use_entry);
pos->use_entry.next = pos->use_entry.prev = NULL;
}
};
static int process_log(evt_engine_t *engine, const CAutoArray &SubIDs, int log_type, int ent_id, int severity, int sys_code, int usr_code, const char *message)
{
int rc;
struct list_head matched_list = LIST_HEAD_INIT(matched_list);
struct list_head reset_list = LIST_HEAD_INIT(reset_list);
struct list_head affect_list = LIST_HEAD_INIT(affect_list);
struct list_head matched_trigger_list = LIST_HEAD_INIT(matched_trigger_list);
get_matched_slot_list(engine, SubIDs,log_type, ent_id, severity, sys_code, usr_code, message, &matched_list);
if (list_empty(&matched_list)) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("warning: no matched slot! sys_code = %d, usr_code = %d", sys_code, usr_code);
}
return 0;
}
get_reset_slot_list(engine, &matched_list, &reset_list);
rc = process_matched_slot_list(engine, &matched_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process matched slot list failed!");
}
return rc;
}
rc = process_reset_slot_list(engine, &reset_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process reset slot list failed!");
}
return rc;
}
list_splice_tail(&matched_list, &affect_list);
list_splice_tail(&reset_list, &affect_list);
get_matched_trigger_list(engine, &affect_list, &matched_trigger_list);
rc = process_trigger_list(engine, &matched_trigger_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process trigger list failed!");
}
return rc;
}
rc = postprocess_slot_list(engine, &affect_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("postprocess slot list failed!");
}
return rc;
}
clear_slot_list(&affect_list);
clear_trigger_list(&matched_trigger_list);
return rc;
}
static int process_sysvar(evt_engine_t *engine, evt_sysvar_t *sysvar, const char *old_value, const char *curr_value)
{
int i;
int rc = 0;
struct list_head trigger_list = LIST_HEAD_INIT(trigger_list);
for (i = 0; i < sysvar->arr_ref_rule->nelts; ++i) {
evt_sysvar_rule_t *rule = ARRAY_IDX(sysvar->arr_ref_rule, i, evt_sysvar_rule_t*);
evt_trigger_t *trigger = rule->parent;
if (!trigger->use_entry.next) {
list_add_tail(&trigger->use_entry, &trigger_list);
}
}
rc = process_trigger_list(engine, &trigger_list);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process trigger list failed!");
}
}
clear_trigger_list(&trigger_list);
return rc;
}
static int build_ref(evt_engine_t *engine)
{
int i;
evt_trigger_t *trigger;
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("engine->slot_ht->size = %d.", engine->slot_ht->size);
for (i = 0; i < engine->slot_ht->size; ++i) {
evt_slot_t *tpos;
struct hlist_node *pos;
hlist_for_each_entry(tpos, pos, &engine->slot_ht->buckets[i], evt_slot_t, hentry) {
int j;
for (j = 0; j < tpos->arr_reset->nelts; ++j) {
char *code = ARRAY_IDX(tpos->arr_reset, j, char*);
evt_slot_key_t key;
key.code = code;
key.index_hash_code = hash32_str(code, HASH32_STR_INIT);
evt_slot_t *ref_slot = slot_find(engine->slot_ht, &key);
if (ref_slot) {
ARRAY_PUSH(ref_slot->arr_rref_reset, evt_slot_t*) = tpos;
ARRAY_PUSH(tpos->arr_ref_reset, evt_slot_t*) = ref_slot;
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("build reset ref for slot %s->%s", tpos->key.code, code);
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("cannot build reset ref for slot %s->%s", tpos->key.code, code);
}
return Error_Unexpect;
}
}
}
}
list_for_each_entry(trigger, &engine->trigger_list, evt_trigger_t, entry) {
evt_slot_rule_t *rule;
list_for_each_entry(rule, &trigger->slot_rule_list, evt_slot_rule_t, entry) {
evt_slot_key_t key;
key.code = rule->code;
key.index_hash_code = hash32_str(key.code, HASH32_STR_INIT);
evt_slot_t *ref_slot = slot_find(engine->slot_ht, &key);
if (ref_slot) {
rule->ref_slot = ref_slot;
ARRAY_PUSH(ref_slot->arr_ref_trigger, evt_trigger_t*) = rule->parent;
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("array push trigger.slot %s.", rule->code);
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger.slot %s cannot find code!", rule->code);
}
return Error_Unexpect;
}
}
}
return 0;
}
// HH:MM:SS.mmm or MM:SS.mmm or xxxms or xxx
// 10:10:10 -> 10h 10m 10 second
// 1:00 -> 1min = 1000ms
// 1s -> 1 second = 1000ms
// 1000 -> 1000millisecond
// 1000ms -> 1000millisecond
// 1min -> 1000millisecond
// return millisecond
static int parse_timeout_value(const char *s)
{
int t[8] = {0};
int tc = 0;
const char *p = s;
#define PARSE_T_COLON 0x7fff0000
#define PARSE_T_DOT 0x7fff0001
#define PARSE_T_MIN 0x7fff0002
#define PARSE_T_MS 0x7fff0003
#define PARSE_T_S 0x7fff0004
#define PARSE_T_H 0x7fff0005
while (*p && tc < 8) {
switch (*p) {
case ':':
t[tc++] = PARSE_T_COLON;
p++;
break;
case '.':
t[tc++] = PARSE_T_DOT;
p++;
break;
case 's':
t[tc++] = PARSE_T_S;
p++;
break;
case 'h':
t[tc++] = PARSE_T_H;
p++;
break;
case 'm':
if (p[1] == 'i' && p[2] == 'n') {
t[tc++] = PARSE_T_MIN;
p += 3;
} else if (p[1] == 's') {
t[tc++] = PARSE_T_MS;
p += 2;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
int x = *p - '0';
++p;
while (*p >= '0' && *p <= '9') {
x = x * 10 + (*p - '0');
p++;
}
if (x >= 0x7fff0000)
return -1;
t[tc++] = x;
}
break;
default:
return -1;
}
}
switch (tc) {
case 0:
return 0;
case 1:
if (t[0] < 0x7fff0000)
return t[0];
break;
case 2:
if (t[0] < 0x7fff0000) {
if (t[1] == PARSE_T_S) {
return t[0] * 1000;
} else if (t[1] == PARSE_T_MS) {
return t[0];
} else if (t[1] == PARSE_T_H) {
return t[0] * 60 * 60 * 1000;
} else if (t[1] == PARSE_T_MIN) {
return t[0] * 60 * 1000;
} else {
return -1;
}
} else if (t[0] == PARSE_T_DOT && t[1] < 0x7fff0000) {
return t[1];
}
break;
case 3:
if (t[0] < 0x7fff0000 && t[2] < 0x7fff0000) {
if (t[1] == PARSE_T_DOT) {
return t[0] * 1000 + t[2];
} else if (t[1] == PARSE_T_COLON) {
return (t[0] * 60 + t[2]) * 1000;
}
}
break;
case 5:
if (t[0] < 0x7fff0000 && t[2] < 0x7fff0000 && t[4] < 0x7fff0000 && t[1] == PARSE_T_COLON && t[3] == PARSE_T_COLON)
return ((t[0] * 60 + t[2]) * 60 + t[4]) * 1000;
break;
case 7:
if (t[0] < 0x7fff0000 && t[2] < 0x7fff0000 && t[4] < 0x7fff0000 && t[1] == PARSE_T_COLON && t[3] == PARSE_T_COLON && t[5] == PARSE_T_DOT && t[6] < 0x7fff0000)
return ((t[0] * 60 + t[2]) * 60 + t[4]) * 1000 + t[6];
default:
break;
}
return -1;
}
static int parse_bool(const char *s)
{
if (_stricmp(s, "true") == 0 || _stricmp(s, "1") == 0) {
return 1;
}
else if (_stricmp(s, "false") == 0 || _stricmp(s, "0") == 0) {
return 0;
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse bool failed! s : %s", s);
}
return -1;
}
}
static int parse_log_type(const char *s)
{
static const char *keys[] = {"Log_Ignore", "Log_Event", "Log_Warning", "Log_Error", "Log_Debug"};
int i;
for (i = 0; i < array_size(keys); ++i) {
if (_stricmp(s, keys[i]) == 0)
return i;
}
return -1;
}
static int parse_ent_id(evt_engine_t *engine, const char *s)
{
// get entity devel id
return engine->cb.get_entity_id(engine, s, engine->cb.user_data);
}
static int parse_severity(const char *s)
{
static const struct {
char *key;
int level;
} ts[] = {
{"Severity_None", 0},
{"Severity_Low", 1},
{"Severity_Middle", 2},
{"Severity_High", 3},
{"0", 0},
{"1", 1},
{"2", 2},
{"3", 3},
};
for (int i = 0; i < array_size(ts); ++i) {
if (_stricmp(s, ts[i].key) == 0) {
return ts[i].level;
}
}
return -1;
}
#define DEF_CODE(x) {#x, x},
static int parse_sys_code(const char *s)
{
static const struct {
const char *code;
int code_value;
}keys[] = {
DEF_CODE(Error_Succeed)
DEF_CODE(Error_DataCheck)
DEF_CODE(Error_Null)
DEF_CODE(Error_Param)
DEF_CODE(Error_Overflow)
DEF_CODE(Error_TooSmallBuffer)
DEF_CODE(Error_NotIntegrated)
DEF_CODE(Error_TargetBeing)
DEF_CODE(Error_NoTarget)
DEF_CODE(Error_NoDefine)
DEF_CODE(Error_NotImpl)
DEF_CODE(Error_NotExist)
DEF_CODE(Error_Duplication)
DEF_CODE(Error_Unregisted)
DEF_CODE(Error_AlreadyExist)
DEF_CODE(Error_MethodNotFound)
DEF_CODE(Error_Redirect)
DEF_CODE(Error_InvalidState)
DEF_CODE(Error_NotInit)
DEF_CODE(Error_Paused)
DEF_CODE(Error_Stoped)
DEF_CODE(Error_Losted)
DEF_CODE(Error_Closed)
DEF_CODE(Error_TaskControl)
DEF_CODE(Error_Pending)
DEF_CODE(Error_Cancel)
DEF_CODE(Error_Break)
DEF_CODE(Error_NotMeetCondition)
DEF_CODE(Error_NoPrivilege)
DEF_CODE(Error_MethodSignatureFailed)
DEF_CODE(Error_PeerAction)
DEF_CODE(Error_PeerClose)
DEF_CODE(Error_PeerIgnore)
DEF_CODE(Error_PeerReject)
DEF_CODE(Error_PeerDelay)
DEF_CODE(Error_Process)
DEF_CODE(Error_NetBroken)
DEF_CODE(Error_UpdateFailed)
DEF_CODE(Error_RegistryFailed)
DEF_CODE(Error_IO)
DEF_CODE(Error_Readonly)
DEF_CODE(Error_TimeOut)
DEF_CODE(Error_BlockTimeOut)
DEF_CODE(Error_ThreadTimeOut)
DEF_CODE(Error_QueueTimeOut)
DEF_CODE(Error_ReplyTimeOut)
DEF_CODE(Error_Hardware)
DEF_CODE(Error_DevLoadFileFailed)
DEF_CODE(Error_DevNotAvailable)
DEF_CODE(Error_DevAlreadyConnected)
DEF_CODE(Error_DevConnFailed)
DEF_CODE(Error_DevCommFailed)
DEF_CODE(Error_DevMedia)
DEF_CODE(Error_Debug)
DEF_CODE(Error_Assert)
DEF_CODE(Error_Trace)
DEF_CODE(Error_Bug)
DEF_CODE(Error_Unrecover)
DEF_CODE(Error_Resource)
DEF_CODE(Error_NewProcess)
DEF_CODE(Error_FailVerify)
DEF_CODE(Error_Block)
DEF_CODE(Error_Exception)
DEF_CODE(Error_Unexpect)
};
if (s) {
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
char *p;
return (int)strtol(&s[2], &p, 16);
} else if (s[0] <= '9' && s[0] >= '1') {
return atoi(s);
} else {
int i;
for (i = 0; i < array_size(keys); ++i) {
if (_stricmp(s, keys[i].code) == 0) {
return keys[i].code_value;
}
}
}
}
return -1;
}
static int parse_usr_code(const char *s)
{
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
char *p;
return (int)strtol(&s[2], &p, 16);
}
else if (s[0] <= '9' && s[0] >= '1') {
return atoi(s);
}
else {
return -1;
}
}
static char *parse_code(const char *ns, const char *s)
{
if (strchr(s, '.')) {
return toolkit_strdup(s);
}
else {
return strdup_printf("%s.%s", ns, s);
}
}
static int extract_filter_element(evt_engine_t* engine, rvc_slotfilter_t* filter_elem, int* p_log_type, int* p_ent_id, const char** p_entity, int* p_severity, int* p_sys_code, int* p_usr_code, const char** p_slotvar)
{
int log_type, ent_id, severity, sys_code, usr_code;
const char* entity = NULL;
const char* slotvar = NULL;
if (filter_elem->strLogType) {
log_type = parse_log_type(filter_elem->strLogType);
if (log_type == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse log type failed!");
}
return Error_Unexpect;
}
}
else {
log_type = Log_Ignore;
}
if (filter_elem->strEntity) {
ent_id = parse_ent_id(engine, filter_elem->strEntity);
if (ent_id == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse entity id failed!");
}
return Error_Unexpect;
}
else {
entity = filter_elem->strEntity;
}
}
else {
ent_id = -1;
}
if (filter_elem->strSeverityLevel) {
severity = parse_severity(filter_elem->strSeverityLevel);
if (severity == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse severity level failed!");
}
return Error_Unexpect;
}
}
else {
severity = Severity_None;
}
if (filter_elem->strSysError) {
sys_code = parse_sys_code(filter_elem->strSysError);
if (sys_code == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse sys code failed! sys_code: %s", filter_elem->strSysError);
}
return Error_Unexpect;
}
}
else {
sys_code = Error_IgnoreAll;
}
if (filter_elem->strUserCode) {
usr_code = parse_usr_code(filter_elem->strUserCode);
}
else {
usr_code = -2;
}
if (filter_elem->strContentToVar) {
slotvar = filter_elem->strContentToVar;
}
else {
slotvar = NULL;
}
if (!(filter_elem->strLogType || filter_elem->strEntity || filter_elem->strSeverityLevel || filter_elem->strSysError || filter_elem->strUserCode || filter_elem->strContentToVar)){
return Error_Null;
}
*p_log_type = log_type;
*p_ent_id = ent_id;
*p_severity = severity;
*p_sys_code = sys_code;
*p_usr_code = usr_code;
*p_entity = entity;
*p_slotvar = slotvar;
return 0;
}
static int extract_filter(evt_engine_t *engine, scew_element *filter_elem, int *p_log_type, int *p_ent_id, const char **p_entity, int *p_severity, int *p_sys_code, int *p_usr_code, const char **p_slotvar)
{
int log_type, ent_id, severity, sys_code, usr_code;
const char *entity = NULL;
const char *slotvar = NULL;
scew_attribute *attr;
attr = scew_element_attribute_by_name(filter_elem, "LogType");
if (attr) {
log_type = parse_log_type(scew_attribute_value(attr));
if (log_type == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse log type failed!");
}
return Error_Unexpect;
}
}
else {
log_type = Log_Ignore;
}
attr = scew_element_attribute_by_name(filter_elem, "Entity");
if (attr) {
ent_id = parse_ent_id(engine, scew_attribute_value(attr));
if (ent_id == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse entity id failed!");
}
return Error_Unexpect;
}
else {
entity = scew_attribute_value(attr);
}
}
else {
ent_id = -1;
}
attr = scew_element_attribute_by_name(filter_elem, "SeverityLevel");
if (attr) {
severity = parse_severity(scew_attribute_value(attr));
if (severity == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse severity level failed!");
}
return Error_Unexpect;
}
}
else {
severity = Severity_None;
}
attr = scew_element_attribute_by_name(filter_elem, "SysError");
if (attr) {
sys_code = parse_sys_code(scew_attribute_value(attr));
if (sys_code == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse sys code failed! sys_code: %s", scew_attribute_value(attr));
}
return Error_Unexpect;
}
}
else {
sys_code = Error_IgnoreAll;
}
attr = scew_element_attribute_by_name(filter_elem, "UserCode");
if (attr) {
usr_code = parse_usr_code(scew_attribute_value(attr));
}
else {
usr_code = -2;
}
attr = scew_element_attribute_by_name(filter_elem, "ContentToVar");
if (attr) {
slotvar = scew_attribute_value(attr);
}
else {
slotvar = NULL;
}
*p_log_type = log_type;
*p_ent_id = ent_id;
*p_severity = severity;
*p_sys_code = sys_code;
*p_usr_code = usr_code;
*p_entity = entity;
*p_slotvar = slotvar;
return 0;
}
static int load_filter_element(evt_engine_t* engine, evt_slot_t* slot, rvc_slotfilter_t* filter_elem)
{
evt_filter_t* filter = ZALLOC_T(evt_filter_t);
const char* entity = NULL;
const char* slotvar = NULL;
int rc = extract_filter_element(engine, filter_elem, &filter->log_type, &filter->ent_id, (const char**)&entity, &filter->severity, &filter->sys_code, &filter->user_code, &slotvar);
if (rc != 0) {
return rc;
}
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("filter->log_type = %d, filter->ent_id = %d, entity = %s, filter->severity = %d, filter->sys_code = %d, filter->user_code = 0x%08x, slotvar = %s.", filter->log_type, filter->ent_id, entity, filter->severity, filter->sys_code, filter->user_code, slotvar);
if (slotvar) {
int i;
for (i = 0; i < slot->arr_slotvar->nelts; ++i) {
evt_slotvar_t* var = ARRAY_IDX(slot->arr_slotvar, i, evt_slotvar_t*);
if (_stricmp(var->name, slotvar) == 0) {
filter->content_to_var = var;
break;
}
}
if (!filter->content_to_var) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("cannot find %s slotvar!", slotvar);
}
return -1;
}
}
filter->entity = entity ? _strdup(entity) : NULL;
filter->key.listen_id = 0;
filter->owner = slot;
ARRAY_PUSH(slot->arr_filter, evt_filter_t*) = filter;
return 0;
}
static int load_filter(evt_engine_t *engine, evt_slot_t *slot, scew_element *filter_elem)
{
evt_filter_t *filter = ZALLOC_T(evt_filter_t);
const char *entity = NULL;
const char *slotvar = NULL;
int rc = extract_filter(engine, filter_elem, &filter->log_type, &filter->ent_id, (const char**)&entity, &filter->severity, &filter->sys_code, &filter->user_code, &slotvar);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("extract filter failed!");
}
return rc;
}
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("filter->log_type = %d, filter->ent_id = %d, entity = %s, filter->severity = %d, filter->sys_code = %d, filter->user_code = 0x%08x, slotvar = %s.", filter->log_type, filter->ent_id, entity, filter->severity, filter->sys_code, filter->user_code, slotvar);
if (slotvar) {
int i;
for (i = 0; i < slot->arr_slotvar->nelts; ++i) {
evt_slotvar_t *var = ARRAY_IDX(slot->arr_slotvar, i, evt_slotvar_t *);
if (_stricmp(var->name, slotvar) == 0) {
filter->content_to_var = var;
break;
}
}
if (!filter->content_to_var) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("cannot find %s slotvar!", slotvar);
}
return -1;
}
}
filter->entity = entity ? _strdup(entity) : NULL;
filter->key.listen_id = 0;
filter->owner = slot;
ARRAY_PUSH(slot->arr_filter, evt_filter_t*) = filter;
return 0;
}
static int load_slotvar(evt_engine_t *engine, evt_slot_t *slot, scew_element *slotvar_elem)
{
evt_slotvar_t *slotvar = ZALLOC_T(evt_slotvar_t);
scew_attribute *attr;
attr = scew_element_attribute_by_name(slotvar_elem, "Name");
if (attr) {
slotvar->name = _strdup(scew_attribute_value(attr));
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("not found slot var Name property!");
}
return -1;
}
attr = scew_element_attribute_by_name(slotvar_elem, "Value");
if (attr) {
slotvar->init_value = _strdup(scew_attribute_value(attr));
slotvar->current_value = _strdup(slotvar->init_value);
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("not found slot var Value property!");
}
return -1;
}
ARRAY_PUSH(slot->arr_slotvar, evt_slotvar_t*) = slotvar;
return 0;
}
static int load_slotvar_element(evt_engine_t* engine, evt_slot_t* slot, rvc_slotvar_t* slotvar_elem)
{
evt_slotvar_t* slotvar = ZALLOC_T(evt_slotvar_t);
if (slotvar_elem->strName) {
slotvar->name = _strdup(slotvar_elem->strName);
}
else {
return -1;
}
if (slotvar_elem->strValue) {
slotvar->init_value = _strdup(slotvar_elem->strValue);
slotvar->current_value = _strdup(slotvar->init_value);
}
else {
return -1;
}
ARRAY_PUSH(slot->arr_slotvar, evt_slotvar_t*) = slotvar;
return 0;
}
static int load_slot_arrays(evt_engine_t* engine, const char* ns, rvc_slot_t* tnode)
{
evt_slot_t* slot = ZALLOC_T(evt_slot_t);
if (!slot) {
return Error_Resource;
}
INIT_HLIST_NODE(&slot->hentry);
slot->arr_filter = array_make(-1, sizeof(evt_filter_t*));
slot->arr_reset = array_make(-1, sizeof(char*));
slot->arr_rref_reset = array_make(-1, sizeof(evt_slot_t*));
slot->arr_ref_reset = array_make(-1, sizeof(evt_slot_t*));
slot->arr_ref_trigger = array_make(-1, sizeof(evt_trigger_t*));
slot->arr_slotvar = array_make(-1, sizeof(evt_slotvar_t*));
slot->parent = engine;
char* code = NULL;
if (!tnode->strCode) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("slot miss attribute code!");
}
goto on_error;
}
else {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("tnode->strCode == %s.", tnode->strCode);
code = parse_code(ns, tnode->strCode);
if (!code) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse code failed!");
}
goto on_error;
}
else {
slot->key.code = code;
slot->key.index_hash_code = hash32_str(code, HASH32_STR_INIT);
}
}
if (tnode->strTimeout) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("tnode->strTimeout == %s.", tnode->strTimeout);
evt_expire_t* expire = ZALLOC_T(evt_expire_t);
if (!expire) {
goto on_error;
}
expire->timeout = parse_timeout_value(tnode->strTimeout);
if (expire->timeout < 0) {
FREE(expire);
goto on_error;
}
if (expire->timeout == 0) {
FREE(expire);
}
else {
expire->parent = slot;
expire->timer_id = 0;
slot->timer = expire;
}
}
if (tnode->strOneTrigger) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("tnode->strOneTrigger == %s.", tnode->strOneTrigger);
slot->once = parse_bool(tnode->strOneTrigger);
}
else {
slot->once = 0;
}
int vars_arr_length = sizeof(tnode->Vars) / sizeof(rvc_slotvar_t);
if (vars_arr_length > 0) {
for (int ivar = 0; ivar < vars_arr_length; ivar++) {
int rc = load_slotvar_element(engine, slot, &tnode->Vars[ivar]);
if (rc != 0) {
break;
}
else {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("slot var name is %s, value is %s.", tnode->Vars[ivar].strName, tnode->Vars[ivar].strValue);
}
}
}
int filters_arr_length = sizeof(tnode->Filters) / sizeof(rvc_slotfilter_t);
if (filters_arr_length > 0) {
for (int ifilter = 0; ifilter < filters_arr_length; ifilter++) {
int rc = load_filter_element(engine, slot, &tnode->Filters[ifilter]);
if (rc != 0) {
break;
}
}
}
int reset_arr_length = sizeof(tnode->Reset) / sizeof(rvc_slotreset_t);
if (reset_arr_length > 0) {
for (int ireset = 0; ireset < reset_arr_length; ireset++) {
if (tnode->Reset[ireset].strSource) {
char* source = parse_code(ns, tnode->Reset[ireset].strSource);
if (!source) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse code of Reset tag Source attribute failed!");
}
goto on_error;
}
else {
ARRAY_PUSH(slot->arr_reset, char*) = source;
}
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("slot var reset source is %s.", tnode->Reset[ireset].strSource);
}
else {
break;
}
}
}
if (!slot->timer) {
slot->once = 1;
}
if (slot_find(engine->slot_ht, &slot->key)) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("duplicate slot %s", slot->key.code);
}
goto on_error;
}
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->slot_ht->size = %d, engine->slot_ht count = %d.", __FUNCTION__, __LINE__, engine->slot_ht->size, htable_get_count(engine->slot_ht));
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("slot->key.code = %s, slot->key.index_hash_code = %d.", slot->key.code, slot->key.index_hash_code);
slot_add(engine->slot_ht, slot);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->slot_ht->size = %d, engine->slot_ht count = %d.", __FUNCTION__, __LINE__, engine->slot_ht->size, htable_get_count(engine->slot_ht));
return 0;
on_error:
slot_free(slot);
return Error_Unexpect;
}
static int load_slot(evt_engine_t *engine, const char *ns, scew_element *slot_elem)
{
evt_slot_t *slot = ZALLOC_T(evt_slot_t);
if (!slot){
return Error_Resource;
}
INIT_HLIST_NODE(&slot->hentry);
slot->arr_filter = array_make(-1, sizeof(evt_filter_t*));
slot->arr_reset = array_make(-1, sizeof(char*));
slot->arr_rref_reset = array_make(-1, sizeof(evt_slot_t*));
slot->arr_ref_reset = array_make(-1, sizeof(evt_slot_t*));
slot->arr_ref_trigger = array_make(-1, sizeof(evt_trigger_t*));
slot->arr_slotvar = array_make(-1, sizeof(evt_slotvar_t*));
slot->parent = engine;
char* code = NULL;
scew_list* slotval_list = NULL;
scew_list* filter_list = NULL;
scew_list* reset_list = NULL;
scew_attribute *attr = scew_element_attribute_by_name(slot_elem, "Code");
if (!attr) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("slot miss attribute code!");
}
goto on_error;
}
else {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("scew_attribute_name is %s.", scew_attribute_name(attr));
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("scew_attribute_value is %s.", scew_attribute_value(attr));
code = parse_code(ns, scew_attribute_value(attr));
if (!code) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse code failed!");
}
goto on_error;
}
else {
slot->key.code = code;
slot->key.index_hash_code = hash32_str(code, HASH32_STR_INIT);
}
}
attr = scew_element_attribute_by_name(slot_elem, "Timeout");
if (attr) {
evt_expire_t *expire = ZALLOC_T(evt_expire_t);
if (!expire){
goto on_error;
}
expire->timeout = parse_timeout_value(scew_attribute_value(attr));
if (expire->timeout < 0) {
FREE(expire);
goto on_error;
}
if (expire->timeout == 0) {
FREE(expire);
}
else {
expire->parent = slot;
expire->timer_id = 0;
slot->timer = expire;
}
}
attr = scew_element_attribute_by_name(slot_elem, "OnceTrigger");
if (attr) {
slot->once = parse_bool(scew_attribute_value(attr));
}
else {
slot->once = 0;
}
slotval_list = scew_element_list_by_name(slot_elem, "Var");
if (slotval_list) {
for (scew_list *it = scew_list_first(slotval_list); it; it = scew_list_next(it)) {
scew_element *elem = (scew_element *)scew_list_data(it);
int rc = load_slotvar(engine, slot, elem);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load slot var failed!%s", slot->key.code);
}
goto on_error;
}
}
scew_list_free(slotval_list);
}
filter_list = scew_element_list_by_name(slot_elem, "Filter");
if (filter_list) {
for (scew_list *it = scew_list_first(filter_list); it; it = scew_list_next(it)) {
scew_element *elem = (scew_element *)scew_list_data(it);
int rc = load_filter(engine, slot, elem);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load filter failed!");
}
goto on_error;
}
}
scew_list_free(filter_list);
}
reset_list = scew_element_list_by_name(slot_elem, "Reset");
if (reset_list) {
for (scew_list *it = scew_list_first(reset_list); it; it = scew_list_next(it)) {
scew_element *elem = (scew_element *)scew_list_data(it);
attr = scew_element_attribute_by_name(elem, "Source");
if (attr) {
char *source = parse_code(ns, scew_attribute_value(attr));
if (!source) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("parse code of Reset tag Source attribute failed!");
}
goto on_error;
}
else {
ARRAY_PUSH(slot->arr_reset, char*) = source;
}
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Reset tag miss source attribute!");
}
goto on_error;
}
}
scew_list_free(reset_list);
}
if (!slot->timer){
slot->once = 1;
}
if (slot_find(engine->slot_ht, &slot->key)) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("duplicate slot %s", slot->key.code);
}
goto on_error;
}
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->slot_ht->size = %d, engine->slot_ht count = %d.", __FUNCTION__, __LINE__, engine->slot_ht->size, htable_get_count(engine->slot_ht));
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("slot->key.code = %s, slot->key.index_hash_code = %d.", slot->key.code, slot->key.index_hash_code);
slot_add(engine->slot_ht, slot);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->slot_ht->size = %d, engine->slot_ht count = %d.", __FUNCTION__, __LINE__, engine->slot_ht->size, htable_get_count(engine->slot_ht));
return 0;
on_error:
slot_free(slot);
return Error_Unexpect;
}
static int load_slot_element_rule(evt_trigger_t* trigger, const char* ns, rvc_triggerslot_t* slot_elem)
{
evt_slot_rule_t* rule = ZALLOC_T(evt_slot_rule_t);
if (slot_elem->strCode) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Slot Code value is %s.", slot_elem->strCode);
rule->code = parse_code(ns, slot_elem->strCode);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("after parse_code, rule->code is %s.", rule->code);
}
else {
goto on_error;
}
if (slot_elem->strPositive) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Slot Positive value is %s.", slot_elem->strPositive);
rule->positive = parse_bool(slot_elem->strPositive);
if (rule->positive == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("slot rule parse positive attr failed!");
}
goto on_error;
}
}
else {
rule->positive = 1;
}
if (slot_elem->strMessage) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Slot Message value is %s.", slot_elem->strMessage);
rule->message = _strdup(slot_elem->strMessage);
}
rule->parent = trigger;
list_add_tail(&rule->entry, &trigger->slot_rule_list);
return 0;
on_error:
slot_rule_free(rule);
return Error_Unexpect;
}
static int load_slot_rule(evt_trigger_t *trigger, const char *ns, scew_element *slot_elem)
{
evt_slot_rule_t *rule = ZALLOC_T(evt_slot_rule_t);
scew_attribute *attr = scew_element_attribute_by_name(slot_elem, "Code");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Slot Code value is %s.", scew_attribute_value(attr));
rule->code = parse_code(ns, scew_attribute_value(attr));
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("after parse_code, rule->code is %s.", rule->code);
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("slot rule parse code attribute failed!");
}
goto on_error;
}
attr = scew_element_attribute_by_name(slot_elem, "Positive");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Slot Positive value is %s.", scew_attribute_value(attr));
rule->positive = parse_bool(scew_attribute_value(attr));
if (rule->positive == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("slot rule parse positive attr failed!");
}
goto on_error;
}
}
else {
rule->positive = 1;
}
attr = scew_element_attribute_by_name(slot_elem, "Message");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Slot Message value is %s.", scew_attribute_value(attr));
rule->message = _strdup(scew_attribute_value(attr));
}
rule->parent = trigger;
list_add_tail(&rule->entry, &trigger->slot_rule_list);
return 0;
on_error:
slot_rule_free(rule);
return Error_Unexpect;
}
static int load_sysvar_element_rule(evt_engine_t* engine, evt_trigger_t* trigger, rvc_triggersysvar_t* sysvar_elem)
{
evt_sysvar_rule_t* rule = ZALLOC_T(evt_sysvar_rule_t);
scew_list* state_list = NULL;
if (sysvar_elem->strCode) {
char* code = sysvar_elem->strCode;
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sysvar code is %s.", code);
evt_sysvar_key_t key;
key.code = code;
key.index_hash_code = hash32_str(code, HASH32_STR_INIT);
evt_sysvar_t* sysvar = sysvar_find(engine->sysvar_ht, &key);
if (!sysvar) {
sysvar = ZALLOC_T(evt_sysvar_t);
INIT_HLIST_NODE(&sysvar->hentry);
sysvar->arr_ref_rule = array_make(-1, sizeof(evt_sysvar_rule_t*));
sysvar->parent = engine;
sysvar->key.code = _strdup(code);
sysvar->key.index_hash_code = key.index_hash_code;
sysvar_add(engine->sysvar_ht, sysvar);
}
ARRAY_PUSH(sysvar->arr_ref_rule, evt_sysvar_rule_t*) = rule;
rule->ref_sysvar = sysvar;
}
else {
goto on_error;
}
if (sysvar_elem->strPositive) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sysvar Positive is %s.", sysvar_elem->strPositive);
rule->positive = parse_bool(sysvar_elem->strPositive);
}
else {
rule->positive = 1;
}
rule->parent = trigger;
rule->arr_state = array_make(0, sizeof(char*));
int states_arr_length = sizeof(sysvar_elem->strstates) / sizeof(char*);
if (states_arr_length > 0) {
for (int istate = 0; istate < states_arr_length; istate++) {
const char* state = sysvar_elem->strstates[istate];
if (state) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("add sysvar state %s.", state);
ARRAY_PUSH(rule->arr_state, char*) = _strdup(state);
}
else {
//DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sysvar state is NULL, add it.");
//ARRAY_PUSH(rule->arr_state, char*) = NULL;
break;
}
}
}
else {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger sysvar does not have state children!");
}
goto on_error;
}
list_add_tail(&rule->entry, &trigger->sysvar_list);
return 0;
on_error:
sysvar_rule_free(rule);
return Error_Unexpect;
}
static int load_sysvar_rule(evt_engine_t *engine, evt_trigger_t *trigger, scew_element *sysvar_elem)
{
evt_sysvar_rule_t *rule = ZALLOC_T(evt_sysvar_rule_t);
scew_list* state_list = NULL;
scew_attribute *attr = scew_element_attribute_by_name(sysvar_elem, "Code");
if (attr) {
char *code = (char*)scew_attribute_value(attr);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sysvar code is %s.", code);
evt_sysvar_key_t key;
key.code = code;
key.index_hash_code = hash32_str(code, HASH32_STR_INIT);
evt_sysvar_t *sysvar = sysvar_find(engine->sysvar_ht, &key);
if (!sysvar) {
sysvar = ZALLOC_T(evt_sysvar_t);
INIT_HLIST_NODE(&sysvar->hentry);
sysvar->arr_ref_rule = array_make(-1, sizeof(evt_sysvar_rule_t*));
sysvar->parent = engine;
sysvar->key.code = _strdup(code);
sysvar->key.index_hash_code = key.index_hash_code;
sysvar_add(engine->sysvar_ht, sysvar);
}
ARRAY_PUSH(sysvar->arr_ref_rule, evt_sysvar_rule_t*) = rule;
rule->ref_sysvar = sysvar;
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load sysvar rule, undefine code attr!");
}
goto on_error;
}
attr = scew_element_attribute_by_name(sysvar_elem, "Positive");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sysvar Positive is %s.", (char*)scew_attribute_value(attr));
rule->positive = parse_bool((char*)scew_attribute_value(attr));
}
else {
rule->positive = 1;
}
rule->parent = trigger;
rule->arr_state = array_make(0, sizeof(char*));
state_list = scew_element_children(sysvar_elem);
if (state_list) {
for (scew_list *it = scew_list_first(state_list); it; it = scew_list_next(it)) {
scew_element *state_elem = (scew_element *)scew_list_data(it);
const char *state = scew_element_contents(state_elem);
if (state) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("add sysvar state %s.", state);
ARRAY_PUSH(rule->arr_state, char*) = _strdup(state);
}
else {
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sysvar state is NULL, add it.");
ARRAY_PUSH(rule->arr_state, char*) = NULL;
}
}
scew_list_first(state_list);
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger sysvar does not have state children!");
}
goto on_error;
}
list_add_tail(&rule->entry, &trigger->sysvar_list);
return 0;
on_error:
sysvar_rule_free(rule);
return Error_Unexpect;
}
void SetLogType(int nIslog)
{
nIslog = nIslog;
}
static int load_trigger_arrays(evt_engine_t* engine, const char* ns, rvc_trigger_t* trigger_elem)
{
evt_trigger_t* trigger = ZALLOC_T(evt_trigger_t);
INIT_LIST_HEAD(&trigger->slot_rule_list);
INIT_LIST_HEAD(&trigger->sysvar_list);
if (trigger_elem->strLogType) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("LogType value is %s.", trigger_elem->strLogType);
trigger->log_type = parse_log_type(trigger_elem->strLogType);
if (trigger->log_type == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger log type parse failed!");
}
goto on_error;
}
}
else {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger LogType undefined!");
}
goto on_error;
}
if (trigger_elem->strSeverityLevel) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SeverityLevel value is %s.", trigger_elem->strSeverityLevel);
trigger->severity_level = parse_severity(trigger_elem->strSeverityLevel);
if (trigger->severity_level == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse severity level failed!");
}
goto on_error;
}
}
else {
if (trigger->log_type == Log_Event || trigger->log_type == Log_Error) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger LogType undefined!");
}
goto on_error;
}
}
if (trigger_elem->strSysError) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SysError value is %s.", trigger_elem->strSysError);
trigger->sys_code = parse_sys_code(trigger_elem->strSysError);
if (trigger->sys_code == -1) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse sys code failed! sys_code: %s", trigger_elem->strSysError);
}
goto on_error;
}
}
else {
if (trigger->log_type == Log_Error || trigger->log_type == Log_Warning) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse sys code undefined!");
}
goto on_error;
}
}
if (trigger_elem->strUserCode) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("UserCode value is %s.", trigger_elem->strUserCode);
trigger->user_code = parse_usr_code(trigger_elem->strUserCode);
}
else {
if (trigger->log_type == Log_Event || trigger->log_type == Log_Error || trigger->log_type == Log_Warning) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse user code undefined!");
}
goto on_error;
}
}
if (trigger_elem->strMessage) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Message value is %s.", trigger_elem->strMessage);
trigger->msg = _strdup(trigger_elem->strMessage);
}
int slots_arr_length = sizeof(trigger_elem->Slots) / sizeof(rvc_triggerslot_t);
if (slots_arr_length > 0) {
for (int islot = 0; islot < slots_arr_length; islot++) {
int rc = load_slot_element_rule(trigger, ns, &trigger_elem->Slots[islot]);
if (rc != 0) {
break;
}
}
}
int sysvars_arr_length = sizeof(trigger_elem->SysVars) / sizeof(rvc_triggersysvar_t);
if (sysvars_arr_length > 0) {
for (int isysvar = 0; isysvar < sysvars_arr_length; isysvar++) {
int rc = load_sysvar_element_rule(engine, trigger, &trigger_elem->SysVars[isysvar]);
if (rc != 0) {
break;
}
}
}
if (trigger_elem->strDelayer) {
trigger->delay_ms = parse_timeout_value(trigger_elem->strDelayer);
trigger->delay_timer_id = -1;
}
else {
trigger->delay_ms = 0;
trigger->delay_timer_id = -1;
}
trigger->parent = engine;
list_add_tail(&trigger->entry, &engine->trigger_list);
return 0;
on_error:
trigger_free(trigger);
return Error_Unexpect;
}
static int load_trigger(evt_engine_t *engine, const char *ns, scew_element *trigger_elem)
{
evt_trigger_t *trigger = ZALLOC_T(evt_trigger_t);
scew_attribute *attr;
scew_list *slot_list, *sysvar_list;
scew_element *delayer;
INIT_LIST_HEAD(&trigger->slot_rule_list);
INIT_LIST_HEAD(&trigger->sysvar_list);
attr = scew_element_attribute_by_name(trigger_elem, "LogType");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("LogType value is %s.", scew_attribute_value(attr));
trigger->log_type = parse_log_type(scew_attribute_value(attr));
if (trigger->log_type == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger log type parse failed!");
}
goto on_error;
}
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger LogType undefined!");
}
goto on_error;
}
attr = scew_element_attribute_by_name(trigger_elem, "SeverityLevel");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SeverityLevel value is %s.", scew_attribute_value(attr));
trigger->severity_level = parse_severity(scew_attribute_value(attr));
if (trigger->severity_level == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse severity level failed!");
}
goto on_error;
}
}
else {
if (trigger->log_type == Log_Event || trigger->log_type == Log_Error) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger LogType undefined!");
}
goto on_error;
}
}
attr = scew_element_attribute_by_name(trigger_elem, "SysError");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("SysError value is %s.", scew_attribute_value(attr));
trigger->sys_code = parse_sys_code(scew_attribute_value(attr));
if (trigger->sys_code == -1) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse sys code failed! sys_code: %s", scew_attribute_value(attr));
}
goto on_error;
}
}
else {
if (trigger->log_type == Log_Error || trigger->log_type == Log_Warning) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse sys code undefined!");
}
goto on_error;
}
}
attr = scew_element_attribute_by_name(trigger_elem, "UserCode");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("UserCode value is %s.", scew_attribute_value(attr));
trigger->user_code = parse_usr_code(scew_attribute_value(attr));
}
else {
if (trigger->log_type == Log_Event || trigger->log_type == Log_Error || trigger->log_type == Log_Warning) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("trigger parse user code undefined!");
}
goto on_error;
}
}
attr = scew_element_attribute_by_name(trigger_elem, "Message");
if (attr) {
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Message value is %s.", scew_attribute_value(attr));
trigger->msg = _strdup(scew_attribute_value(attr));
}
slot_list = scew_element_list_by_name(trigger_elem, "Slot");
if (slot_list) {
for (scew_list *it = scew_list_first(slot_list); it; it = scew_list_next(it)) {
scew_element *slot_elem = (scew_element*)scew_list_data(it);
int rc = load_slot_rule(trigger, ns, slot_elem);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load slot rule failed!");
}
scew_list_free(slot_list);
goto on_error;
}
}
scew_list_free(slot_list);
}
sysvar_list = scew_element_list_by_name(trigger_elem, "SysVar");
if (sysvar_list) {
for (scew_list *it = scew_list_first(sysvar_list); it; it = scew_list_next(it)) {
scew_element *sysvar_elem = (scew_element*)scew_list_data(it);
int rc = load_sysvar_rule(engine, trigger, sysvar_elem);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load sysvar rule failed!");
}
scew_list_free(sysvar_list);
goto on_error;
}
}
scew_list_free(sysvar_list);
}
delayer = scew_element_by_name(trigger_elem, "Delayer");
if (delayer) {
trigger->delay_ms = parse_timeout_value(scew_element_contents(delayer));
trigger->delay_timer_id = -1;
}
else {
trigger->delay_ms = 0;
trigger->delay_timer_id = -1;
}
trigger->parent = engine;
list_add_tail(&trigger->entry, &engine->trigger_list);
return 0;
on_error:
trigger_free(trigger);
return Error_Unexpect;
}
static int load_file(evt_engine_t *engine, const char *filename)
{
scew_reader *reader = NULL;
scew_parser *parser = NULL;
scew_tree *tree = NULL;
scew_element *root;
const char *ns;
char tmp_ns[MAX_PATH];
int rc = Error_Param;
scew_attribute* attr = NULL;
scew_element* elem = NULL;
reader = scew_reader_file_create(filename);
if (!reader) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("open file %s failed!", filename);
}
goto on_error;
}
parser = scew_parser_create();
tree = scew_parser_load(parser, reader);
if (!tree) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("read file %s failed! parser xml failed", filename);
}
goto on_error;
}
root = scew_tree_root(tree);
if (!root) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("%s file does not have root element!", filename);
}
goto on_error;
}
attr = scew_element_attribute_by_name(root, "xmlns");
if (attr) {
ns = (const char*)scew_attribute_value(attr);
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("scew_element_attribute_by_name xmlns success, ns is %s.", ns);
}
else {
const char *s = strrchr(filename, SPLIT_SLASH)+1;
const char *e = strrchr(filename, '.');
memcpy(tmp_ns, s, e-s);
tmp_ns[e-s] = 0;
ns = tmp_ns;
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("scew_element_attribute_by_name xmlns failed, ns is %s.", ns);
}
elem = scew_element_by_name(root, "SlotList");
if (elem) {
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("element SlotList contents is %s.", scew_element_contents(elem));
scew_list *slot_list = scew_element_children(elem);
if (slot_list) {
for (scew_list *it = scew_list_first(slot_list); it; it = scew_list_next(it)) {
scew_element *slot_elem = (scew_element *)scew_list_data(it);
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("slot_elem element name is %s, count is %d.", scew_element_name(slot_elem), scew_element_count(slot_elem));
if (load_slot(engine, ns, slot_elem) != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load slot failed!");
}
goto on_error;
}
}
}
}
elem = scew_element_by_name(root, "TriggerList");
if (elem) {
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("element TriggerList contents is %s.", scew_element_contents(elem));
scew_list *trigger_list = scew_element_children(elem);
if (trigger_list) {
for (scew_list *it = scew_list_first(trigger_list); it; it = scew_list_next(it)) {
scew_element *trigger_elem = (scew_element*)scew_list_data(it);
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("the number of children of %s is %d.", scew_element_name(trigger_elem), scew_element_count(trigger_elem));
if (load_trigger(engine, ns, trigger_elem) != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load trigger failed!");
}
goto on_error;
}
}
}
}
rc = 0;
on_error:
if (tree) {
scew_tree_free(tree);
}
if (parser) {
scew_parser_free(parser);
}
if (reader) {
scew_reader_close(reader);
}
return rc;
}
static int load_strategy_array(evt_engine_t* engine, slot_trigger_elem_t* pelement)
{
const char* ns = pelement->slotns;
int rc = Error_Param;
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ns = %s.", pelement->slotns);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sizeof(pelement->slotarr) = %d.", sizeof(pelement->slotarr));
for (int islot = 0; islot < sizeof(pelement->slotarr) / sizeof(rvc_slot_t); islot++) {
if (load_slot_arrays(engine, ns, &pelement->slotarr[islot]) != 0) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load slot array failed!");
}
return rc;
}
}
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sizeof(pelement->triggerarr) = %d.", sizeof(pelement->triggerarr));
for (int itrigger = 0; itrigger < sizeof(pelement->triggerarr) / sizeof(rvc_trigger_t); itrigger++) {
if (load_trigger_arrays(engine, ns, &pelement->triggerarr[itrigger]) != 0) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load trigger array failed!");
}
return rc;
}
}
rc = 0;
return rc;
}
int evt_engine_create(const evt_engine_callback_t *callback, evt_engine_t **p_engine)
{
evt_engine_t *engine = MALLOC_T(evt_engine_t);
engine->filter_ht = htable_create(0);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->filter_ht->size = %d.", __FUNCTION__, __LINE__, engine->filter_ht->size);
engine->sysvar_ht = htable_create(0);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->sysvar_ht->size = %d.", __FUNCTION__, __LINE__, engine->sysvar_ht->size);
engine->slot_ht = htable_create(0);
DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d engine->slot_ht->size = %d.", __FUNCTION__, __LINE__, engine->slot_ht->size);
INIT_LIST_HEAD(&engine->trigger_list);
spinlock_init(&engine->lock);
memcpy(&engine->cb, callback, sizeof(evt_engine_callback_t));
*p_engine = engine;
return 0;
}
void evt_engine_destroy(evt_engine_t *engine)
{
assert(engine->filter_ht->count == 0);
assert(engine->slot_ht->count == 0);
assert(engine->sysvar_ht->count == 0);
htable_destroy(engine->filter_ht);
htable_destroy(engine->slot_ht);
htable_destroy(engine->sysvar_ht);
FREE(engine);
}
int evt_engine_load(evt_engine_t *engine, int nfile, const char **files)
{
int i;
int rc = 0;
for (i = 0; i < nfile; ++i) {
const char* filename = files[i];
assert(filename);
rc = load_file(engine, filename);
if (rc != 0) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load file %s failed!", filename);
}
return rc;
}
else {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("%s loaded!", filename);
}
}
}
rc = build_ref(engine);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("build ref failed!");
}
return rc;
}
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("build ref ok!");
}
return rc;
}
int evt_engine_load(evt_engine_t* engine, int icount, slot_trigger_elem_t* parr)
{
int rc = 0;
for (int i = 0; i < icount; ++i) {
rc = load_strategy_array(engine, &parr[i]);
if (rc != 0) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("load strategy array failed!");
}
return rc;
}
else {
if (nIslog) {
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("load strategy array success!");
}
}
}
rc = build_ref(engine);
if (rc != 0) {
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("build ref failed!");
}
return rc;
}
if (nIslog) {
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("build ref ok!");
}
return rc;
}
int evt_engine_unload(evt_engine_t *engine)
{
int i;
struct hlist_node *pos, *n;
evt_trigger_t *trigger, *tmp;
for (i = 0; i < engine->slot_ht->size; ++i) {
evt_slot_t *slot;
hlist_for_each_entry_safe(slot, pos, n, &engine->slot_ht->buckets[i], evt_slot_t, hentry) {
hlist_del(pos);
slot_free(slot);
engine->slot_ht->count--;
}
}
for (i = 0; i < engine->sysvar_ht->size; ++i) {
evt_sysvar_t *sysvar;
hlist_for_each_entry_safe(sysvar, pos, n, &engine->sysvar_ht->buckets[i], evt_sysvar_t, hentry) {
hlist_del(pos);
sysvar_free(sysvar);
engine->sysvar_ht->count--;
}
}
list_for_each_entry_safe(trigger, tmp, &engine->trigger_list, evt_trigger_t, entry) {
list_del(&trigger->entry);
trigger_free(trigger);
}
return 0;
}
int evt_engine_process_log(evt_engine_t *engine,
const CAutoArray &SubIDs,
unsigned long long nLogID,
LogTypeEnum eLogType,
SeverityLevelEnum eLevel,
DWORD dwSysError,
DWORD dwUserCode,
DWORD dwEntityId,
const char *pszEntityName,
const char *pszModuleName,
const char *pszMessage)
{
return process_log(engine, SubIDs, (int)eLogType, (int)dwEntityId, (int)eLevel, (int)dwSysError, (int)dwUserCode, pszMessage);
}
int evt_engine_process_sysvar(evt_engine_t *engine,
const char *pszKey,
const char *pszValue,
const char *pszOldValue,
const char *pszEntityName)
{
if (!pszKey){
return Error_Param;
}
evt_sysvar_key_t key;
key.code = const_cast(pszKey);
key.index_hash_code = hash32_str(pszKey, HASH32_STR_INIT);
evt_sysvar_t *sysvar = sysvar_find(engine->sysvar_ht, &key);
if (sysvar) {
return process_sysvar(engine, sysvar, pszOldValue, pszValue);
}
else {
return Error_NotExist;
}
}
int evt_engine_start(evt_engine_t *engine)
{
int i;
int rc = engine->cb.subscribe_sysevent(engine, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("subscribe sysevent failed!");
}
return rc;
}
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("subscribe sysevent ok!");
}
for (i = 0; i < engine->sysvar_ht->size; ++i) {
evt_sysvar_t *tpos;
struct hlist_node *pos;
hlist_for_each_entry(tpos, pos, &engine->sysvar_ht->buckets[i], evt_sysvar_t, hentry) {
CSimpleStringA strValue;
rc = engine->cb.get_sysevent(engine, tpos->key.code, strValue, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("get sysvar %s failed! Error = %d", tpos->key.code, rc);
}
return rc;
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get sysvar %s ok! value=%s", tpos->key.code, strValue.GetData());
}
rc = process_sysvar(engine, tpos, NULL, strValue);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("process sysvar %s failed! value = %s", tpos->key.code, strValue.GetData());
}
return rc;
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("process sysvar %s ok! key = %s, value = %s", tpos->key.code, tpos->key.code, strValue.GetData());
}
}
}
}
}
for (i = 0; i < engine->slot_ht->size; ++i) {
evt_slot_t *slot;
struct hlist_node *pos;
hlist_for_each_entry(slot, pos, &engine->slot_ht->buckets[i], evt_slot_t, hentry) {
int kk;
for (kk = 0; kk < slot->arr_filter->nelts; ++kk) {
evt_filter_t *filter = ARRAY_IDX(slot->arr_filter, kk, evt_filter_t*);
rc = engine->cb.subscribe_log(engine, &filter->key.listen_id,
(LogTypeEnum)filter->log_type, filter->entity, (SeverityLevelEnum)filter->severity, (ErrorCodeEnum)filter->sys_code, filter->user_code, filter->content_to_var ? false : true, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("subscribe log failed!");
}
return rc;
}
else {
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("subscribe log ok, id = %d", filter->key.listen_id);
}
}
filter_add(engine->filter_ht, filter);
}
}
}
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("subscribe started!");
}
return rc;
}
int evt_engine_stop(evt_engine_t *engine)
{
int rc;
int i;
for (i = 0; i < engine->slot_ht->size; ++i) {
evt_slot_t *slot;
struct hlist_node *pos;
hlist_for_each_entry(slot, pos, &engine->slot_ht->buckets[i], evt_slot_t, hentry) {
int kk;
for (kk = 0; kk < slot->arr_filter->nelts; ++kk) {
evt_filter_t *filter = ARRAY_IDX(slot->arr_filter, kk, evt_filter_t*);
rc = engine->cb.unsubscribe_log(engine, filter->key.listen_id, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("unsubscribe log failed, slot = %s, log listen_id = %s", slot->key.code, filter->key.listen_id);
}
return rc;
}
filter_remove(engine->filter_ht, filter);
}
}
}
rc = engine->cb.unsubscribe_sysevent(engine, engine->cb.user_data);
if (rc != 0) {
if (nIslog){
DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("unsubscibe sysevent failed!");
}
return rc;
}
if (nIslog){
DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("unsubscibe sysevent ok!");
}
return rc;
}