Переглянути джерело

Z991239-905 #comment feat: mod_evtconverter实体文件迁移,编译通过

陈礼鹏80274480 5 роки тому
батько
коміт
d906915234

+ 28 - 0
Module/mod_evtconverter/CMakeLists.txt

@@ -0,0 +1,28 @@
+define_moudle("eventconverter")
+
+set(${MODULE_PREFIX}_SRCS
+	evtengine.cpp
+	evtengine.h
+	mod_evtconverter.cpp
+	)
+
+set(MOD_VERSION_STRING "0.0.1-dev1")
+add_module_libraries(${MODULE_PREFIX} ${MODULE_NAME} ${MOD_VERSION_STRING})
+
+target_include_directories(${MODULE_NAME} PRIVATE
+	${ThirdPartyHeadRoot}/scew-1.1.3/scew
+	${ThirdPartyHeadRoot}/Expat-2.1.0/Source/lib
+)
+
+target_link_directories(${MODULE_NAME} PRIVATE
+	${ThirdPartyLib}
+	${CONAN_LIB_DIRS_SCEW}
+	${CONAN_LIB_DIRS_EXPAT}
+)
+
+
+# 添加实体需要依赖的其他共享库(包括系统库)
+set(${MODULE_PREFIX}_LIBS  ${MODULE_BASE_ALL_LIBS} scew expat)
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+deploy_module(${MODULE_PREFIX} ${MODULE_NAME})

+ 2 - 0
Module/mod_evtconverter/ChangeLog

@@ -0,0 +1,2 @@
+
+* 2020-9-15 实体迁移

+ 2084 - 0
Module/mod_evtconverter/evtengine.cpp

@@ -0,0 +1,2084 @@
+#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
+<?xml version="1.0" encoding="utf-8"?>
+	<Transfer xmlns="test">
+	<SlotList>
+	<Slot Code="A" Timeout="1:00" OnceTrigger="true">
+	<Filter></Filter>
+	<Reset Source="B"/>
+	<Reset Source="C"/>
+	</Slot>
+	<Slot Code="B" Timeout="" OnceTrigger="false">
+	</Slot>
+	</SlotList>
+	<TriggerList>
+	<Trigger LogType="Log_Warning" UserCode="2001" SeverityLevel="Severity_High" SysError="Error_Close" Message="">
+	<Slot Code="Test2.TestSlot1" Positive="true"/>
+	<Slot Code="TestSlot2"/>
+	<SysVar Code="RunState">
+	<State>O</State>
+	<State>M</State>
+	</SysVar>
+	<SysVar Code="NetState" Positive="false">
+	<State>D</State>
+	</SysVar>
+	</Trigger>
+	</TriggerList>
+	</Transfer>
+#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 __int64 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<CUUID> &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<CUUID> &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;
+	scew_attribute *attr = scew_element_attribute_by_name(slot_elem, "Code");
+	if (!attr) {
+				if (nIslog){Dbg("slot miss attribute code!");}
+		goto on_error;
+	} else {
+		char *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;
+	}
+	scew_list *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);
+	}
+	scew_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);
+	}
+	scew_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_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*));
+	scew_list* 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;
+
+	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;
+	}
+
+	scew_attribute *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;
+	}
+
+	scew_element *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<CUUID> &SubIDs,
+						   unsigned __int64 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<char*>(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;
+}
+
+

+ 53 - 0
Module/mod_evtconverter/evtengine.h

@@ -0,0 +1,53 @@
+#ifndef _EVT_ENGINE_H
+#define _EVT_ENGINE_H
+
+#pragma once
+
+#include "SpBase.h"
+
+typedef struct evt_engine_t evt_engine_t;
+
+typedef void (*evt_engine_timer_func)(int timer_id, void *user_data);
+
+typedef struct evt_engine_callback_t
+{
+	int (*set_timer)(evt_engine_t *engine, int timer_id, int interval, evt_engine_timer_func timer_cb, void *timer_user_data, void *user_data);
+	int (*kill_timer)(evt_engine_t *engine, int timer_id, void *user_data);
+	int (*subscribe_log)(evt_engine_t *engine, unsigned __int64 *sub_id, LogTypeEnum eLogType, const char *szEntity, SeverityLevelEnum eSeverityLevel, ErrorCodeEnum eSysError, DWORD dwUserCode, bool bIgnoreMessage, void *user_data);
+	int (*unsubscribe_log)(evt_engine_t *engine, unsigned __int64 sub_id, void *user_data);
+	int (*subscribe_sysevent)(evt_engine_t *engine, void *user_data);
+	int (*unsubscribe_sysevent)(evt_engine_t *engine, void *user_data);
+	int (*get_sysevent)(evt_engine_t *engine, const char *key, CSimpleStringA &strValue, void *user_data);
+	int (*set_sysevent)(evt_engine_t *engine, const char *key,const char *val, void *user_data);
+	int (*get_entity_id)(evt_engine_t *engine, const char *entity, void *user_data);
+	int (*new_timer_id)(evt_engine_t *engine, void *user_data);
+	void *user_data;
+}evt_engine_callback_t;
+
+int evt_engine_create(const evt_engine_callback_t *callback, evt_engine_t **p_engine);
+void evt_engine_destroy(evt_engine_t *engine);
+int evt_engine_load(evt_engine_t *engine, int nfile, const char **files);
+int evt_engine_unload(evt_engine_t *engine);
+int evt_engine_process_log(evt_engine_t *engine, 
+							const CAutoArray<CUUID> &SubIDs,
+						  unsigned __int64 nLogID, 
+						  LogTypeEnum eLogType, 
+						  SeverityLevelEnum eLevel,
+						  DWORD dwSysError, 
+						  DWORD dwUserCode,
+						  DWORD dwEntityId,
+						  const char *pszEntityName, 
+						  const char *pszModuleName, 
+						  const char *pszMessage);
+int evt_engine_process_sysvar(evt_engine_t *engine, 
+							  const char *pszKey,
+							  const char *pszValue,
+							  const char *pszOldValue,
+							  const char *pszEntityName);
+int evt_engine_start(evt_engine_t *engine);
+int evt_engine_stop(evt_engine_t *engine);
+ 
+
+void SetLogType(int nIslog);
+
+#endif // _EVT_ENGINE_H

+ 530 - 0
Module/mod_evtconverter/mod_evtconverter.cpp

@@ -0,0 +1,530 @@
+#include "stdafx.h"
+#include "SpBase.h"
+#include "evtengine.h"
+#include "..\include\EventCode.h"
+
+
+class CEventConverterEntity : public CEntityBase, public ISysVarListener, public ILogListener
+{
+public:
+	CEventConverterEntity() : m_pEngine(NULL), m_lIdSeq(0) {}
+	virtual ~CEventConverterEntity() {}
+	virtual const char *GetEntityName() const { return "EventConverter"; }
+	
+	virtual void OnPreStart(CAutoArray<CSimpleStringA> strArgs,CSmartPointer<ITransactionContext> pTransactionContext) 
+	{ 
+		ErrorCodeEnum Error = __OnStart(Error_Succeed);
+		pTransactionContext->SendAnswer(Error);
+	}
+	ErrorCodeEnum __OnStart(ErrorCodeEnum preOperationError)
+	{
+		if (m_nIslog)
+		{
+			LOG_FUNCTION();
+		}
+		//MessageBoxA(0,0,0,0);
+		m_eDeviceType = eStand2sType;  //add by chh
+		m_nIslog = 1;
+		ErrorCodeEnum Error;
+		CSimpleStringA str;
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		CSmartPointer<IConfigInfo> spConfig;
+		Error = spEntityFunction->OpenConfig(Config_Software, spConfig);
+		if (Error != Error_Succeed) {
+			LOG_TRACE("open config failed!");
+			return Error;
+		}
+		//is Pad Version
+		CSystemStaticInfo stStaticinfo;
+		CSmartPointer<IEntityFunction> spFunction = GetFunction();
+		spFunction->GetSystemStaticInfo(stStaticinfo);
+		LOG_TRACE("stStaticinfo.strMachineType = %s",stStaticinfo.strMachineType);
+		if (stricmp(stStaticinfo.strMachineType,"RVC.PAD")==0)
+		{
+			if (stricmp(stStaticinfo.strSite,"CMB.FLB")==0)
+			{
+				LOG_TRACE("the type is mobile pad");
+				m_eDeviceType = eMobilePadType;
+			}
+			else
+			{
+				LOG_TRACE("the type is pad");
+				m_eDeviceType = ePadtype;
+			}
+		}
+		else if (stricmp(stStaticinfo.strMachineType,"RVC.Desk2S")==0)
+		{
+			LOG_TRACE("the type is Desk2S");
+			m_eDeviceType = eDesk2SType;
+		}
+		else if (stricmp(stStaticinfo.strMachineType,"RPM.Stand1S")==0)
+		{
+			LOG_TRACE("the type is RPM.Stand1S");
+			m_eDeviceType = eRpm1sType;
+		}
+		else if (stricmp(stStaticinfo.strMachineType,"RVC.CardStore")==0)
+		{
+			LOG_TRACE("the type is RVC.CardStore");
+			m_eDeviceType = eCardStore;
+		}
+		else
+		{
+			LOG_TRACE("the type is standard");
+			m_eDeviceType = eStand2sType;
+		}
+
+		int num = 0;
+		CAutoArray<CSimpleStringA> ConfigFiles;
+		if ((ePadtype == m_eDeviceType)||(eMobilePadType == m_eDeviceType))
+		{
+			Error = spConfig->ReadConfigValue("padLoad", "Number", str);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("load config failed, read load.number failed!");
+				return Error;
+			}
+			num = atoi((LPCSTR)str);
+			ConfigFiles.Init(num);
+			CSimpleStringA strConfigDir;
+			Error = spEntityFunction->GetPath("CFG", strConfigDir);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("get etc directory failed!");
+				return Error;
+			}
+			for (int i = 0; i < num; ++i) {
+				char t[32];
+				_itoa(i+1, &t[0], 10);
+				Error = spConfig->ReadConfigValue("padLoad", &t[0], str);
+				if (Error != Error_Succeed) 
+				{
+					LOG_TRACE("load config failed! read num %d failed!", i+1);
+					return Error;
+				}
+				ConfigFiles[i] = CSimpleStringA::Format("%s\\%s", (LPCSTR)strConfigDir, (LPCSTR)str);
+			}
+		}
+		else if (eRpm1sType == m_eDeviceType) // add by ly
+		{
+			Error = spConfig->ReadConfigValue("Rpm1sLoad", "Number", str);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("load config failed, read rpm1sLoad.number failed!");
+				return Error;
+			}
+			num = atoi((LPCSTR)str);
+			ConfigFiles.Init(num);
+			CSimpleStringA strConfigDir;
+			Error = spEntityFunction->GetPath("CFG", strConfigDir);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("get etc directory failed!");
+				return Error;
+			}
+			for (int i = 0; i < num; ++i) {
+				char t[32];
+				_itoa(i+1, &t[0], 10);
+				Error = spConfig->ReadConfigValue("Rpm1sLoad", &t[0], str);
+				if (Error != Error_Succeed) 
+				{
+					LOG_TRACE("load config failed! read num %d failed!", i+1);
+					return Error;
+				}
+				ConfigFiles[i] = CSimpleStringA::Format("%s\\%s", (LPCSTR)strConfigDir, (LPCSTR)str);
+			}
+		}
+		else if (eDesk2SType == m_eDeviceType)
+		{
+			Error = spConfig->ReadConfigValue("Desk2SLoad", "Number", str);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("load config failed, read Desk2Sload.number failed!");
+				return Error;
+			}
+			else                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
+			{
+				LOG_TRACE("read Desk2Sload.number success!");
+			}
+			num = atoi((LPCSTR)str);
+			ConfigFiles.Init(num);
+			CSimpleStringA strConfigDir;
+			Error = spEntityFunction->GetPath("CFG", strConfigDir);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("get etc directory failed!");
+				return Error;
+			}
+			for (int i = 0; i < num; ++i) 
+			{
+				char t[32];
+				_itoa(i+1, &t[0], 10);
+				Error = spConfig->ReadConfigValue("Desk2SLoad", &t[0], str);
+				if (Error != Error_Succeed) 
+				{
+					LOG_TRACE("load config failed! read num %d failed!", i+1);
+					return Error;
+				}
+				ConfigFiles[i] = CSimpleStringA::Format("%s\\%s", (LPCSTR)strConfigDir, (LPCSTR)str);
+			}
+		}
+		else if (eCardStore == m_eDeviceType)
+		{
+			Error = spConfig->ReadConfigValue("CardStoreLoad", "Number", str);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("load config failed, read CardStoreLoad.number failed!");
+				return Error;
+			}
+			else                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
+			{
+				LOG_TRACE("read CardStoreLoad.number success!");
+			}
+			num = atoi((LPCSTR)str);
+			ConfigFiles.Init(num);
+			CSimpleStringA strConfigDir;
+			Error = spEntityFunction->GetPath("CFG", strConfigDir);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("get etc directory failed!");
+				return Error;
+			}
+			for (int i = 0; i < num; ++i) 
+			{
+				char t[32];
+				_itoa(i+1, &t[0], 10);
+				Error = spConfig->ReadConfigValue("CardStoreLoad", &t[0], str);
+				if (Error != Error_Succeed) 
+				{
+					LOG_TRACE("load config failed! read num %d failed!", i+1);
+					return Error;
+				}
+				ConfigFiles[i] = CSimpleStringA::Format("%s\\%s", (LPCSTR)strConfigDir, (LPCSTR)str);
+			}
+		}
+		else
+		{
+			Error = spConfig->ReadConfigValue("Load", "Number", str);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("load config failed, read load.number failed!");
+				return Error;
+			}
+			num = atoi((LPCSTR)str);
+			ConfigFiles.Init(num);
+			CSimpleStringA strConfigDir;
+			Error = spEntityFunction->GetPath("CFG", strConfigDir);
+			if (Error != Error_Succeed) 
+			{
+				LOG_TRACE("get etc directory failed!");
+				return Error;
+			}
+			for (int i = 0; i < num; ++i) {
+				char t[32];
+				_itoa(i+1, &t[0], 10);
+				Error = spConfig->ReadConfigValue("Load", &t[0], str);
+				if (Error != Error_Succeed) 
+				{
+					LOG_TRACE("load config failed! read num %d failed!", i+1);
+					return Error;
+				}
+				ConfigFiles[i] = CSimpleStringA::Format("%s\\%s", (LPCSTR)strConfigDir, (LPCSTR)str);
+			}
+		}
+		//is log
+		Error = spConfig->ReadConfigValue("Log", "IsLog", str);
+		if (Error != Error_Succeed) 
+		{
+			LOG_TRACE("load config failed, read Log.IsLog failed!");
+			return Error;
+		}
+		m_nIslog = atoi(str);
+		SetLogType(m_nIslog);
+		evt_engine_t *engine;
+
+		evt_engine_callback_t cb;
+		cb.get_entity_id = &__get_entity_id;
+		cb.get_sysevent = &__get_sysevent;
+		cb.kill_timer = &__kill_timer;
+		cb.new_timer_id = &__new_timer_id;
+		cb.set_sysevent = &__set_sysevent;
+		cb.set_timer = &__set_timer;
+		cb.subscribe_log = &__subscribe_log;
+		cb.subscribe_sysevent = &__subscribe_sysevent;
+		cb.unsubscribe_log = &__unsubscribe_log;
+		cb.unsubscribe_sysevent = &__unsubscribe_sysevent;
+		cb.user_data = this;
+		int rc = evt_engine_create(&cb, &engine);
+		if (rc != 0) 
+		{
+			LOG_TRACE("create engine failed!");
+			return (ErrorCodeEnum)rc;
+		}
+		if (m_nIslog)
+		{
+			LOG_TRACE("create engine ok!");
+		}
+		if (num > 0) {
+			const char **files = new const char*[num];
+			for (int i = 0; i < num; ++i)
+				files[i] = (const char*)ConfigFiles[i];
+			rc = evt_engine_load(engine, num, files);
+			delete files;
+			if (rc != 0) {
+				LOG_TRACE("load config failed!");
+				return (ErrorCodeEnum)rc;
+			}
+		}
+
+		rc = evt_engine_start(engine);
+		if (rc != 0) {
+			LOG_TRACE("start engine failed!");
+			return (ErrorCodeEnum)rc;
+		}
+
+		m_pEngine = engine;
+
+		return preOperationError;
+	}
+
+	virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext) 
+	{ 
+		ErrorCodeEnum Error = __OnClose(Error_Succeed);
+		pTransactionContext->SendAnswer(Error); 
+	}
+	ErrorCodeEnum __OnClose(ErrorCodeEnum preOperationError)
+	{
+		int rc;
+		rc = evt_engine_stop(m_pEngine);
+		if (rc != 0) {
+			LOG_TRACE("stop engine failed!");
+			return (ErrorCodeEnum)rc;
+		}
+		rc = evt_engine_unload(m_pEngine);
+		if (rc != 0) {
+			LOG_TRACE("unload engine failed!");
+			return (ErrorCodeEnum)rc;
+		}
+		evt_engine_destroy(m_pEngine);
+		m_pEngine = NULL;
+
+		return Error_Succeed;
+	}
+
+	virtual void OnSysVarEvent(const char *pszKey,const char *pszValue,const char *pszOldValue,const char *pszEntityName)
+	{
+		if (m_nIslog)
+		{
+			Dbg("process sysvar key=%s oldvalue=%s, value=%s", pszKey, pszOldValue, pszValue);
+		}
+		if (m_pEngine) 
+		{
+			int rc = evt_engine_process_sysvar(m_pEngine, pszKey, pszValue, pszOldValue, pszEntityName);
+			if (rc != 0) 
+			{
+				Dbg("process sysvar failed! Error; %d, key=%s oldvalue=%s, value=%s", rc,pszKey, pszOldValue, pszValue);
+			}
+			else
+			{
+				if (m_nIslog)
+				{
+					Dbg("process sysvar success");
+				}			
+			}
+		}
+	}
+
+	virtual void OnLog(const CAutoArray<CUUID> &SubIDs, const CUUID nLogID,const LogTypeEnum eLogType, const SeverityLevelEnum eLevel,
+		const DWORD dwSysError,const DWORD dwUserCode,const DWORD dwEntityInstanceID, const WORD wEntityDevelID, 
+		const CAutoArray<DWORD> &Param, const char *pszEntityName, const char *pszModuleName,const char *pszMessage)
+	{
+		if (m_nIslog)
+		{
+			Dbg("process eLogTpye = %d, dwUserCode = 0x%08x, %s", eLogType, dwUserCode, pszMessage);
+		}
+		if (m_pEngine) {
+			int rc = evt_engine_process_log(m_pEngine, SubIDs, nLogID, eLogType, eLevel, dwSysError, dwUserCode, wEntityDevelID, pszEntityName, pszModuleName, pszMessage);
+			if (rc != 0) {
+				Dbg("process log failed! Error: %d", rc);
+			}
+		}
+	}
+
+private:
+
+	struct CTimerWrap : public ITimerListener, public IReleasable
+	{
+		virtual ~CTimerWrap() {}
+		virtual void OnTimeout(DWORD dwTimerID)
+		{
+			(*m_pTimerCallback)((int)dwTimerID, pUserData);
+		}
+		evt_engine_timer_func m_pTimerCallback;
+		void *pUserData;
+	};
+
+	//.....
+
+	int set_timer(int timer_id, int interval, evt_engine_timer_func timer_cb, void *timer_user_data)
+	{
+		CTimerWrap *pWarp = new CTimerWrap();
+		pWarp->m_pTimerCallback = timer_cb;
+		pWarp->pUserData = timer_user_data;
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		ErrorCodeEnum Error = spEntityFunction->SetTimer((DWORD)timer_id, pWarp, (DWORD)interval);
+		if (Error != Error_Succeed) {
+			LOG_TRACE("set timer %d failed!", timer_id);
+			delete pWarp;
+		} else {
+			spEntityFunction->SetTimerData((DWORD)timer_id, pWarp);
+		}
+		return (int)Error;
+	}
+
+	int kill_timer(int timer_id)
+	{
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		CSmartPointer<IReleasable> pWarp;
+		spEntityFunction->GetTimerData((DWORD)timer_id, pWarp);
+		spEntityFunction->KillTimer((DWORD)timer_id);
+		return 0;
+	}
+
+	int subscribe_log(unsigned __int64 *sub_id, LogTypeEnum eLogType, const char *szEntity, SeverityLevelEnum eSeverityLevel, ErrorCodeEnum eSysError, DWORD dwUserCode, bool bIgnoreMessage)
+	{
+		CUUID uuid;
+		ErrorCodeEnum Error = GetFunction()->SubscribeLog(uuid, this, eLogType, eSeverityLevel, eSysError, dwUserCode, szEntity, bIgnoreMessage);
+		if (Error != Error_Succeed) {
+			LOG_TRACE("subscribe log failed! Error = %d", Error);
+		} else {
+			*sub_id = (unsigned __int64)uuid;
+			if (m_nIslog)
+			{
+				LOG_TRACE("subscribe log ok!");
+			}
+		}
+		return (int)Error;
+	}
+
+	int unsubscribe_log(unsigned __int64 sub_id)
+	{
+		ErrorCodeEnum Error = GetFunction()->UnsubscribeLog(sub_id);
+		if (Error == Error_Succeed) {
+			if (m_nIslog)
+			{
+				LOG_TRACE("unsubscribe log ok!");
+			}
+		} else {
+			LOG_TRACE("unsubscribe log failed! Error = %d", Error);
+		}
+		return (int)Error;
+	}
+
+	int subscribe_sysevent()
+	{
+		if (m_nIslog)
+		{
+			LOG_TRACE("subscribe sysevent!");
+		}
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		return (int)spEntityFunction->RegistSysVarEvent("*", this);
+	}
+
+	int unsubscribe_sysevent()
+	{
+		if (m_nIslog)
+		{
+			LOG_TRACE("unsubscribe sysevent!");
+		}
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		return (int)spEntityFunction->UnregistSysVarEvent("*");
+	}
+
+	int get_sysevent(const char *key, CSimpleStringA &strValue)
+	{
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		return (int)spEntityFunction->GetSysVar(key, strValue);
+	}
+
+	int set_sysevent(const char *key,const char *val)
+	{
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		return (int)spEntityFunction->SetSysVar(key, val);
+	}
+
+	int get_entity_id(const char *entity)
+	{
+		CEntityStaticInfo Info;
+		CSmartPointer<IEntityFunction> spEntityFunction = GetFunction();
+		ErrorCodeEnum Error = spEntityFunction->GetEntityStaticInfo(entity, Info);
+		if (Error == Error_Succeed) {
+			return (int)Info.wEntityDevelopID;
+		} else {
+			return -1; // failed
+		}
+	}
+	int new_timer_id()
+	{
+		return ++m_lIdSeq;
+	}
+
+	static int __set_timer(evt_engine_t *engine, int timer_id, int interval, evt_engine_timer_func timer_cb, void *timer_user_data, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->set_timer(timer_id, interval, timer_cb, timer_user_data);
+	}
+	static int __kill_timer(evt_engine_t *engine, int timer_id, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->kill_timer(timer_id);
+	}
+	static int __subscribe_log(evt_engine_t *engine, unsigned __int64 *sub_id, LogTypeEnum eLogType, const char *szEntity, SeverityLevelEnum eSeverityLevel, ErrorCodeEnum eSysError, DWORD dwUserCode, bool bIgnoreMessage, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->subscribe_log(sub_id, eLogType, szEntity, eSeverityLevel, eSysError, dwUserCode, bIgnoreMessage);
+	}
+	static int __unsubscribe_log(evt_engine_t *engine, unsigned __int64 sub_id, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->unsubscribe_log(sub_id);
+	}
+	static int __subscribe_sysevent(evt_engine_t *engine, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->subscribe_sysevent();
+	}
+	static int __unsubscribe_sysevent(evt_engine_t *engine, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->unsubscribe_sysevent();
+	}
+	static int __get_sysevent(evt_engine_t *engine, const char *key, CSimpleStringA &strValue, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->get_sysevent(key, strValue);
+	}
+	static int __set_sysevent(evt_engine_t *engine, const char *key,const char *val, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->set_sysevent(key, val);
+	}
+	static int __get_entity_id(evt_engine_t *engine, const char *entity, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->get_entity_id(entity);
+	}
+	static int __new_timer_id(evt_engine_t *engine, void *user_data)
+	{
+		CEventConverterEntity *pThis = static_cast<CEventConverterEntity *>(user_data);
+		return pThis->new_timer_id();
+	}
+
+private:
+	LONG m_lIdSeq;
+	evt_engine_t *m_pEngine;
+	int m_nIslog;
+	DeviceTypeEnum m_eDeviceType;  	// add by chh
+};
+
+SP_BEGIN_ENTITY_MAP()
+	SP_ENTITY(CEventConverterEntity)
+SP_END_ENTITY_MAP()