#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 "scew.h" #if 0 O M D #endif #define BIT_MASK(bit) (1 << (bit)) 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 = 0; 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 int detect_loop(); 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){Dbg("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) { Dbg("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) { Dbg("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) { Dbg("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) { Dbg("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) { Dbg("process trigger list failed!"); } return; } rc = postprocess_slot_list(engine, &affect_list); if (rc != 0) { if (nIslog) { Dbg("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) { Dbg("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) { Dbg("set timer failed! slot: %s, timer_id: %d", slot->key.code, new_id); } } } } if (removed) *removed = TRUE; } 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) { Dbg("set timer failed! slot: %s, timer_id: %d", slot->key.code, new_id); } } } if (removed) *removed = FALSE; } 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) { Dbg("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) { Dbg("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 = FALSE; 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 = TRUE; } 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) { Dbg("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) { Dbg("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) { Dbg("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) { Dbg("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) { Dbg("get sysvar failed!"); } goto on_done; } if (nIslog) { Dbg("sysvar key=%s, value=%s", pos->ref_sysvar->key.code, (LPCSTR)strState); Dbg("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) { Dbg("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) { Dbg("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) { Dbg("set timer failed!"); } } } else { rc = generate_trigger_log(engine, trigger); if (rc != 0) { if (nIslog) { Dbg("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) { Dbg("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) { Dbg("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) { Dbg("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) { Dbg("process matched slot list failed!"); } return rc; } rc = process_reset_slot_list(engine, &reset_list); if (rc != 0) { if (nIslog) { Dbg("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) { Dbg("process trigger list failed!"); } return rc; } rc = postprocess_slot_list(engine, &affect_list); if (rc != 0) { if (nIslog) { Dbg("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){Dbg("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; 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; } else { if (nIslog){Dbg("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; } else { if (nIslog){Dbg("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){Dbg("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(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){Dbg("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){Dbg("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){Dbg("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){Dbg("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(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){Dbg("extract filter failed!");} return rc; } 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) { Dbg("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){Dbg("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){Dbg("not found slot var Value property!");} return -1; } ARRAY_PUSH(slot->arr_slotvar, evt_slotvar_t*) = slotvar; return 0; } 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){Dbg("slot miss attribute code!");} goto on_error; } else { code = parse_code(ns, scew_attribute_value(attr)); if (!code) { if (nIslog){Dbg("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){Dbg("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){Dbg("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){Dbg("parse code of Reset tag Source attribute failed!");} goto on_error; } else { ARRAY_PUSH(slot->arr_reset, char*) = source; } } else { if (nIslog){Dbg("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){Dbg("duplicate slot %s", slot->key.code);} goto on_error; } slot_add(engine->slot_ht, slot); return 0; on_error: slot_free(slot); 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) { rule->code = parse_code(ns, scew_attribute_value(attr)); } else { if (nIslog){Dbg("slot rule parse code attribute failed!");} goto on_error; } attr = scew_element_attribute_by_name(slot_elem, "Positive"); if (attr) { rule->positive = parse_bool(scew_attribute_value(attr)); if (rule->positive == -1) { if (nIslog){Dbg("slot rule parse positive attr failed!");} goto on_error; } } else { rule->positive = TRUE; } attr = scew_element_attribute_by_name(slot_elem, "Message"); if (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_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); 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){Dbg("load sysvar rule, undefine code attr!");} goto on_error; } attr = scew_element_attribute_by_name(sysvar_elem, "Positive"); if (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) { ARRAY_PUSH(rule->arr_state, char*) = _strdup(state); } else { ARRAY_PUSH(rule->arr_state, char*) = NULL; } } scew_list_first(state_list); } else { if (nIslog){Dbg("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(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) { trigger->log_type = parse_log_type(scew_attribute_value(attr)); if (trigger->log_type == -1) { if (nIslog){Dbg("trigger log type parse failed!");} goto on_error; } } else { if (nIslog){Dbg("trigger LogType undefined!");} goto on_error; } attr = scew_element_attribute_by_name(trigger_elem, "SeverityLevel"); if (attr) { trigger->severity_level = parse_severity(scew_attribute_value(attr)); if (trigger->severity_level == -1) { if (nIslog){Dbg("trigger parse severity level failed!");} goto on_error; } } else { if (trigger->log_type == Log_Event || trigger->log_type == Log_Error) { if (nIslog){Dbg("trigger LogType undefined!");} goto on_error; } } attr = scew_element_attribute_by_name(trigger_elem, "SysError"); if (attr) { trigger->sys_code = parse_sys_code(scew_attribute_value(attr)); if (trigger->sys_code == -1) { if (nIslog){Dbg("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){Dbg("trigger parse sys code undefined!");} goto on_error; } } attr = scew_element_attribute_by_name(trigger_elem, "UserCode"); if (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){Dbg("trigger parse user code undefined!");} goto on_error; } } attr = scew_element_attribute_by_name(trigger_elem, "Message"); if (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){Dbg("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){Dbg("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){Dbg("open file %s failed!", filename);} goto on_error; } parser = scew_parser_create(); tree = scew_parser_load(parser, reader); if (!tree) { if (nIslog){Dbg("read file %s failed! parser xml failed", filename);} goto on_error; } root = scew_tree_root(tree); if (!root) { if (nIslog){Dbg("%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); } else { const char *s = strrchr(filename, '\\')+1; const char *e = strrchr(filename, '.'); memcpy(tmp_ns, s, e-s); tmp_ns[e-s] = 0; ns = tmp_ns; } elem = scew_element_by_name(root, "SlotList"); if (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); if (load_slot(engine, ns, slot_elem) != 0) { if (nIslog){Dbg("load slot failed!");} goto on_error; } } } } elem = scew_element_by_name(root, "TriggerList"); if (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); if (load_trigger(engine, ns, trigger_elem) != 0) { if (nIslog){Dbg("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; } 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); engine->sysvar_ht = htable_create(0); engine->slot_ht = htable_create(0); 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){Dbg("Load file %s failed!", filename);} return rc; } else { if (nIslog){Dbg("%s loaded!", filename);} } } rc = build_ref(engine); if (rc != 0) { if (nIslog){Dbg("build ref failed!");} return rc; } if (nIslog){Dbg("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; rc = engine->cb.subscribe_sysevent(engine, engine->cb.user_data); if (rc != 0) { if (nIslog){Dbg("subscribe sysevent failed!");} return rc; } if (nIslog){Dbg("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){Dbg("get sysvar %s failed! Error = %d", tpos->key.code, rc);} return rc; } else { if (nIslog){Dbg("get sysvar %s ok! value=%s", tpos->key.code, (LPCSTR)strValue);} rc = process_sysvar(engine, tpos, NULL, strValue); if (rc != 0) { if (nIslog){Dbg("process sysvar %s failed! value = %s", tpos->key.code, (LPCSTR)strValue);} return rc; } else { if (nIslog){Dbg("process sysvar %s ok! key = %s, value = %s", tpos->key.code, tpos->key.code, (LPCSTR)strValue);} } } } } 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){Dbg("subscribe log failed!");} return rc; } else { if (nIslog){Dbg("subscribe log ok, id = %d", filter->key.listen_id);} } filter_add(engine->filter_ht, filter); } } } if (nIslog){Dbg("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){Dbg("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){Dbg("unsubscibe sysevent failed!");} return rc; } if (nIslog){Dbg("unsubscibe sysevent ok!");} return rc; }