From 2a9bbc3c81bd8665a6e9f089f2b5071eda13e039 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 10 Feb 2016 10:01:18 +0800 Subject: [PATCH 01/31] Add runtime statistic feature. --- inc/Maat_rule.h | 28 ++- src/entry/Maat_api.cpp | 324 +++++++++++++++++++++++++-------- src/entry/Maat_rule.cpp | 15 +- src/entry/Maat_rule_internal.h | 35 +++- src/entry/Maat_stat.cpp | 206 +++++++++++++++++++++ src/entry/Makefile | 6 +- src/inc_internal/field_stat.h | 70 +++++++ src/inc_internal/rulescan.h | 24 ++- test/maat_test.cpp | 21 ++- 9 files changed, 628 insertions(+), 101 deletions(-) create mode 100644 src/entry/Maat_stat.cpp create mode 100644 src/inc_internal/field_stat.h diff --git a/inc/Maat_rule.h b/inc/Maat_rule.h index ca0de2e..b8d3e66 100644 --- a/inc/Maat_rule.h +++ b/inc/Maat_rule.h @@ -108,17 +108,36 @@ struct Maat_hit_detail_t struct Maat_region_pos_t region_pos[MAAT_MAX_HIT_RULE_NUM]; }; //--------------------HITTING DETAIL DESCRIPTION END + +//Abondon interface ,left for compatible. Maat_feather_t Maat_summon_feather(int max_thread_num, const char* table_info_path, const char* ful_cfg_dir, const char* inc_cfg_dir, - void*logger); - + void*logger);//MESA_handle_logger +//Abondon interface ,left for compatible. Maat_feather_t Maat_summon_feather_json(int max_thread_num, const char* table_info_path, const char* json_rule, void* logger); +Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger); +int Maat_initiate_feather(Maat_feather_t feather); + +enum MAAT_INIT_OPT{ + MAAT_OPT_SCANDIR_INTERVAL_MS=1, //VALUE is interger,SIZE=sizeof(int). DEFAULT:1,000 milliseconds. + MAAT_OPT_EFFECT_INVERVAL_MS, //VALUE is interger,SIZE=sizeof(int). DEFAULT:60,000 milliseconds. + MAAT_OPT_FULL_CFG_DIR, //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_INC_CFG_DIR, //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_JSON_FILE_PATH, //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_STAT_ON, //VALUE is indifferent,SIZE is indifferent.MAAT_OPT_STAT_FILE_PATH must be set.Default: stat OFF. + MAAT_OPT_PERF_ON, //VALUE is indifferent,SIZE is indifferent.MAAT_OPT_STAT_FILE_PATH must be set.Default: stat OFF. + MAAT_OPT_STAT_FILE_PATH, //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. + MAAT_OPT_SCAN_DETAIL //VALUE is interger,SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping; + // 2 return hit pos and regex grouping pos;DEFAULT:2 +}; +//return -1 if failed, return 0 on success; +int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size); void Maat_burn_feather(Maat_feather_t feather); //return table_id(>=0) if success,otherwise return -1; @@ -179,10 +198,5 @@ void Maat_stream_scan_digest_end(stream_para_t* stream_para); void Maat_clean_status(scan_status_t* mid); -#define MAAT_OPT_SCANDIR_INTERVAL_MS 1 //opt value is interger,size=sizeof(int),1,000 milliseconds as default -#define MAAT_OPT_EFFECT_INVERVAL_MS 2 //opt value is interger,size=sizeof(int),60,000 milliseconds as default -//return -1 if failed, return 0 on success; -int Maat_set_feather_opt(Maat_feather_t feather,int type,void* value,int size); - #endif // H_MAAT_RULE_H_INCLUDE diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 1822130..d87cc88 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -1,6 +1,7 @@ #include #include #include + #include #include #include "rulescan.h" @@ -101,7 +102,6 @@ int region_compile(struct _scan_status_t *_mid,void* region_hit,int region_type_ struct _Maat_compile_rule_t* array_mi_rule[MAX_SCANNER_HIT_NUM]; struct _Maat_compile_rule_t* _mi_rule=NULL; int region_pos[MAX_SCANNER_HIT_NUM]; - _mid->cur_hit_cnt=0; for(i=0;irwlock)); - - } - + } } + if(result_cnt>0) + { + _mid->feather->hit_cnt++; + } return result_cnt; } @@ -320,6 +322,7 @@ struct _scan_status_t* _Maat_make_status(struct _Maat_feather_t* feather,int thr _mid->hit_group_cnt=0; _mid->hit_group_size=4; _mid->hitted_group_id=(unsigned int*)malloc(sizeof(unsigned int)*_mid->hit_group_size); + feather->mid_cnt++; return _mid; } @@ -350,14 +353,8 @@ int detain_last_data(char* buff,int buff_size,int detained_len,const char* data, return ret_len; } - -Maat_feather_t Maat_summon_feather(int max_thread_num, - const char* table_info_path, - const char* ful_cfg_dir, - const char* inc_cfg_dir, - void* logger) +Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger) { - _Maat_feather_t* feather=(_Maat_feather_t*)calloc(sizeof(struct _Maat_feather_t),1); feather->table_cnt=read_table_info(feather->p_table_info, MAX_TABLE_NUM,table_info_path,logger); feather->map_tablename2id=map_create(); @@ -373,65 +370,25 @@ Maat_feather_t Maat_summon_feather(int max_thread_num, map_register(feather->map_tablename2id,feather->p_table_info[i]->table_name,feather->p_table_info[i]->table_id); } } - memcpy(feather->inc_dir,inc_cfg_dir,strlen(inc_cfg_dir)); - memcpy(feather->full_dir,ful_cfg_dir,strlen(ful_cfg_dir)); feather->logger=logger; feather->scan_thread_num=max_thread_num; feather->garbage_q=MESA_lqueue_create(0,0); - config_monitor_traverse(feather->maat_version, - ful_cfg_dir, - maat_start_cb, - maat_update_cb, - maat_finish_cb, - feather, - logger); - if(feather->update_tmp_scanner==NULL) - { - MESA_handle_runtime_log(logger,RLOG_LV_FATAL,maat_module , - "At initiation: no valid index file in %s",ful_cfg_dir); - } - feather->scanner=feather->update_tmp_scanner; - feather->update_tmp_scanner=NULL; - feather->still_working=1; - if(feather->scanner!=NULL) - { - feather->maat_version=feather->scanner->version; - } feather->effect_interval_ms=60*1000; feather->scan_interval_ms=1*1000; - pthread_t cfg_mon_t; - pthread_create(&cfg_mon_t, NULL, thread_rule_monitor, (void*)feather); return feather; } -Maat_feather_t Maat_summon_feather_json(int max_thread_num, - const char* table_info_path, - const char* json_rule, - void* logger) -{ - Maat_feather_t feather; - char full_index_dir[256]={0}; - int ret=-1; - MESA_handle_runtime_log(logger,RLOG_LV_INFO,maat_module , - "Maat initial with JSON file %s.",json_rule); - - ret=json2iris(json_rule, full_index_dir,sizeof(full_index_dir),logger); - if(ret<0) - { - return NULL; - } - MESA_handle_runtime_log(logger,RLOG_LV_INFO,maat_module , - "generate index file %s OK.",full_index_dir); - feather=Maat_summon_feather(max_thread_num,table_info_path, full_index_dir, full_index_dir,logger); - return feather; -} -int Maat_set_feather_opt(Maat_feather_t feather,int type,void* value,int size) +int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size) { _Maat_feather_t* _feather=(_Maat_feather_t*)feather; - int intval=0; + int intval=0,ret=-1; + if(_feather->still_working==1)// not allowed set after Maat_initiate_feather; + { + return -2; + } switch(type) { case MAAT_OPT_EFFECT_INVERVAL_MS: - intval=*(int*)value; + intval=*(const int*)value; if(size!=sizeof(int)||intval<=0) { return -1; @@ -439,18 +396,168 @@ int Maat_set_feather_opt(Maat_feather_t feather,int type,void* value,int size) _feather->effect_interval_ms=intval; break; case MAAT_OPT_SCANDIR_INTERVAL_MS: - intval=*(int*)value; + intval=*(const int*)value; if(size!=sizeof(int)||intval<0) { return -1; } _feather->scan_interval_ms=intval; break; + case MAAT_OPT_FULL_CFG_DIR: + if(size>(int)sizeof(_feather->full_dir)) + { + return -1; + } + memcpy(_feather->full_dir,(const char*)value,size); + break; + case MAAT_OPT_INC_CFG_DIR: + if(size>(int)sizeof(_feather->inc_dir)) + { + return -1; + } + memcpy(_feather->inc_dir,(const char*)value,size); + break; + case MAAT_OPT_JSON_FILE_PATH: + ret=json2iris((const char*)value, _feather->full_dir,sizeof(_feather->full_dir),_feather->logger); + if(ret<0) + { + return -1; + } + memcpy(_feather->inc_dir,_feather->full_dir,sizeof(_feather->inc_dir)); + MESA_handle_runtime_log(_feather->logger,RLOG_LV_INFO,maat_module , + "Maat initial with JSON file %s,generate index file %s OK." + ,(const char*)value + ,_feather->full_dir); + break; + case MAAT_OPT_STAT_ON: + _feather->stat_on=1; + _feather->stat_handle=FS_create_handle(); + break; + case MAAT_OPT_PERF_ON: + _feather->perf_on=1; + break; + case MAAT_OPT_STAT_FILE_PATH: + if(size>(int)sizeof(_feather->stat_file)) + { + return -1; + } + memcpy(_feather->stat_file,(const char*)value,size); + MESA_handle_runtime_log(_feather->logger,RLOG_LV_INFO,maat_module , + "Maat performance statistic output to %s." + ,(const char*)value); + _feather->stat_on=1; + break; + case MAAT_OPT_SCAN_DETAIL: + intval=*(const int*)value; + _feather->rule_scan_type=intval; + break; default: return -1; } return 0; } +int Maat_initiate_feather(Maat_feather_t feather) +{ + _Maat_feather_t* _feather=(_Maat_feather_t*)feather; + config_monitor_traverse(_feather->maat_version, + _feather->full_dir, + maat_start_cb, + maat_update_cb, + maat_finish_cb, + _feather, + _feather->logger); + if(_feather->update_tmp_scanner==NULL) + { + MESA_handle_runtime_log(_feather->logger,RLOG_LV_FATAL,maat_module , + "At initiation: no valid index file in %s",_feather->full_dir); + } + _feather->scanner=_feather->update_tmp_scanner; + _feather->update_tmp_scanner=NULL; + _feather->still_working=1; + _feather->rule_scan_type=2; + if(_feather->scanner!=NULL) + { + _feather->maat_version=_feather->scanner->version; + } + if(strlen(_feather->stat_file)==0) + { + _feather->perf_on=0; + _feather->stat_on=0; + } + maat_stat_init(_feather); + + pthread_t cfg_mon_t; + pthread_create(&cfg_mon_t, NULL, thread_rule_monitor, (void*)_feather); + return 0; + +} + +Maat_feather_t Maat_summon_feather(int max_thread_num, + const char* table_info_path, + const char* ful_cfg_dir, + const char* inc_cfg_dir, + void* logger) +{ + int ret=-1; + Maat_feather_t feather=NULL; + feather=Maat_feather(max_thread_num,table_info_path,logger); + if(feather==NULL) + { + return NULL; + } + ret=Maat_set_feather_opt(feather, MAAT_OPT_FULL_CFG_DIR, ful_cfg_dir, strlen(ful_cfg_dir)+1); + if(ret<0) + { + goto error_out; + } + ret=Maat_set_feather_opt(feather, MAAT_OPT_FULL_CFG_DIR, inc_cfg_dir, strlen(inc_cfg_dir)+1); + if(ret<0) + { + goto error_out; + } + ret=Maat_initiate_feather(feather); + if(ret<0) + { + goto error_out; + } + return feather; + +error_out: + Maat_burn_feather(feather); + return NULL; + + +} +Maat_feather_t Maat_summon_feather_json(int max_thread_num, + const char* table_info_path, + const char* json_rule, + void* logger) +{ + int ret=-1; + Maat_feather_t feather=NULL; + feather=Maat_feather(max_thread_num,table_info_path,logger); + if(feather==NULL) + { + return NULL; + } + ret=Maat_set_feather_opt(feather, MAAT_OPT_JSON_FILE_PATH, json_rule, strlen(json_rule)+1); + if(ret<0) + { + goto error_out; + } + ret=Maat_initiate_feather(feather); + if(ret<0) + { + goto error_out; + } return feather; + +error_out: + + Maat_burn_feather(feather); + return NULL; + +} + void Maat_burn_feather(Maat_feather_t feather) { _Maat_feather_t* _feather=(_Maat_feather_t*)feather; @@ -530,8 +637,12 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num];//dynamic array - struct _Maat_table_info_t *p_table=NULL; + struct timeval start,end; + if(_feather->perf_on==1) + { + gettimeofday(&start,NULL); + } p_table=acqurie_table(_feather, table_id,TABLE_TYPE_EXPR); if(p_table==NULL) { @@ -587,6 +698,7 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id } if(hit_region_cnt>0) { + p_table->hit_cnt++; if(*mid==NULL) { _mid=_Maat_make_status(_feather,thread_num); @@ -609,6 +721,11 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id } } DEC_SCANNER_REF(my_scanner, thread_num); + if(_feather->perf_on==1) + { + gettimeofday(&end,NULL); + maat_stat_table(p_table,data_len,&start, &end); + } if(compile_ret==0&&hit_region_cnt>0) { return -2; @@ -643,6 +760,11 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id intval_scan_data.sub_type=make_sub_type(table_id,CHARSET_NONE, 0); intval_scan_data.int_data=intval; _Maat_table_info_t* p_table=NULL; + struct timeval start,end; + if(_feather->perf_on==1) + { + gettimeofday(&start,NULL); + } p_table=acqurie_table(_feather,table_id,TABLE_TYPE_INTVAL); if(p_table==NULL) { @@ -669,6 +791,7 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id } else if(region_ret>0) { + p_table->hit_cnt++; if(*mid==NULL) { _mid=_Maat_make_status(_feather,thread_num); @@ -685,6 +808,11 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id } DEC_SCANNER_REF(my_scanner,thread_num); + if(_feather->perf_on==1) + { + gettimeofday(&end,NULL); + maat_stat_table(p_table,0,&start, &end); + } if(compile_ret==0&®ion_ret>0) { return -2; @@ -707,6 +835,11 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _Maat_scanner_t* my_scanner=NULL; + struct timeval start,end; + if(_feather->perf_on==1) + { + gettimeofday(&start,NULL); + } p_table=acqurie_table(_feather, table_id, TABLE_TYPE_IP); if(p_table==NULL) { @@ -758,6 +891,7 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id } else if(region_ret>0) { + p_table->hit_cnt++; if(*mid==NULL) { _mid=_Maat_make_status(_feather,thread_num); @@ -773,7 +907,11 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id result,compile_result,rule_num); } DEC_SCANNER_REF(my_scanner,thread_num); - + if(_feather->perf_on==1) + { + gettimeofday(&end,NULL); + maat_stat_table(p_table,0,&start, &end); + } if(compile_ret==0&®ion_ret>0) { return -2; @@ -834,6 +972,7 @@ stream_para_t Maat_stream_scan_string_start(Maat_feather_t feather,int table_id, { sp->do_regex=1; } + p_table->stream_num++; sp->rs_stream_para=rulescan_startstream(_feather->scanner->region,thread_num); return sp; } @@ -852,6 +991,11 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para scan_result_t *region_result; _compile_result_t compile_result[rule_num];//dynamic array scan_data_t region_scan_data; + struct timeval start,end; + if(sp->feather->perf_on==1) + { + gettimeofday(&start,NULL); + } if(data==NULL||data_len==0) { return 0; @@ -939,6 +1083,8 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para } if(hit_region_cnt>0) { + sp->feather->p_table_info[sp->table_id]->hit_cnt++; + if(*mid==NULL) { _mid=_Maat_make_status(sp->feather,sp->thread_num); @@ -975,6 +1121,11 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para free(sp->scan_buff); sp->scan_buff=0; } + if(sp->feather->perf_on==1) + { + gettimeofday(&end,NULL); + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end); + } if(compile_ret==0&&hit_region_cnt>0) { return -2; @@ -998,7 +1149,8 @@ void Maat_stream_scan_string_end(stream_para_t* stream_para) { struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; - + struct _Maat_table_info_t * p_table=sp->feather->p_table_info[sp->table_id]; + p_table->stream_num--; if(scanner!=NULL) { if(sp->version==sp->feather->maat_version) @@ -1056,6 +1208,8 @@ stream_para_t Maat_stream_scan_digest_start(Maat_feather_t feather,int table_id, sp->total_len=total_len; sp->fuzzy_hash_handle=tmp_fuzzy_handle; pthread_mutex_init(&(sp->fuzzy_mutex),NULL); + p_table->stream_num++; + return sp; } @@ -1092,6 +1246,11 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int char* digest_buff=NULL; struct _scan_status_t* _mid=(struct _scan_status_t*)(*mid); pthread_rwlock_t *GIE_rwlock=&(sp->feather->scanner->digest_rwlock[sp->table_id]); + struct timeval start,end; + if(sp->feather->perf_on==1) + { + gettimeofday(&start,NULL); + } if(sp->acc_scan_len+(unsigned long long)data_len > sp->total_len) { return 0; @@ -1129,24 +1288,30 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int { return -1; } - if(hit_region_cnt==0) + if(hit_region_cnt>0) { - return 0; + sp->feather->p_table_info[sp->table_id]->hit_cnt++; + if(*mid==NULL) + { + _mid=_Maat_make_status(sp->feather,sp->thread_num); + *mid=_mid; + } + else + { + _mid=(struct _scan_status_t*)(*mid); + } + compile_ret=region_compile(_mid, + query_result,sizeof(GIE_result_t),offsetof(GIE_result_t, tag), + hit_region_cnt, + result,compile_result,rule_num); + + } + if(sp->feather->perf_on==1) + { + gettimeofday(&end,NULL); + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end); } - if(*mid==NULL) - { - _mid=_Maat_make_status(sp->feather,sp->thread_num); - *mid=_mid; - } - else - { - _mid=(struct _scan_status_t*)(*mid); - } - compile_ret=region_compile(_mid, - query_result,sizeof(GIE_result_t),offsetof(GIE_result_t, tag), - hit_region_cnt, - result,compile_result,rule_num); if(compile_ret==0&&hit_region_cnt>0) { return -2; @@ -1157,7 +1322,8 @@ void Maat_stream_scan_digest_end(stream_para_t* stream_para) { struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; - + struct _Maat_table_info_t * p_table=sp->feather->p_table_info[sp->table_id]; + p_table->stream_num--; if(scanner!=NULL) { if(sp->version==sp->feather->maat_version) @@ -1171,6 +1337,7 @@ void Maat_stream_scan_digest_end(stream_para_t* stream_para) assert(sp->scan_buff==NULL); free(sp); *stream_para=NULL; + return; } void Maat_clean_status(scan_status_t* mid) @@ -1181,6 +1348,7 @@ void Maat_clean_status(scan_status_t* mid) return; } _mid=(struct _scan_status_t*)(*mid); + _mid->feather->mid_cnt--; free(_mid->hitted_group_id); free(_mid); *mid=NULL; diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 5a5585f..d47debd 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "Maat_rule.h" #include "Maat_rule_internal.h" @@ -24,11 +25,10 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_3_20151224=1; +int MAAT_FRAME_VERSION_1_4_20160210=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"CHARSET_NONE","GBK","BIG5","UNICODE","UTF-8"}; - int converHextoint(char srctmp) { if(isdigit(srctmp)) @@ -673,7 +673,7 @@ void destroy_digest_rule(GIE_digest_t*rule) rule=NULL; return; } -struct _Maat_scanner_t* create_maat_scanner(unsigned int version,int scan_thread_num,MESA_lqueue_head tomb) +struct _Maat_scanner_t* create_maat_scanner(unsigned int version,int scan_thread_num,MESA_lqueue_head tomb,int rs_scan_type) { int i=0; @@ -714,6 +714,7 @@ struct _Maat_scanner_t* create_maat_scanner(unsigned int version,int scan_thread scanner->ref_cnt=(int*)calloc(CPU_CACHE_ALIGMENT,scan_thread_num); scanner->region_update_q=MESA_lqueue_create(0,0); scanner->region=rulescan_initialize(scan_thread_num); + rulescan_set_param(scanner->region,rs_scan_type); scanner->tomb_ref=tomb; scanner->region_rslt_buff=(scan_result_t*)malloc(sizeof(scan_result_t)*MAX_SCANNER_HIT_NUM*scan_thread_num); @@ -2191,7 +2192,7 @@ void maat_start_cb(unsigned int new_version,int update_type,void*u_para) int i=0,j=0; if(update_type==CM_UPDATE_TYPE_FULL) { - feather->update_tmp_scanner=create_maat_scanner(new_version,feather->scan_thread_num,feather->garbage_q); + feather->update_tmp_scanner=create_maat_scanner(new_version,feather->scan_thread_num,feather->garbage_q,feather->rule_scan_type); MESA_handle_runtime_log(feather->logger,RLOG_LV_INFO,maat_module, "Full config version %u -> %u update start", feather->maat_version,new_version); @@ -2375,12 +2376,17 @@ void *thread_rule_monitor(void *arg) } } garbage_bury(feather->garbage_q,feather->logger); + if(feather->stat_on==1) + { + maat_stat_output(feather); + } } MESA_htable_destroy(feather->map_tablename2id,free); destroy_maat_scanner(feather->scanner); garbage_bury(feather->garbage_q,feather->logger); MESA_lqueue_destroy(feather->garbage_q,lqueue_destroy_cb,NULL); + FS_stop(&(feather->stat_handle)); int i=0,j=0; struct dynamic_array_t* d_array=NULL; @@ -2406,3 +2412,4 @@ void *thread_rule_monitor(void *arg) free(feather); return NULL; } + diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index 0204cec..89dd64f 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -5,6 +5,7 @@ #include #include +#include #include "dynamic_array.h" #include "UniversalBoolMatch.h" #include "rulescan.h" @@ -47,6 +48,7 @@ typedef int atomic_t; #define MAX_FAILED_NUM 128 +#define MAX_MAAT_STAT_NUM 64 #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif @@ -91,6 +93,7 @@ enum MAAT_MATCH_METHOD MATCH_METHOD_LEFT, MATCH_METHOD_FULL }; + struct db_str_rule_t { int region_id; @@ -224,6 +227,13 @@ struct _Maat_table_info_t int expr_rule_cnt; //expr_type=0,1,3 int regex_rule_cnt; //expr_type=2 struct _plugin_table_info *cb_info; +//for stat>>>>>>>> + int stat_line_id; + long long scan_cnt; + long long scan_cpu_time; //microseconds + long long input_bytes; + long long stream_num; + long long hit_cnt; }; struct _scan_status_t { @@ -294,17 +304,28 @@ struct _Maat_feather_t struct _Maat_scanner_t *update_tmp_scanner; MESA_lqueue_head garbage_q; int table_cnt; + int GROUP_MODE_ON; + int still_working; + int scan_interval_ms; + int effect_interval_ms; + int stat_on; + int perf_on; struct _Maat_table_info_t *p_table_info[MAX_TABLE_NUM]; MESA_htable_handle map_tablename2id; void* logger; int maat_version; int scan_thread_num; + int rule_scan_type; char inc_dir[MAX_TABLE_NAME_LEN]; char full_dir[MAX_TABLE_NAME_LEN]; - int GROUP_MODE_ON; - int still_working; - int scan_interval_ms; - int effect_interval_ms; + char stat_file[MAX_TABLE_NAME_LEN]; +//for stat>>>> + screen_stat_handle_t stat_handle; + int total_stat_id; + int fs_status_id[MAX_MAAT_STAT_NUM]; + int fs_column_id[MAX_MAAT_STAT_NUM]; + long long mid_cnt; + long long hit_cnt; }; struct _maat_garbage_t { @@ -338,5 +359,11 @@ inline void ipv6_ntoh(unsigned int *v6_addr) } return; } +void maat_stat_init(struct _Maat_feather_t* feather); +void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timeval* start, struct timeval* end); +void maat_stat_output(struct _Maat_feather_t* feather); + + + #endif diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp new file mode 100644 index 0000000..cb25e3d --- /dev/null +++ b/src/entry/Maat_stat.cpp @@ -0,0 +1,206 @@ +#include "Maat_rule_internal.h" +#include "field_stat.h" +enum MAAT_FS_STATUS{ + STATUS_VERSION=0, + STATUS_TABLE_NUM, + STATUS_MID_NUM, + STATUS_GARBAGE_QSIZE, +}; + +enum MAAT_FS_COLUMN +{ + COLUMN_TABLE_RULE_NUM=0, + COLUMN_TABLE_REGEX_NUM, + COLUMN_TABLE_STREAM_NUM, + COLUMN_TABLE_SCAN_CNT, + COLUMN_TABLE_SCAN_BYTES, + COLUMN_TABLE_CPU_TIME,//microseconds + COLUMN_TABLE_HIT_CNT +}; +void maat_stat_init(struct _Maat_feather_t* feather) +{ + int value=0; + int i=0; + struct _Maat_table_info_t* p_table=NULL; + + feather->stat_handle=FS_create_handle(); + FS_set_para(feather->stat_handle, OUTPUT_DEVICE, feather->stat_file, strlen(feather->stat_file)+1); + value=1; + FS_set_para(feather->stat_handle, PRINT_MODE, &value, sizeof(value)); + value=0; + FS_set_para(feather->stat_handle, CREATE_THREAD, &value, sizeof(value)); + + feather->fs_status_id[STATUS_VERSION]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"version"); + feather->fs_status_id[STATUS_TABLE_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"table_num"); + feather->fs_status_id[STATUS_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"mid_num"); + feather->fs_status_id[STATUS_GARBAGE_QSIZE]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"garbage_num"); + + feather->fs_column_id[COLUMN_TABLE_RULE_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"rule"); + feather->fs_column_id[COLUMN_TABLE_REGEX_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"regex"); + feather->fs_column_id[COLUMN_TABLE_STREAM_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"stream"); + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"scan_cps"); + feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"IN_Bps"); + if(feather->perf_on==1) + { + feather->fs_column_id[COLUMN_TABLE_CPU_TIME]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"cpu_us"); + value=feather->fs_column_id[COLUMN_TABLE_CPU_TIME]; + FS_set_para(feather->stat_handle, ID_INVISBLE, &value, sizeof(value)); + FS_register_ratio(feather->stat_handle, + feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES], + feather->fs_column_id[COLUMN_TABLE_CPU_TIME], + FS_STYLE_COLUMN, + FS_CALC_SPEED, + "PROC_Bps"); + } + feather->fs_column_id[COLUMN_TABLE_HIT_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"hit_cnt"); + value=feather->fs_column_id[COLUMN_TABLE_HIT_CNT]; + FS_set_para(feather->stat_handle, ID_INVISBLE, &value, sizeof(value)); + FS_register_ratio(feather->stat_handle, + feather->fs_column_id[COLUMN_TABLE_HIT_CNT], + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], + FS_STYLE_COLUMN, + FS_CALC_SPEED, + "hit_rate"); + feather->total_stat_id=FS_register(feather->stat_handle, FS_STYLE_LINE, FS_CALC_CURRENT,"Sum"); + for(i=0;ip_table_info[i]; + if(p_table==NULL||p_table->table_type==TABLE_TYPE_PLUGIN + ||p_table->table_type==TABLE_TYPE_GROUP + ||p_table->table_type==TABLE_TYPE_COMPILE) + { + continue; + } + p_table->stat_line_id=FS_register(feather->stat_handle, FS_STYLE_LINE, FS_CALC_CURRENT,p_table->table_name); + } + FS_start(feather->stat_handle); + return; +} +void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timeval* start, struct timeval* end) +{ + p_table->scan_cnt++; + p_table->input_bytes+=scan_len; + p_table->scan_cpu_time+=(end->tv_sec-start->tv_sec)*1000000+end->tv_usec-start->tv_usec; + return; +} +void maat_stat_output(struct _Maat_feather_t* feather) +{ + long value=0; + long long total_cfg_num=0, total_input_bytes=0, total_regex_num=0; + long long total_scan_cnt=0, total_cpu_time=0,total_stream_cnt=0; + int i=0; + struct _Maat_table_info_t* p_table=NULL; + + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_VERSION], 0,FS_OP_SET,feather->maat_version); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TABLE_NUM], 0,FS_OP_SET,feather->table_cnt); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_MID_NUM], 0,FS_OP_SET,feather->mid_cnt); + + value=MESA_lqueue_get_count(feather->garbage_q); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_GARBAGE_QSIZE], 0,FS_OP_SET,value); + + for(i=0;ip_table_info[i]; + if(p_table==NULL||p_table->table_type==TABLE_TYPE_PLUGIN + ||p_table->table_type==TABLE_TYPE_GROUP + ||p_table->table_type==TABLE_TYPE_COMPILE) + { + continue; + } + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_RULE_NUM], + FS_OP_SET, + p_table->cfg_num); + total_cfg_num+=p_table->cfg_num; + + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_REGEX_NUM], + FS_OP_SET, + p_table->regex_rule_cnt); + total_regex_num+= p_table->regex_rule_cnt; + + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_STREAM_NUM], + FS_OP_SET, + p_table->stream_num); + total_stream_cnt+= p_table->stream_num; + + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], + FS_OP_ADD, + p_table->scan_cnt); + total_scan_cnt+=p_table->scan_cnt; + p_table->scan_cnt=0; + + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES], + FS_OP_ADD, + p_table->input_bytes); + total_input_bytes+=p_table->input_bytes; + p_table->input_bytes=0; + if(feather->perf_on==1) + { + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_CPU_TIME], + FS_OP_ADD, + p_table->scan_cpu_time); + total_cpu_time+=p_table->scan_cpu_time; + p_table->scan_cpu_time=0; + } + FS_operate(feather->stat_handle, + p_table->stat_line_id, + feather->fs_column_id[COLUMN_TABLE_HIT_CNT], + FS_OP_ADD, + p_table->hit_cnt); + //total hit count stat in region_compile + p_table->hit_cnt=0; + } + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_RULE_NUM], + FS_OP_SET, + total_cfg_num); + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_REGEX_NUM], + FS_OP_SET, + total_regex_num); + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_STREAM_NUM], + FS_OP_SET, + total_stream_cnt); + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], + FS_OP_ADD, + total_scan_cnt); + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES], + FS_OP_ADD, + total_input_bytes); + if(feather->perf_on==1) + { + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_CPU_TIME], + FS_OP_ADD, + total_cpu_time); + } + FS_operate(feather->stat_handle, + feather->total_stat_id, + feather->fs_column_id[COLUMN_TABLE_HIT_CNT], + FS_OP_ADD, + feather->hit_cnt); + feather->hit_cnt=0; + FS_passive_output(feather->stat_handle); + return; +} + diff --git a/src/entry/Makefile b/src/entry/Makefile index 539f22a..8a8fcd7 100644 --- a/src/entry/Makefile +++ b/src/entry/Makefile @@ -6,7 +6,7 @@ CCC = g++ CFLAGS = -Wall -g -fPIC CFLAGS += $(OPTFLAGS) LDDICTATOR = -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,free -Wl,-wrap,realloc -LDFLAGS = -lMESA_handle_logger -lMESA_htable -lpthread -lm -lrulescan -lpcre +LDFLAGS = -lMESA_handle_logger -lMESA_htable -lpthread -lm -lrulescan -lpcre -lMESA_field_stat #LDFLAGS += $(LDDICTATOR) MAILLIB = ../lib @@ -15,8 +15,8 @@ H_DIR =-I$(G_H_DIR) -I../../inc LIBMAAT = libmaatframe.a LIBMAAT_SO = libmaatframe.so -OBJS=config_monitor.o Maat_rule.o Maat_api.o UniversalBoolMatch.o dynamic_array.o cJSON.o json2iris.o map_str2int.o\ - interval_index.o great_index_engine.o mesa_fuzzy.o +OBJS=config_monitor.o Maat_rule.o Maat_api.o Maat_stat.o UniversalBoolMatch.o dynamic_array.o cJSON.o\ + json2iris.o map_str2int.o interval_index.o great_index_engine.o mesa_fuzzy.o .c.o: $(CC) -c $(CFLAGS) -I. $(H_DIR) $< diff --git a/src/inc_internal/field_stat.h b/src/inc_internal/field_stat.h new file mode 100644 index 0000000..07e8a5f --- /dev/null +++ b/src/inc_internal/field_stat.h @@ -0,0 +1,70 @@ +#ifndef H_SCREEN_STAT_H_INCLUDE +#define H_SCREEN_STAT_H_INCLUDE +#include + +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif + +enum field_dsp_style_t +{ + FS_STYLE_FIELD=0, + FS_STYLE_COLUMN, + FS_STYLE_LINE, + FS_STYLE_STATUS +}; +enum field_calc_algo +{ + FS_CALC_CURRENT=0, + FS_CALC_SPEED +}; +enum field_op +{ + FS_OP_ADD=1, + FS_OP_SET +}; + + +typedef void* screen_stat_handle_t; + +enum FS_option +{ + OUTPUT_DEVICE, //VALUE is a const char*, indicate a file path string, SIZE = strlen(string+'\0')+1.DEFAULT:output to stdout. + PRINT_MODE, //VALUE is an interger,1:Rewrite ,2: Append. SIZE=4,DEFALUT:REWRITE. + STAT_CYCLE, //VALUE is an interger idicate interval seconds of every output, SIZE=4 ,DEFUALT:2 seconds. + PRINT_TRIGGER, //VALUE is an interger,1:Do print,0: Don't print.SIZE=4.DEFAULT:1. + CREATE_THREAD,//VALUE is an interger,1: Create a print thread,0:not create,output by call passive_output function, + //and the STAT_CYCLE is meaningless.SIZE=4,DEFAULT:0. + ID_INVISBLE,//value is field_id/status_id/column_id, not output this string, SIZE=4,DEFAULT: shutdown NO one. +}; + +//Always success. +screen_stat_handle_t FS_create_handle(void); + +int FS_set_para(screen_stat_handle_t handle, enum FS_option type,const void* value,int size); +void FS_start(screen_stat_handle_t handle); +void FS_stop(screen_stat_handle_t* handle); + +//return field_id/line_id/column_id greater than zero if success,return an interger less than zero if failed. +int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); + +//numerator_id and denominator_id must be column/field/status style. +int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); + +//id: when id's type is FIELD , column_id is ignore. +int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value); + +void FS_passive_output(screen_stat_handle_t handle); + +screen_stat_handle_t init_screen_stat(FILE* output_fp,int stat_cycle,int screen_print_trigger); + +//return field_id >=0 when success, return -1 when failed. +int stat_field_register(screen_stat_handle_t handle,const char* field_name); + +//return >=0 when success, return -1 when failed. +#define FS_OP_TYPE_ADD (FS_OP_ADD) +#define FS_OP_TYPE_SET (FS_OP_SET) +int stat_field_operation(screen_stat_handle_t handle,int field_id,int operation,long long value); + +#endif + diff --git a/src/inc_internal/rulescan.h b/src/inc_internal/rulescan.h index 9230e64..8ee4b80 100644 --- a/src/inc_internal/rulescan.h +++ b/src/inc_internal/rulescan.h @@ -23,10 +23,21 @@ extern "C" { #endif + /* 定义不同的扫描类型 */ + enum ScanType + { + SCANTYPE_DEFAULT = 0, + SCANTYPE_DETAIL_RESULT = 1, + SCANTYPE_REGEX_GROUP = 2 + }; + + #define MAX_REGEX_GROUP_NUM 5 /* 对于正则表达式,所支持的最大分组的个数 */ + #define MAX_EXPR_ITEM_NUM (1U<<3) /* 每条与表达式最多由MAX_EXPR_ITEM_NUM个规则组成 */ #define MAX_MATCH_POS_NUM 1024 /* 每条规则最多允许返回的命中位置的个数 */ + #define MATCH_POS_NUM_INC 64 /* 每条规则允许返回的命中位置的个数初始值与增量值 */ - /* 定义不同的规则类型 */ + /* 定义不同的规则类型 */ const unsigned int RULETYPE_STR = 0; /* 字符串或二进制规则 */ const unsigned int RULETYPE_REG = 1; /* 正则表达式规则 */ const unsigned int RULETYPE_INT = 2; /* 数值区间规则 */ @@ -195,6 +206,17 @@ extern "C" */ void * rulescan_initialize(unsigned int max_thread_num); + /* + 功能: + 设置扫描参数,本函数在rulescan_update之前可多次调用,每次设置一种扫描类型 + 参数: + instance[in]: 扫描器对象指针; + scan_type_flag[in]: 扫描类型的标志信息,0代表不返回位置等信息;1代表返回位置等信息,但是不返回正则分组信息;2代表返回位置信息和正则分组信息 + 返回值: + 1:正确设置,-1:设置失败。 + */ + int rulescan_set_param(void * instance, int scan_type_flag); + /* 功能:动态注册一组与表达式,更新扫描器对象。对于同一个instance句柄,不允许同时有多个更新线程。 参数: diff --git a/test/maat_test.cpp b/test/maat_test.cpp index 4be5a90..f52d2ad 100644 --- a/test/maat_test.cpp +++ b/test/maat_test.cpp @@ -13,6 +13,7 @@ #include #include //fstat #include //fstat +#include void Maat_read_entry_start_cb(int update_type,void* u_para) { @@ -36,7 +37,7 @@ void Maat_read_entry_finish_cb(void* u_para) { return; } -int main() +int main(int argc,char* argv[]) { Maat_feather_t feather=NULL; int cb_table_id=-1,url_scan_table_id=-1,size_scan_table_id=-1,ip_scan_table_id=-1,digest_scan_table_id=-1; @@ -49,20 +50,31 @@ int main() const char* log_file="./test.log"; const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; const char* digest_test_file="./digest_test.data"; + const char* stat_file="./scan_staus.log"; struct stat digest_fstat; unsigned long long read_size=0,scan_offset=0; char digest_test_buff[4096]={0}; int scan_val=2015; struct Maat_rule_t result[4]; int found_pos[4]; + int scan_detail=0; scan_status_t mid=NULL; - void *logger=MESA_create_runtime_log_handle(log_file,0); - feather=Maat_summon_feather_json(g_iThreadNum, + +/* feather=Maat_summon_feather_json(g_iThreadNum, table_info_path, json_path, logger); +*/ // feather=Maat_summon_feather(g_iThreadNum,table_info_path,ful_cfg_dir,inc_cfg_dir,logger); + feather=Maat_feather(g_iThreadNum, table_info_path, logger); + Maat_set_feather_opt(feather, MAAT_OPT_JSON_FILE_PATH, json_path, sizeof(json_path)+1); + Maat_set_feather_opt(feather, MAAT_OPT_STAT_FILE_PATH, stat_file, strlen(stat_file)); + Maat_set_feather_opt(feather, MAAT_OPT_STAT_ON, NULL, 0); + Maat_set_feather_opt(feather, MAAT_OPT_PERF_ON, NULL, 0); + Maat_set_feather_opt(feather, MAAT_OPT_SCAN_DETAIL, &scan_detail, sizeof(scan_detail)); + Maat_initiate_feather(feather); + if(feather==NULL) { printf("Maat initial error, see %s\n",log_file); @@ -140,6 +152,7 @@ int main() break; } } + sleep(2); Maat_clean_status(&mid); struct Maat_hit_detail_t *hit_detail=(struct Maat_hit_detail_t *)malloc(sizeof(struct Maat_hit_detail_t)*10); stream_para_t sp=Maat_stream_scan_string_start(feather,url_scan_table_id,0); @@ -202,7 +215,6 @@ int main() } } Maat_clean_status(&mid); - digest_scan_table_id=Maat_table_register(feather, "FILE_DIGEST"); if(digest_scan_table_id<0) { @@ -238,6 +250,7 @@ int main() } Maat_stream_scan_string_end(&sp); Maat_clean_status(&mid); + sleep(4); Maat_burn_feather(feather); free(hit_detail); return 0; From c2509da065c9fc36a292250b7f926637015c5023 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Thu, 11 Feb 2016 13:57:39 +0800 Subject: [PATCH 02/31] Add EXPR PLUS region table and Maat_set_scan_status function to indicate the district. --- inc/Maat_rule.h | 10 +- src/entry/Maat_api.cpp | 249 +++++++++++------- src/entry/Maat_rule.cpp | 104 +++++--- src/entry/Maat_rule_internal.h | 20 +- src/entry/Maat_stat.cpp | 9 +- src/entry/json2iris.cpp | 15 +- src/entry/map_str2int.cpp | 34 ++- test/maat_json.json | 28 +++ test/maat_test.cpp | 445 ++++++++++++++++++++------------- test/table_info.conf | 3 +- 10 files changed, 611 insertions(+), 306 deletions(-) diff --git a/inc/Maat_rule.h b/inc/Maat_rule.h index b8d3e66..42a13d5 100644 --- a/inc/Maat_rule.h +++ b/inc/Maat_rule.h @@ -124,7 +124,8 @@ Maat_feather_t Maat_summon_feather_json(int max_thread_num, Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger); int Maat_initiate_feather(Maat_feather_t feather); -enum MAAT_INIT_OPT{ +enum MAAT_INIT_OPT +{ MAAT_OPT_SCANDIR_INTERVAL_MS=1, //VALUE is interger,SIZE=sizeof(int). DEFAULT:1,000 milliseconds. MAAT_OPT_EFFECT_INVERVAL_MS, //VALUE is interger,SIZE=sizeof(int). DEFAULT:60,000 milliseconds. MAAT_OPT_FULL_CFG_DIR, //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. @@ -149,7 +150,12 @@ int Maat_table_callback_register(Maat_feather_t feather,short table_id, Maat_finish_callback_t *finish,//u_para void* u_para); - +enum MAAT_SCAN_OPT +{ + MAAT_SET_SCAN_DISTRICT=1 //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. +}; +//return 0 if success, return -1 when failed; +int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCAN_OPT,const void* value,int size); //Return hit rule number, return -1 when error occurs,return -2 when hit current region //mid MUST set NULL before fist call diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index d87cc88..a01e9d1 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -26,10 +26,18 @@ struct _Maat_table_info_t * acqurie_table(struct _Maat_feather_t* _feather,int t return NULL; } p_table=_feather->p_table_info[table_id]; - if(p_table==NULL||p_table->table_type!=expect_type) + if(p_table==NULL) { return NULL; } + if(p_table->table_type!=expect_type) + { + if(expect_type!=TABLE_TYPE_EXPR|| + p_table->table_type!=TABLE_TYPE_EXPR_PLUS) + { + return NULL; + } + } return p_table; } inline void INC_SCANNER_REF(_Maat_scanner_t*scanner,int thread_num) @@ -90,14 +98,14 @@ int pickup_hit_region_from_compile(universal_bool_expr_t *compile_hit,const unsi } return k; } -int region_compile(struct _scan_status_t *_mid,void* region_hit,int region_type_size,int group_offset,int region_hit_num,struct Maat_rule_t* result,_compile_result_t *rs_result, int size) +int region_compile(_Maat_feather_t*feather,struct _INNER_scan_status_t *_mid,void* region_hit,int region_type_size,int group_offset,int region_hit_num,struct Maat_rule_t* result,_compile_result_t *rs_result, int size) { int scan_ret=0,result_cnt=0; int ret=0,i=0,j=0; int r_in_c_cnt=0; - void* expr_compiler=_mid->feather->scanner->expr_compiler; int shortcut_avilable_cnt=0; + void* bool_matcher=feather->scanner->expr_compiler; struct _Maat_group_rule_t* group_rule=NULL; struct _Maat_compile_rule_t* array_mi_rule[MAX_SCANNER_HIT_NUM]; struct _Maat_compile_rule_t* _mi_rule=NULL; @@ -130,7 +138,7 @@ int region_compile(struct _scan_status_t *_mid,void* region_hit,int region_type_ } else { - scan_ret=boolexpr_match(expr_compiler,_mid->thread_num, + scan_ret=boolexpr_match(bool_matcher,_mid->thread_num, _mid->hitted_group_id,_mid->hit_group_cnt, (void **)array_mi_rule, MAX_SCANNER_HIT_NUM); } @@ -161,14 +169,14 @@ int region_compile(struct _scan_status_t *_mid,void* region_hit,int region_type_ } if(result_cnt>0) { - _mid->feather->hit_cnt++; + feather->hit_cnt++; } return result_cnt; } -int exprid2region_id(struct _Maat_group_rule_t* group_rule,int expr_id) +int exprid2region_id(struct _Maat_group_rule_t* group_rule,int expr_id,int* district_id) { - int i=0,region_id=-1;; + int i=0,region_id=-1; struct _Maat_region_rule_t* region_rule=NULL; assert(group_rule->group_id>=0); pthread_mutex_lock(&(group_rule->mutex)); @@ -182,11 +190,34 @@ int exprid2region_id(struct _Maat_group_rule_t* group_rule,int expr_id) if(region_rule->expr_id==expr_id) { region_id=region_rule->region_id; + *district_id=region_rule->district_id; } } pthread_mutex_unlock(&(group_rule->mutex)); return region_id; } +int match_district(struct _OUTER_scan_status_t *_mid,scan_result_t *region_hit,int region_hit_num) +{ + struct _Maat_group_rule_t* group_rule=NULL; + int i=0; + int district_id=-1,region_id=-1; + int ret_region_num=region_hit_num; + while(i0&&district_id!=_mid->district_id) + { + ret_region_num--; + memmove(&(region_hit[i]),&(region_hit[i+1]),sizeof(scan_result_t)*(ret_region_num-i)); + } + else + { + i++; + } + } + return ret_region_num; +} int fill_regex_pos(struct regex_pos_t *regex_pos,int size,rule_result_t *rs_result,const char* buff) @@ -255,7 +286,7 @@ int hit_pos_RS2Maat(struct sub_item_pos_t* maat_sub_item,int size,rule_result_t* } return k; } -int fill_region_hit_detail(const char* scan_buff,const _scan_status_t* _mid, +int fill_region_hit_detail(const char* scan_buff,const _INNER_scan_status_t* _mid, scan_result_t *region_hit,int region_cnt, _compile_result_t *compile_hit,int compile_cnt, struct Maat_hit_detail_t *hit_detail,int detail_num) @@ -265,6 +296,7 @@ int fill_region_hit_detail(const char* scan_buff,const _scan_status_t* _mid, int region_pos[MAX_SCANNER_HIT_NUM],pos=0; int r_in_c_cnt=0; int region_id=-1; + int district_id=-1; //Indifferenc memset(r_in_c_flag,0,sizeof(r_in_c_flag)); memset(region_pos,0,sizeof(region_pos)); @@ -281,7 +313,7 @@ int fill_region_hit_detail(const char* scan_buff,const _scan_status_t* _mid, pos=region_pos[j]; r_in_c_flag[pos]=1; group_rule=(struct _Maat_group_rule_t*)(region_hit[pos].tag); - region_id=exprid2region_id(group_rule,region_hit[pos].expr_id); + region_id=exprid2region_id(group_rule,region_hit[pos].expr_id,&district_id); if(region_id<0) { continue; @@ -303,7 +335,7 @@ int fill_region_hit_detail(const char* scan_buff,const _scan_status_t* _mid, group_rule=(struct _Maat_group_rule_t*)(region_hit[k].tag); hit_detail[j].config_id=-2; hit_detail[j].hit_region_cnt=1; - hit_detail[j].region_pos[0].region_id=exprid2region_id(group_rule,region_hit[k].expr_id); + hit_detail[j].region_pos[0].region_id=exprid2region_id(group_rule,region_hit[k].expr_id,&district_id); hit_detail[j].region_pos[0].sub_item_num=region_hit[k].rnum; hit_pos_RS2Maat(hit_detail[j].region_pos[0].sub_item_pos,MAAT_MAX_EXPR_ITEM_NUM, region_hit[k].result,region_hit[k].rnum,scan_buff); @@ -312,20 +344,48 @@ int fill_region_hit_detail(const char* scan_buff,const _scan_status_t* _mid, } return j; } -struct _scan_status_t* _Maat_make_status(struct _Maat_feather_t* feather,int thread_num) +struct _INNER_scan_status_t* _make_inner_status(int thread_num) { - struct _scan_status_t* _mid=NULL; - _mid=(struct _scan_status_t*)calloc(sizeof(struct _scan_status_t),1); - _mid->feather=feather; - _mid->thread_num=thread_num; - _mid->cur_hit_cnt=0; - _mid->hit_group_cnt=0; - _mid->hit_group_size=4; - _mid->hitted_group_id=(unsigned int*)malloc(sizeof(unsigned int)*_mid->hit_group_size); - feather->mid_cnt++; + struct _INNER_scan_status_t* inner_mid=NULL; + inner_mid=(struct _INNER_scan_status_t*)calloc(sizeof(struct _INNER_scan_status_t),1); + inner_mid->thread_num=thread_num; + inner_mid->cur_hit_cnt=0; + inner_mid->hit_group_cnt=0; + inner_mid->hit_group_size=4; + inner_mid->hitted_group_id=(unsigned int*)malloc(sizeof(unsigned int)*inner_mid->hit_group_size); + return inner_mid; +} +struct _OUTER_scan_status_t* _make_outer_status(_Maat_feather_t *feather) +{ + struct _OUTER_scan_status_t* outer_mid=NULL; + outer_mid=(struct _OUTER_scan_status_t*)calloc(sizeof(struct _OUTER_scan_status_t),1); + outer_mid->feather=feather; + outer_mid->district_id=-1; + feather->outer_mid_cnt++; + return outer_mid; +} +struct _OUTER_scan_status_t* grab_mid(scan_status_t* raw_mid,_Maat_feather_t* feather,int thread_num,int is_hit_region) +{ + struct _OUTER_scan_status_t* _mid=NULL; + if(*raw_mid!=NULL) + { + _mid=(struct _OUTER_scan_status_t*)(*raw_mid); + } + if(is_hit_region==1) + { + if(_mid==NULL) + { + _mid=_make_outer_status(feather); + *raw_mid=_mid; + } + if(_mid->inner==NULL) + { + _mid->inner=_make_inner_status(thread_num); + feather->inner_mid_cnt++; + } + } return _mid; } - int detain_last_data(char* buff,int buff_size,int detained_len,const char* data,int data_len) { int to_copy_size=0,foward_offset=0; @@ -352,7 +412,6 @@ int detain_last_data(char* buff,int buff_size,int detained_len,const char* data, } return ret_len; } - Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger) { _Maat_feather_t* feather=(_Maat_feather_t*)calloc(sizeof(struct _Maat_feather_t),1); @@ -633,7 +692,7 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id int region_ret=0,compile_ret=0,hit_region_cnt=0; unsigned int sub_type=0; struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; - struct _scan_status_t* _mid=NULL; + struct _OUTER_scan_status_t* _mid=(struct _OUTER_scan_status_t*)(*mid); scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num];//dynamic array @@ -643,6 +702,7 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id { gettimeofday(&start,NULL); } + _mid=grab_mid(mid,_feather, thread_num, 0); p_table=acqurie_table(_feather, table_id,TABLE_TYPE_EXPR); if(p_table==NULL) { @@ -652,6 +712,10 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id { return 0; } + if(p_table->table_type==TABLE_TYPE_EXPR_PLUS&&(_mid==NULL||_mid->is_set_district!=1)) + { + return -1; + } if(p_table->do_charset_merge==1) { sub_type=make_sub_type(table_id,CHARSET_NONE,0); @@ -696,25 +760,21 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id } } + if(hit_region_cnt>0&&p_table->table_type==TABLE_TYPE_EXPR_PLUS) + { + hit_region_cnt=match_district(_mid,region_result,hit_region_cnt); + } if(hit_region_cnt>0) { p_table->hit_cnt++; - if(*mid==NULL) - { - _mid=_Maat_make_status(_feather,thread_num); - *mid=_mid; - } - else - { - _mid=(struct _scan_status_t*)(*mid); - } - compile_ret=region_compile(_mid, + _mid=grab_mid(mid,_feather,thread_num, 1); + compile_ret=region_compile(_feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); if(hit_detail!=NULL) { - *detail_ret=fill_region_hit_detail(data,_mid, + *detail_ret=fill_region_hit_detail(data,_mid->inner, region_result,hit_region_cnt, compile_result,compile_ret, hit_detail,detail_num); @@ -750,7 +810,7 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id ,scan_status_t *mid,int thread_num) { int region_ret=0,compile_ret=0; - struct _scan_status_t* _mid=NULL; + struct _OUTER_scan_status_t* _mid=NULL; scan_data_t intval_scan_data; scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num]; @@ -792,16 +852,8 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id else if(region_ret>0) { p_table->hit_cnt++; - if(*mid==NULL) - { - _mid=_Maat_make_status(_feather,thread_num); - *mid=_mid; - } - else - { - _mid=(struct _scan_status_t*)(*mid); - } - compile_ret=region_compile(_mid, + _mid=grab_mid(mid, _feather, thread_num, 1); + compile_ret=region_compile(_feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), region_ret, result,compile_result,rule_num); @@ -827,7 +879,7 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id ,scan_status_t *mid,int thread_num) { int region_ret=0,compile_ret=0; - struct _scan_status_t* _mid=NULL; + struct _OUTER_scan_status_t* _mid=NULL; scan_data_t ip_scan_data; scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num]; @@ -892,16 +944,8 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id else if(region_ret>0) { p_table->hit_cnt++; - if(*mid==NULL) - { - _mid=_Maat_make_status(_feather,thread_num); - *mid=_mid; - } - else - { - _mid=(struct _scan_status_t*)(*mid); - } - compile_ret=region_compile(_mid, + _mid=grab_mid(mid, _feather, thread_num, 1); + compile_ret=region_compile(_feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), region_ret, result,compile_result,rule_num); @@ -987,15 +1031,17 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para int sub_type=0; int region_ret=0,hit_region_cnt=0,compile_ret=0; - struct _scan_status_t* _mid=(struct _scan_status_t*)(*mid); + struct _OUTER_scan_status_t* _mid=NULL; scan_result_t *region_result; _compile_result_t compile_result[rule_num];//dynamic array scan_data_t region_scan_data; + _Maat_table_info_t* p_table=NULL; struct timeval start,end; if(sp->feather->perf_on==1) { gettimeofday(&start,NULL); } + _mid=grab_mid(mid, sp->feather, sp->thread_num,0); if(data==NULL||data_len==0) { return 0; @@ -1008,10 +1054,15 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para { return 0; } - if(sp->feather->p_table_info[sp->table_id]->cfg_num==0) + p_table=sp->feather->p_table_info[sp->table_id]; + if(p_table->cfg_num==0) { return 0; } + if(p_table->table_type==TABLE_TYPE_EXPR_PLUS&&(_mid==NULL||_mid->is_set_district!=1)) + { + return -1; + } region_result=scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*sp->thread_num; *detail_ret=0; if(sp->do_merge==1) @@ -1081,20 +1132,15 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para hit_region_cnt+=region_ret; } } + if(hit_region_cnt>0&&p_table->table_type==TABLE_TYPE_EXPR_PLUS) + { + hit_region_cnt=match_district(_mid,region_result,hit_region_cnt); + } if(hit_region_cnt>0) { - sp->feather->p_table_info[sp->table_id]->hit_cnt++; - - if(*mid==NULL) - { - _mid=_Maat_make_status(sp->feather,sp->thread_num); - *mid=_mid; - } - else - { - _mid=(struct _scan_status_t*)(*mid); - } - compile_ret=region_compile(_mid, + p_table->hit_cnt++; + _mid=grab_mid(mid, sp->feather,sp->thread_num, 1); + compile_ret=region_compile(sp->feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); @@ -1102,14 +1148,14 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para { if(sp->scan_buff!=NULL) { - *detail_ret=fill_region_hit_detail(sp->scan_buff,_mid, + *detail_ret=fill_region_hit_detail(sp->scan_buff,_mid->inner, region_result,hit_region_cnt, compile_result,compile_ret, hit_detail,detail_num); } else { - *detail_ret=fill_region_hit_detail(data,_mid, + *detail_ret=fill_region_hit_detail(data,_mid->inner, region_result,hit_region_cnt, compile_result,compile_ret, hit_detail,detail_num); @@ -1119,7 +1165,7 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para if(*detail_ret==0) { free(sp->scan_buff); - sp->scan_buff=0; + sp->scan_buff=NULL; } if(sp->feather->perf_on==1) { @@ -1244,7 +1290,7 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int GIE_handle_t* GIE_handle=sp->feather->scanner->digest_handle[sp->table_id]; unsigned long long digest_len=0; char* digest_buff=NULL; - struct _scan_status_t* _mid=(struct _scan_status_t*)(*mid); + struct _OUTER_scan_status_t* _mid=NULL; pthread_rwlock_t *GIE_rwlock=&(sp->feather->scanner->digest_rwlock[sp->table_id]); struct timeval start,end; if(sp->feather->perf_on==1) @@ -1291,16 +1337,8 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int if(hit_region_cnt>0) { sp->feather->p_table_info[sp->table_id]->hit_cnt++; - if(*mid==NULL) - { - _mid=_Maat_make_status(sp->feather,sp->thread_num); - *mid=_mid; - } - else - { - _mid=(struct _scan_status_t*)(*mid); - } - compile_ret=region_compile(_mid, + _mid=grab_mid(mid,sp->feather, sp->thread_num,1); + compile_ret=region_compile(sp->feather,_mid->inner, query_result,sizeof(GIE_result_t),offsetof(GIE_result_t, tag), hit_region_cnt, result,compile_result,rule_num); @@ -1340,17 +1378,52 @@ void Maat_stream_scan_digest_end(stream_para_t* stream_para) return; } +int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCAN_OPT type,const void* value,int size) +{ + struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; + struct _OUTER_scan_status_t* _mid=NULL; + int ret=0,map_ret=-1; + _mid=grab_mid(mid,_feather, 0, 0); + if(*mid==NULL) + { + _mid=_make_outer_status(_feather); + *mid=_mid; + } + switch(type) + { + case MAAT_SET_SCAN_DISTRICT: + map_ret=map_str2int(_feather->scanner->district_map,(const char*)value,&(_mid->district_id)); + if(map_ret<0) + { + //May be the district have not effect yet. + } + _mid->is_set_district=1; + ret=0; + break; + default: + ret=-1; + break; + } + return ret; +} void Maat_clean_status(scan_status_t* mid) { - struct _scan_status_t* _mid=NULL; + struct _OUTER_scan_status_t* _mid=NULL; if(*mid==NULL) { return; } - _mid=(struct _scan_status_t*)(*mid); - _mid->feather->mid_cnt--; - free(_mid->hitted_group_id); + _mid=(struct _OUTER_scan_status_t*)(*mid); + _mid->feather->outer_mid_cnt--; + if(_mid->inner!=NULL) + { + free(_mid->inner->hitted_group_id); + free(_mid->inner); + _mid->feather->inner_mid_cnt--; + } + _mid->feather=NULL; free(_mid); *mid=NULL; return; } + diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index d47debd..92a5e4c 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -25,7 +25,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_4_20160210=1; +int MAAT_FRAME_VERSION_1_5_20160211=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"CHARSET_NONE","GBK","BIG5","UNICODE","UTF-8"}; @@ -269,6 +269,7 @@ int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* map_register(string2int_map,"plugin", TABLE_TYPE_PLUGIN); map_register(string2int_map,"intval", TABLE_TYPE_INTVAL); map_register(string2int_map,"digest", TABLE_TYPE_DIGEST); + map_register(string2int_map,"expr_plus", TABLE_TYPE_EXPR_PLUS); map_register(string2int_map,"group", TABLE_TYPE_GROUP); map_register(string2int_map,"bin", CHARSET_NONE); map_register(string2int_map,"gbk", CHARSET_GBK); @@ -706,6 +707,8 @@ struct _Maat_scanner_t* create_maat_scanner(unsigned int version,int scan_thread scanner->region_hash=MESA_htable_create(&hargs, sizeof(hargs)); MESA_htable_print_crtl(scanner->region_hash,0); + + scanner->district_map=map_create(); scanner->version=version; scanner->cfg_num=0; @@ -738,7 +741,7 @@ void destroy_maat_scanner(struct _Maat_scanner_t*scanner) MESA_htable_destroy(scanner->compile_hash,NULL); MESA_htable_destroy(scanner->group_hash, NULL); MESA_htable_destroy(scanner->region_hash, NULL); - + map_destroy(scanner->district_map); destroy_bool_matcher((void*)scanner->expr_compiler); q_cnt=MESA_lqueue_get_count(scanner->region_update_q); for(i=0;ilast_update_time=time(NULL); return; } -struct _Maat_group_rule_t* add_region_to_group(struct _Maat_group_rule_t* group,int region_id,int expr_id,enum MAAT_TABLE_TYPE region_type) +struct _Maat_group_rule_t* add_region_to_group(struct _Maat_group_rule_t* group,int region_id,int district_id,int expr_id,enum MAAT_TABLE_TYPE region_type) { struct _Maat_region_rule_t* region_rule=(struct _Maat_region_rule_t*)malloc(sizeof(struct _Maat_region_rule_t)); region_rule->region_id=region_id; region_rule->expr_id=expr_id; + region_rule->district_id=district_id; region_rule->region_type=region_type; pthread_mutex_lock(&(group->mutex)); dynamic_array_write(group->region_rules,group->region_boundary,region_rule); @@ -1076,12 +1080,24 @@ int sync_region(MESA_htable_handle region_hash,int region_id,const char* table_n } return 1; } +int get_district_id(_Maat_scanner_t *scanner,const char* district_str) +{ + int map_ret=0,district_id=-1; + map_ret=map_str2int(scanner->district_map, district_str,&district_id); + if(map_ret<0) + { + district_id= scanner->district_num; + map_register(scanner->district_map,district_str, district_id); + scanner->district_num++; + } + return district_id; +} int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule,struct _Maat_scanner_t *scanner,void* logger) { unsigned int i=0,j=0; char* p=NULL,*saveptr=NULL,*region_string=NULL; int region_str_len=0,ret=0,k=0; - int expr_id=0; + int expr_id=0,district_id=-1; scan_rule_t*p_rule=NULL; struct _Maat_group_rule_t* group_rule=NULL; @@ -1096,7 +1112,12 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule int sub_expr_cnt=0; struct op_expr_t *op_expr=NULL; struct _Maat_group_rule_t* u_para=NULL; - + + if(table->table_type==TABLE_TYPE_EXPR_PLUS) + { + assert(strlen(db_rule->district)>0); + district_id=get_district_id(scanner, db_rule->district); + } group_rule=(struct _Maat_group_rule_t*)HASH_fetch_by_id(scanner->group_hash, db_rule->group_id); if(group_rule==NULL) { @@ -1168,7 +1189,7 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule break; case EXPR_TYPE_REGEX://it's easy,no need to charset convert expr_id=scanner->exprid_generator++; - u_para=add_region_to_group(group_rule,db_rule->region_id,expr_id,TABLE_TYPE_EXPR); + u_para=add_region_to_group(group_rule,db_rule->region_id,district_id,expr_id,TABLE_TYPE_EXPR); if(u_para==NULL) { return -1; @@ -1234,7 +1255,7 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule break; } expr_id=scanner->exprid_generator++; - u_para=add_region_to_group(group_rule, db_rule->region_id,expr_id, TABLE_TYPE_EXPR); + u_para=add_region_to_group(group_rule, db_rule->region_id,district_id,expr_id, table->table_type); if(u_para==NULL)//duplicate { return -1; @@ -1299,7 +1320,7 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule else { expr_id=scanner->exprid_generator++; - u_para=add_region_to_group(group_rule, db_rule->region_id,expr_id, TABLE_TYPE_EXPR); + u_para=add_region_to_group(group_rule, db_rule->region_id,district_id,expr_id, table->table_type); if(u_para==NULL) { return -1; @@ -1335,7 +1356,7 @@ int add_ip_rule(struct _Maat_table_info_t* table,struct db_ip_rule_t* db_ip_rule scan_rule_t* p_rule=NULL; struct op_expr_t* op_expr=NULL; struct _Maat_group_rule_t* u_para=NULL; - int expr_id=0; + int expr_id=0,district_id=-1; group_rule=(struct _Maat_group_rule_t*)HASH_fetch_by_id(scanner->group_hash, db_ip_rule->group_id); if(group_rule==NULL) @@ -1345,7 +1366,7 @@ int add_ip_rule(struct _Maat_table_info_t* table,struct db_ip_rule_t* db_ip_rule } expr_id=scanner->exprid_generator++; - u_para=add_region_to_group(group_rule,db_ip_rule->region_id,expr_id,TABLE_TYPE_IP); + u_para=add_region_to_group(group_rule,db_ip_rule->region_id,district_id,expr_id,TABLE_TYPE_IP); if(u_para==NULL) { return -1; @@ -1366,8 +1387,8 @@ int add_intval_rule(struct _Maat_table_info_t* table,struct db_intval_rule_t* in scan_rule_t* p_rule=NULL; struct op_expr_t* op_expr=NULL; struct _Maat_group_rule_t* u_para=NULL; - int expr_id=0; - + int expr_id=0,district_id=-1; + group_rule=(struct _Maat_group_rule_t*)HASH_fetch_by_id(scanner->group_hash, intval_rule->group_id); if(group_rule==NULL) { @@ -1375,7 +1396,7 @@ int add_intval_rule(struct _Maat_table_info_t* table,struct db_intval_rule_t* in HASH_add_by_id(scanner->group_hash, intval_rule->group_id, group_rule); } expr_id=scanner->exprid_generator++; - u_para=add_region_to_group(group_rule,intval_rule->region_id,expr_id,TABLE_TYPE_INTVAL); + u_para=add_region_to_group(group_rule,intval_rule->region_id,district_id,expr_id,TABLE_TYPE_INTVAL); if(u_para==NULL) { return -1; @@ -1395,7 +1416,7 @@ int add_digest_rule(struct _Maat_table_info_t* table,struct db_digest_rule_t* db struct _Maat_group_rule_t* group_rule=NULL; GIE_digest_t* digest_rule=NULL; struct _Maat_group_rule_t* u_para=NULL; - int expr_id=0; + int expr_id=0,district_id=-1; group_rule=(struct _Maat_group_rule_t*)HASH_fetch_by_id(scanner->group_hash, db_digest_rule->group_id); if(group_rule==NULL) @@ -1404,7 +1425,7 @@ int add_digest_rule(struct _Maat_table_info_t* table,struct db_digest_rule_t* db HASH_add_by_id(scanner->group_hash, db_digest_rule->group_id, group_rule); } expr_id=scanner->exprid_generator++; - u_para=add_region_to_group(group_rule,db_digest_rule->region_id,expr_id,TABLE_TYPE_DIGEST); + u_para=add_region_to_group(group_rule,db_digest_rule->region_id,expr_id,district_id,TABLE_TYPE_DIGEST); if(u_para==NULL) { return -1; @@ -1643,20 +1664,46 @@ void update_expr_rule(struct _Maat_table_info_t* table,const char* table_line,st { struct db_str_rule_t* maat_str_rule=(struct db_str_rule_t*)malloc(sizeof(struct db_str_rule_t)); int ret=0,db_hexbin=0; - ret=sscanf(table_line,"%d\t%d\t%s\t%d\t%d\t%d\t%d",&(maat_str_rule->region_id) - ,&(maat_str_rule->group_id) - ,maat_str_rule->keywords - ,(int*)&(maat_str_rule->expr_type) - ,(int*)&(maat_str_rule->match_method) - ,&db_hexbin - ,&(maat_str_rule->is_valid)); - if(ret!=7) + switch(table->table_type) { - MESA_handle_runtime_log(logger,RLOG_LV_FATAL,maat_module , - "update error,invalid format of expr table %s:%s",table->table_name,table_line); - free(maat_str_rule); - maat_str_rule=NULL; - return; + case TABLE_TYPE_EXPR: + ret=sscanf(table_line,"%d\t%d\t%s\t%d\t%d\t%d\t%d",&(maat_str_rule->region_id) + ,&(maat_str_rule->group_id) + ,maat_str_rule->keywords + ,(int*)&(maat_str_rule->expr_type) + ,(int*)&(maat_str_rule->match_method) + ,&db_hexbin + ,&(maat_str_rule->is_valid)); + if(ret!=7) + { + MESA_handle_runtime_log(logger,RLOG_LV_FATAL,maat_module , + "update error,invalid format of expr table %s:%s",table->table_name,table_line); + free(maat_str_rule); + maat_str_rule=NULL; + return; + } + break; + case TABLE_TYPE_EXPR_PLUS: + ret=sscanf(table_line,"%d\t%d\t%s\t%s\t%d\t%d\t%d\t%d",&(maat_str_rule->region_id) + ,&(maat_str_rule->group_id) + ,maat_str_rule->district + ,maat_str_rule->keywords + ,(int*)&(maat_str_rule->expr_type) + ,(int*)&(maat_str_rule->match_method) + ,&db_hexbin + ,&(maat_str_rule->is_valid)); + if(ret!=8) + { + MESA_handle_runtime_log(logger,RLOG_LV_FATAL,maat_module , + "update error,invalid format of expr_plus table %s:%s",table->table_name,table_line); + free(maat_str_rule); + maat_str_rule=NULL; + return; + } + break; + default: + assert(0); + break; } switch(db_hexbin) { @@ -2305,6 +2352,7 @@ void maat_update_cb(const char* table_name,const char* line,void *u_para) switch(feather->p_table_info[table_id]->table_type) { case TABLE_TYPE_EXPR: + case TABLE_TYPE_EXPR_PLUS: update_expr_rule(feather->p_table_info[table_id], line, scanner,feather->logger,feather->GROUP_MODE_ON); break; case TABLE_TYPE_IP: diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index 89dd64f..a2b223b 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -40,6 +40,7 @@ typedef int atomic_t; #define MAX_TABLE_NAME_LEN 256 #define MAX_TABLE_LINE_SIZE (1024*4) #define MAX_EXPR_KEYLEN 1024 +#define MAX_DISTRICT_LEN 64 #define MAX_PLUGING_NUM 32 #define MAX_SCANNER_HIT_NUM 64 @@ -76,6 +77,7 @@ enum MAAT_TABLE_TYPE TABLE_TYPE_PLUGIN, TABLE_TYPE_INTVAL, TABLE_TYPE_DIGEST, + TABLE_TYPE_EXPR_PLUS, TABLE_TYPE_GROUP }; @@ -99,6 +101,7 @@ struct db_str_rule_t int region_id; int group_id; char keywords[MAX_EXPR_KEYLEN]; + char district[MAX_DISTRICT_LEN]; enum MAAT_EXPR_TYPE expr_type; enum MAAT_MATCH_METHOD match_method; int is_hexbin; @@ -171,6 +174,7 @@ struct _Maat_region_rule_t { int region_id; int expr_id; + int district_id; enum MAAT_TABLE_TYPE region_type; }; struct _Maat_group_rule_t @@ -235,9 +239,9 @@ struct _Maat_table_info_t long long stream_num; long long hit_cnt; }; -struct _scan_status_t + +struct _INNER_scan_status_t { - struct _Maat_feather_t* feather; int thread_num; int cur_hit_cnt; int hit_group_cnt; @@ -245,6 +249,13 @@ struct _scan_status_t unsigned int cur_hit_id[MAX_SCANNER_HIT_NUM]; unsigned int *hitted_group_id; }; +struct _OUTER_scan_status_t +{ + struct _Maat_feather_t* feather; + int is_set_district; + int district_id; + struct _INNER_scan_status_t* inner; +}; enum maat_garbage_type { GARBAGE_SCANNER=0, @@ -288,6 +299,8 @@ struct _Maat_scanner_t MESA_htable_handle region_hash; MESA_htable_handle group_hash; MESA_htable_handle compile_hash; + MESA_htable_handle district_map; + unsigned int district_num; unsigned int cfg_num; unsigned int exprid_generator; MESA_lqueue_head region_update_q; @@ -324,7 +337,8 @@ struct _Maat_feather_t int total_stat_id; int fs_status_id[MAX_MAAT_STAT_NUM]; int fs_column_id[MAX_MAAT_STAT_NUM]; - long long mid_cnt; + long long outer_mid_cnt; + long long inner_mid_cnt; long long hit_cnt; }; struct _maat_garbage_t diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index cb25e3d..2b05e77 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -3,7 +3,8 @@ enum MAAT_FS_STATUS{ STATUS_VERSION=0, STATUS_TABLE_NUM, - STATUS_MID_NUM, + STATUS_OUTER_MID_NUM, + STATUS_INNER_MID_NUM, STATUS_GARBAGE_QSIZE, }; @@ -32,7 +33,8 @@ void maat_stat_init(struct _Maat_feather_t* feather) feather->fs_status_id[STATUS_VERSION]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"version"); feather->fs_status_id[STATUS_TABLE_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"table_num"); - feather->fs_status_id[STATUS_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"mid_num"); + feather->fs_status_id[STATUS_OUTER_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"outer_mid"); + feather->fs_status_id[STATUS_INNER_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"inner_mid"); feather->fs_status_id[STATUS_GARBAGE_QSIZE]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"garbage_num"); feather->fs_column_id[COLUMN_TABLE_RULE_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"rule"); @@ -93,7 +95,8 @@ void maat_stat_output(struct _Maat_feather_t* feather) FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_VERSION], 0,FS_OP_SET,feather->maat_version); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TABLE_NUM], 0,FS_OP_SET,feather->table_cnt); - FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_MID_NUM], 0,FS_OP_SET,feather->mid_cnt); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_OUTER_MID_NUM], 0,FS_OP_SET,feather->outer_mid_cnt); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_INNER_MID_NUM], 0,FS_OP_SET,feather->inner_mid_cnt); value=MESA_lqueue_get_count(feather->garbage_q); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_GARBAGE_QSIZE], 0,FS_OP_SET,value); diff --git a/src/entry/json2iris.cpp b/src/entry/json2iris.cpp index cdf5a98..397aa85 100644 --- a/src/entry/json2iris.cpp +++ b/src/entry/json2iris.cpp @@ -110,8 +110,11 @@ int set_iris_descriptor(const char* json_file,cJSON *json,struct iris_descriptio map_register(iris_cfg->str2int_map, "ip",TABLE_TYPE_IP); map_register(iris_cfg->str2int_map, "string",TABLE_TYPE_EXPR); + map_register(iris_cfg->str2int_map, "expr",TABLE_TYPE_EXPR); + map_register(iris_cfg->str2int_map, "expr_plus",TABLE_TYPE_EXPR_PLUS); map_register(iris_cfg->str2int_map, "intval",TABLE_TYPE_INTVAL); map_register(iris_cfg->str2int_map, "digest",TABLE_TYPE_DIGEST); + map_register(iris_cfg->str2int_map, "ipv4",4); map_register(iris_cfg->str2int_map, "ipv6",6); @@ -364,7 +367,7 @@ int write_ip_rule(cJSON *region_json,struct iris_description_t *p_iris,const cha return direct_write_rule(region_json, p_iris->str2int_map,json_cmd, cmd_cnt,path,logger); } -int write_expr_rule(cJSON *region_json,struct iris_description_t *p_iris,const char* path,void * logger) +int write_expr_rule(cJSON *region_json,struct iris_description_t *p_iris,const char* path,enum MAAT_TABLE_TYPE table_type,void * logger) { struct traslate_command_t json_cmd[MAX_COLUMN_NUM]; int cmd_cnt=0; @@ -378,6 +381,13 @@ int write_expr_rule(cJSON *region_json,struct iris_description_t *p_iris,const c json_cmd[cmd_cnt].json_type=cJSON_Number; cmd_cnt++; + if(table_type==TABLE_TYPE_EXPR_PLUS) + { + json_cmd[cmd_cnt].json_string="district"; + json_cmd[cmd_cnt].json_type=cJSON_String; + cmd_cnt++; + } + json_cmd[cmd_cnt].json_string="keywords"; json_cmd[cmd_cnt].json_type=cJSON_String; cmd_cnt++; @@ -598,7 +608,8 @@ int write_region_rule(cJSON* region_json,int compile_id,int group_id,iris_descri switch(table_type) { case TABLE_TYPE_EXPR: - ret=write_expr_rule(table_content, p_iris, table_info->table_path, logger); + case TABLE_TYPE_EXPR_PLUS: + ret=write_expr_rule(table_content, p_iris, table_info->table_path,table_type, logger); break; case TABLE_TYPE_IP: ret=write_ip_rule(table_content, p_iris, table_info->table_path, logger); diff --git a/src/entry/map_str2int.cpp b/src/entry/map_str2int.cpp index 07f4b38..8cad88d 100644 --- a/src/entry/map_str2int.cpp +++ b/src/entry/map_str2int.cpp @@ -1,21 +1,35 @@ #include + void map_tmp_free(void* ptr) { free(ptr); } + +long read_map_val(void *data, const uchar *key, uint size, void *user_arg) +{ + if(data!=NULL) + { + *(int*)user_arg=*(int*)data; + return 1; + } + else + { + return 0; + } +} MESA_htable_handle map_create(void) { MESA_htable_handle string2int_map; MESA_htable_create_args_t hargs; memset(&hargs,0,sizeof(hargs)); hargs.thread_safe=1; - hargs.hash_slot_size = 1024*1024; + hargs.hash_slot_size = 4*1024; hargs.max_elem_num = 0; hargs.eliminate_type = HASH_ELIMINATE_ALGO_LRU; hargs.expire_time = 0; hargs.key_comp = NULL; hargs.key2index = NULL; - hargs.recursive = 0; + hargs.recursive = 1; hargs.data_free = map_tmp_free; hargs.data_expire_with_condition = NULL; string2int_map=MESA_htable_create(&hargs, sizeof(hargs)); @@ -31,20 +45,28 @@ int map_register(MESA_htable_handle handle,const char* string,int value) { unsigned int size=strlen(string); unsigned char *key=(unsigned char *)string; - int *data=(int*)malloc(sizeof(int)); int ret=0; + int * data= (int*)malloc(sizeof(int)); *data=value; ret=MESA_htable_add(handle,key,size,data); + if(ret<0) + { + free(data); + } return ret; } int map_str2int(MESA_htable_handle handle,const char* string,int* value) { int *data=NULL; + long cb_ret=0; unsigned int size=strlen(string); - data=(int*)MESA_htable_search(handle,(unsigned char*)string,size); - if(data!=NULL) + + data=(int*)MESA_htable_search_cb(handle,(unsigned char*)string,size, + read_map_val,value,&cb_ret); + +// data=(int*)MESA_htable_search(handle,(unsigned char*)string,size); + if(cb_ret>0) { - *value=*data; return 1; } else diff --git a/test/maat_json.json b/test/maat_json.json index 80bf5c2..4ee7c21 100644 --- a/test/maat_json.json +++ b/test/maat_json.json @@ -188,6 +188,34 @@ ] } ] + }, + { + "compile_id": 128, + "service": 1, + "action": 1, + "do_blacklist": 1, + "do_log": 1, + "effective_rage": 0, + "user_region": "anything", + "is_valid": "yes", + "groups": [ + { + "group_name": "group_8", + "regions": [ + { + "table_name": "HTTP_REGION", + "table_type": "expr_plus", + "table_content": { + "district": "URL", + "keywords": "abckkk&123", + "expr_type": "and", + "match_method": "sub", + "format": "uncase plain" + } + } + ] + } + ] } ], "plugin_table": [ diff --git a/test/maat_test.cpp b/test/maat_test.cpp index f52d2ad..ef1b04e 100644 --- a/test/maat_test.cpp +++ b/test/maat_test.cpp @@ -37,26 +37,273 @@ void Maat_read_entry_finish_cb(void* u_para) { return; } +void print_maat_ret(int ret) +{ + switch(ret) + { + case -1: + printf("scan error.\n"); + break; + case -2: + printf("hit current region,but not hit compile rule.\n"); + break; + case 0: + printf("nothing hit\n"); + break; + default://>0 + printf("hit %d rules\n",ret); + break; + } + return; +} +int test_string_full_scan(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int ret=0; + int table_id=0; + struct Maat_rule_t result[4]; + int found_pos[4]; + const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.\n",table_name); + return -1; + } + + ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + result,found_pos, 4, + mid, 0); + print_maat_ret(ret); + return ret; +} +int test_intval_scan(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int table_id=0,ret=0; + int scan_val=2015; + struct Maat_rule_t result[4]; + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.",table_name); + + } + else + { + ret=Maat_scan_intval(feather, table_id, scan_val, result,4,mid, 0); + print_maat_ret(ret); + } + return ret; +} +int test_str_stream_scan(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int table_id=0,ret=0; + struct Maat_rule_t result[4]; + const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.\n",table_name); + return -1; + } + struct Maat_hit_detail_t *hit_detail=(struct Maat_hit_detail_t *)malloc(sizeof(struct Maat_hit_detail_t)*10); + stream_para_t sp=Maat_stream_scan_string_start(feather,table_id,0); + int detail_ret=0; + if(sp==NULL) + { + printf("stream scan start failed.\n"); + return -1; + } + ret=Maat_stream_scan_string_detail(&sp,CHARSET_NONE,"www.cyberessays.com", strlen("www.cyberessays.com") + ,result,4,hit_detail,10 + ,&detail_ret,mid); + ret=Maat_stream_scan_string_detail(&sp,CHARSET_NONE,scan_data, strlen(scan_data) + ,result,4,hit_detail,10 + ,&detail_ret,mid); + Maat_stream_scan_string_end(&sp); + free(hit_detail); + print_maat_ret(ret); + return ret; +} +int test_ipv4_scan(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int table_id=0,ret=0; + struct Maat_rule_t result[4]; + struct ipaddr ipv4_addr; + struct stream_tuple4_v4 v4_addr; + ipv4_addr.addrtype=ADDR_TYPE_IPV4; + inet_pton(AF_INET,"10.0.6.205",&(v4_addr.saddr)); + v4_addr.source=htons(50001); + inet_pton(AF_INET,"10.0.6.201",&(v4_addr.daddr)); + v4_addr.dest=htons(80); + ipv4_addr.v4=&v4_addr; + + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.\n",table_name); + + } + else + { + ret=Maat_scan_proto_addr(feather,table_id,&ipv4_addr,6,result,4, mid,0); + if(ret>0) + { + printf("ipv4 scan hit compile rule id %d.\n",result[0].config_id); + } + } + return ret; +} +int test_ipv6_scan(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int table_id=0,ret=0; + struct Maat_rule_t result[4]; + struct ipaddr ipv6_addr; + struct stream_tuple4_v6 v6_addr; + + ipv6_addr.addrtype=ADDR_TYPE_IPV6; + inet_pton(AF_INET6,"2001:da8:205:1::101",&(v6_addr.saddr)); + v6_addr.source=htons(50001); + inet_pton(AF_INET6,"2001:da8:205:1::102",&(v6_addr.daddr)); + v6_addr.dest=htons(80); + ipv6_addr.v6=&v6_addr; + + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.\n",table_name); + + } + else + { + ret=Maat_scan_proto_addr(feather,table_id,&ipv6_addr,6,result,4, mid,0); + if(ret==-2) + { + printf("ipv6 scan hit region.\n"); + } + else + { + printf("ipv6 scan result:%d ,shoulde be -2.\n",ret); + + } + } + return ret; +} +int test_digest_scan(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int table_id=0,ret=0; + const char* digest_test_file="./digest_test.data"; + struct stat digest_fstat; + unsigned long long read_size=0,scan_offset=0; + char digest_test_buff[4096]={0}; + + struct Maat_rule_t result[4]; + stream_para_t sp=NULL; + table_id=Maat_table_register(feather, table_name); + if(table_id<0) + { + printf("registe table %s error.\n",table_name); + return 0; + } + ret=stat(digest_test_file,&digest_fstat); + if(ret!=0) + { + printf("fstat %s error.\n",digest_test_file); + return 0; + } + FILE* fp=fopen(digest_test_file,"r"); + if(fp!=NULL) + { + sp=Maat_stream_scan_digest_start(feather, table_id, digest_fstat.st_size, 0); + while(0==feof(fp)) + { + read_size=fread(digest_test_buff,1,sizeof(digest_test_buff),fp); + ret=Maat_stream_scan_digest(&sp, digest_test_buff, read_size, scan_offset, result,4,mid); + scan_offset+=read_size; + if(ret>0) + { + printf("digest scan hit %d.\n",result[0].config_id); + + } + } + fclose(fp); + } + else + { + printf("fopen %s error.\n",digest_test_file); + } + Maat_stream_scan_string_end(&sp); + return ret; +} +int test_plugin_table(Maat_feather_t feather,const char* table_name,void* logger) +{ + int table_id=0,ret=0; + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.\n",table_name); + } + else + { + ret=Maat_table_callback_register(feather, table_id, + Maat_read_entry_start_cb, + Maat_read_entry_cb, + Maat_read_entry_finish_cb, + logger); + if(ret<0) + { + printf("Maat callback register table %s error.\n",table_name); + } + } + return ret; +} +int test_expr_plus(Maat_feather_t feather,const char* table_name,scan_status_t* mid) +{ + int ret=0; + int table_id=0; + struct Maat_rule_t result[4]; + int found_pos[4]; + const char* region_name="URL"; + const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; + table_id=Maat_table_register(feather,table_name); + if(table_id==-1) + { + printf("Database table %s register failed.\n",table_name); + return -1; + } + ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + result,found_pos, 4, + mid, 0); + if(ret>0) + { + printf("Should not hit without set district.\n"); + return -1; + } + ret=Maat_set_scan_status(feather, mid, MAAT_SET_SCAN_DISTRICT,region_name,strlen(region_name)+1); + if(ret<0) + { + printf("set MAAT_SET_SCAN_DISTRICT failed.\n"); + return -1; + } + ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + result,found_pos, 4, + mid, 0); + if(ret>0) + { + printf("Hit expr_puls rule %d.\n",result[0].config_id); + } + return ret; + +} int main(int argc,char* argv[]) { Maat_feather_t feather=NULL; - int cb_table_id=-1,url_scan_table_id=-1,size_scan_table_id=-1,ip_scan_table_id=-1,digest_scan_table_id=-1; - int ret=-1; int g_iThreadNum=4; const char* table_info_path="./table_info.conf"; const char* json_path="./maat_json.json"; // const char* ful_cfg_dir="./maat_json.json_iris_tmp/index"; // const char* inc_cfg_dir="./rules/inc/index"; const char* log_file="./test.log"; - const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; - const char* digest_test_file="./digest_test.data"; const char* stat_file="./scan_staus.log"; - struct stat digest_fstat; - unsigned long long read_size=0,scan_offset=0; - char digest_test_buff[4096]={0}; - int scan_val=2015; - struct Maat_rule_t result[4]; - int found_pos[4]; int scan_detail=0; scan_status_t mid=NULL; void *logger=MESA_create_runtime_log_handle(log_file,0); @@ -80,178 +327,30 @@ int main(int argc,char* argv[]) printf("Maat initial error, see %s\n",log_file); return -1; } + test_plugin_table(feather, "QD_ENTRY_INFO",logger); - cb_table_id=Maat_table_register(feather,"QD_ENTRY_INFO"); - if(cb_table_id==-1) - { - printf("Database table QD_ENTRY_INFO register failed."); - } - else - { - ret=Maat_table_callback_register(feather, cb_table_id, - Maat_read_entry_start_cb, - Maat_read_entry_cb, - Maat_read_entry_finish_cb, - logger); - if(ret<0) - { - printf("Maat callback register table QD_ENTRY_INFO error."); - } - } - - url_scan_table_id=Maat_table_register(feather,"HTTP_URL"); - if(url_scan_table_id==-1) - { - printf("Database table HTTP_URL register failed."); - - } - else - { - ret=Maat_full_scan_string(feather, url_scan_table_id,CHARSET_GBK, scan_data, strlen(scan_data), - result,found_pos, 4, - &mid, 0); - switch(ret) - { - case -1: - printf("scan error.\n"); - break; - case -2: - printf("hit current region,but not hit compile rule.\n"); - break; - case 0: - printf("nothing hit\n"); - break; - default://>0 - printf("hit %d rules\n",ret); - break; - } - } + test_string_full_scan(feather, "HTTP_URL", &mid); + //not clean status here, to test_ipv4_scan make hit compile rule. + test_ipv4_scan(feather, "IP_CONFIG", &mid); Maat_clean_status(&mid); - size_scan_table_id=Maat_table_register(feather,"CONTENT_SIZE"); - if(size_scan_table_id==-1) - { - printf("Database table CONTENT_SIZE register failed."); - - } - else - { - ret=Maat_scan_intval(feather, size_scan_table_id, scan_val, result,4,&mid, 0); - switch(ret) - { - case -1: - printf("scan error.\n"); - break; - case -2: - printf("hit current region,but not hit compile rule.\n"); - break; - case 0: - printf("nothing hit\n"); - break; - default://>0 - printf("hit %d rules\n",ret); - break; - } - } - sleep(2); - Maat_clean_status(&mid); - struct Maat_hit_detail_t *hit_detail=(struct Maat_hit_detail_t *)malloc(sizeof(struct Maat_hit_detail_t)*10); - stream_para_t sp=Maat_stream_scan_string_start(feather,url_scan_table_id,0); - int detail_ret=0; - if(sp==NULL) - { - printf("stream scan start failed.\n"); - return -1; - } - ret=Maat_stream_scan_string_detail(&sp,CHARSET_NONE,"www.cyberessays.com", strlen("www.cyberessays.com") - ,result,4,hit_detail,10 - ,&detail_ret,&mid); - ret=Maat_stream_scan_string_detail(&sp,CHARSET_NONE,scan_data, strlen(scan_data) - ,result,4,hit_detail,10 - ,&detail_ret,&mid); - Maat_stream_scan_string_end(&sp); - struct ipaddr ipv4_addr,ipv6_addr; - struct stream_tuple4_v4 v4_addr; - struct stream_tuple4_v6 v6_addr; - ipv4_addr.addrtype=ADDR_TYPE_IPV4; - inet_pton(AF_INET,"10.0.6.205",&(v4_addr.saddr)); - v4_addr.source=htons(50001); - inet_pton(AF_INET,"10.0.6.201",&(v4_addr.daddr)); - v4_addr.dest=htons(80); - ipv4_addr.v4=&v4_addr; - ip_scan_table_id=Maat_table_register(feather,"IP_CONFIG"); - if(ip_scan_table_id==-1) - { - printf("Database table IP_CONFIG register failed."); - - } - else - { - ret=Maat_scan_proto_addr(feather,ip_scan_table_id,&ipv4_addr,6,result,4, &mid,0); - if(ret>0) - { - printf("ipv4 scan hit compile rule id %d.\n",result[0].config_id); - } - } + test_intval_scan(feather,"CONTENT_SIZE" , &mid); Maat_clean_status(&mid); - ipv6_addr.addrtype=ADDR_TYPE_IPV6; - inet_pton(AF_INET6,"2001:da8:205:1::101",&(v6_addr.saddr)); - v6_addr.source=htons(50001); - inet_pton(AF_INET6,"2001:da8:205:1::102",&(v6_addr.daddr)); - v6_addr.dest=htons(80); - ipv6_addr.v6=&v6_addr; - if(ip_scan_table_id>=0) - { - ret=Maat_scan_proto_addr(feather,ip_scan_table_id,&ipv6_addr,6,result,4, &mid,0); - if(ret==-2) - { - printf("ipv6 scan hit region.\n"); - } - else - { - printf("ipv6 scan result:%d ,shoulde be -2.\n",ret); - } - } - Maat_clean_status(&mid); - digest_scan_table_id=Maat_table_register(feather, "FILE_DIGEST"); - if(digest_scan_table_id<0) - { - printf("registe table FILE_DIGEST error.\n"); - return 0; - } - ret=stat(digest_test_file,&digest_fstat); - if(ret!=0) - { - printf("fstat %s error.\n",digest_test_file); - return 0; - } - FILE* fp=fopen(digest_test_file,"r"); - if(fp!=NULL) - { - sp=Maat_stream_scan_digest_start(feather, digest_scan_table_id, digest_fstat.st_size, 0); - while(0==feof(fp)) - { - read_size=fread(digest_test_buff,1,sizeof(digest_test_buff),fp); - ret=Maat_stream_scan_digest(&sp, digest_test_buff, read_size, scan_offset, result,4,&mid); - scan_offset+=read_size; - if(ret>0) - { - printf("digest scan hit %d.\n",result[0].config_id); - } - } - fclose(fp); - } - else - { - printf("fopen %s error.\n",digest_test_file); - } - Maat_stream_scan_string_end(&sp); + test_ipv6_scan(feather, "IP_CONFIG", &mid); Maat_clean_status(&mid); + + test_digest_scan(feather,"FILE_DIGEST", &mid); + Maat_clean_status(&mid); + + test_expr_plus(feather, "HTTP_REGION", &mid); + Maat_clean_status(&mid); + sleep(4); + Maat_burn_feather(feather); - free(hit_detail); + return 0; } diff --git a/test/table_info.conf b/test/table_info.conf index 7ce9a2e..0facdd5 100644 --- a/test/table_info.conf +++ b/test/table_info.conf @@ -1,7 +1,7 @@ #each collumn seperate with '\t' #id (0~65535) #name string -#type one of ip,expr,digest,intval,compile or plugin +#type one of ip,expr,expr_plus,digest,intval,compile or plugin #src_charset one of GBK,BIG5,UNICODE,UTF8 #dst_charset combined by GBK,BIG5,UNICODE,UTF8,seperate with '/' #do_merege yes or no @@ -14,3 +14,4 @@ 5 CONTENT_SIZE intval GBK GBK no 0 6 QD_ENTRY_INFO plugin GBK GBK no 0 7 FILE_DIGEST digest GBK GBK no 0 +8 HTTP_REGION expr_plus GBK GBK no 0 From dc5713123a245b5449c059dbc2ff7630dab112a9 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Mon, 15 Feb 2016 09:28:47 +0800 Subject: [PATCH 03/31] Enforce parameter check in Maat_initiate function. --- inc/Maat_rule.h | 2 +- src/entry/Maat_api.cpp | 28 ++++++++++++++++++++++------ test/maat_test.cpp | 4 ++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/inc/Maat_rule.h b/inc/Maat_rule.h index 42a13d5..0f595fc 100644 --- a/inc/Maat_rule.h +++ b/inc/Maat_rule.h @@ -155,7 +155,7 @@ enum MAAT_SCAN_OPT MAAT_SET_SCAN_DISTRICT=1 //VALUE is a const char*,MUST end with '\0',SIZE= strlen(string+'\0')+1.DEFAULT: no default. }; //return 0 if success, return -1 when failed; -int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCAN_OPT,const void* value,int size); +int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCAN_OPT type,const void* value,int size); //Return hit rule number, return -1 when error occurs,return -2 when hit current region //mid MUST set NULL before fist call diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index a01e9d1..b720d1b 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -518,6 +518,13 @@ int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const vo int Maat_initiate_feather(Maat_feather_t feather) { _Maat_feather_t* _feather=(_Maat_feather_t*)feather; + if(strlen(_feather->full_dir)==0) + { + MESA_handle_runtime_log(_feather->logger,RLOG_LV_FATAL,maat_module , + "At initiation: NO FULL_CFG_DIR or JSON_FILE_PATH. "); + + return -1; + } config_monitor_traverse(_feather->maat_version, _feather->full_dir, maat_start_cb, @@ -540,9 +547,19 @@ int Maat_initiate_feather(Maat_feather_t feather) } if(strlen(_feather->stat_file)==0) { - _feather->perf_on=0; + if(_feather->stat_on==1) + { + MESA_handle_runtime_log(_feather->logger,RLOG_LV_FATAL,maat_module , + "At initiation: MAAT_OPT_STAT_FILE_PATH not set,TURN OFF STAT trigger."); + } _feather->stat_on=0; } + if(_feather->stat_on==0&&_feather->perf_on==1) + { + MESA_handle_runtime_log(_feather->logger,RLOG_LV_FATAL,maat_module , + "At initiation: STAT tirigger OFF, TURN OFF PERF trigger."); + _feather->perf_on=0; + } maat_stat_init(_feather); pthread_t cfg_mon_t; @@ -1382,7 +1399,7 @@ int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCA { struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _OUTER_scan_status_t* _mid=NULL; - int ret=0,map_ret=-1; + int map_ret=-1; _mid=grab_mid(mid,_feather, 0, 0); if(*mid==NULL) { @@ -1395,16 +1412,15 @@ int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCA map_ret=map_str2int(_feather->scanner->district_map,(const char*)value,&(_mid->district_id)); if(map_ret<0) { - //May be the district have not effect yet. + //May be the district not effected yet. } _mid->is_set_district=1; - ret=0; break; default: - ret=-1; + return -1; break; } - return ret; + return 0; } void Maat_clean_status(scan_status_t* mid) { diff --git a/test/maat_test.cpp b/test/maat_test.cpp index ef1b04e..f9943b2 100644 --- a/test/maat_test.cpp +++ b/test/maat_test.cpp @@ -275,7 +275,7 @@ int test_expr_plus(Maat_feather_t feather,const char* table_name,scan_status_t* mid, 0); if(ret>0) { - printf("Should not hit without set district.\n"); + printf("Should not hit without setting district.\n"); return -1; } ret=Maat_set_scan_status(feather, mid, MAAT_SET_SCAN_DISTRICT,region_name,strlen(region_name)+1); @@ -289,7 +289,7 @@ int test_expr_plus(Maat_feather_t feather,const char* table_name,scan_status_t* mid, 0); if(ret>0) { - printf("Hit expr_puls rule %d.\n",result[0].config_id); + printf("Hit expr_plus rule %d.\n",result[0].config_id); } return ret; From a6ef5b16d124380dd65e641719f3bef31ac83a29 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Thu, 18 Feb 2016 09:58:01 +0800 Subject: [PATCH 04/31] =?UTF-8?q?=E6=8F=90=E9=AB=98=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=BE=93=E5=87=BA=E7=9A=84=E5=8F=AF=E8=AF=BB?= =?UTF-8?q?=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 4 +++- src/entry/Maat_stat.cpp | 13 +++++++++++-- src/inc_internal/field_stat.h | 3 ++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 92a5e4c..6c8fcb0 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -2384,9 +2384,11 @@ void *thread_rule_monitor(void *arg) const char* inc_cfg_dir=(const char*)feather->inc_dir; struct _Maat_scanner_t* old_scanner=NULL; long expr_wait_q_cnt=0; + int scan_dir_cnt=0; while(feather->still_working) { usleep(feather->scan_interval_ms*1000); + scan_dir_cnt++; config_monitor_traverse(feather->maat_version, inc_cfg_dir, maat_start_cb, @@ -2424,7 +2426,7 @@ void *thread_rule_monitor(void *arg) } } garbage_bury(feather->garbage_q,feather->logger); - if(feather->stat_on==1) + if(feather->stat_on==1&&scan_dir_cnt%2==0)//output every 2 seconds { maat_stat_output(feather); } diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index 2b05e77..828c9ae 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -1,5 +1,5 @@ #include "Maat_rule_internal.h" -#include "field_stat.h" +#include enum MAAT_FS_STATUS{ STATUS_VERSION=0, STATUS_TABLE_NUM, @@ -40,7 +40,7 @@ void maat_stat_init(struct _Maat_feather_t* feather) feather->fs_column_id[COLUMN_TABLE_RULE_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"rule"); feather->fs_column_id[COLUMN_TABLE_REGEX_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"regex"); feather->fs_column_id[COLUMN_TABLE_STREAM_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"stream"); - feather->fs_column_id[COLUMN_TABLE_SCAN_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"scan_cps"); + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"IN_Tps"); feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"IN_Bps"); if(feather->perf_on==1) { @@ -50,9 +50,17 @@ void maat_stat_init(struct _Maat_feather_t* feather) FS_register_ratio(feather->stat_handle, feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES], feather->fs_column_id[COLUMN_TABLE_CPU_TIME], + 1000000, //microsecond to second FS_STYLE_COLUMN, FS_CALC_SPEED, "PROC_Bps"); + FS_register_ratio(feather->stat_handle, + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], + feather->fs_column_id[COLUMN_TABLE_CPU_TIME], + 1000000, //microsecond to second + FS_STYLE_COLUMN, + FS_CALC_SPEED, + "PROC_Tps"); } feather->fs_column_id[COLUMN_TABLE_HIT_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"hit_cnt"); value=feather->fs_column_id[COLUMN_TABLE_HIT_CNT]; @@ -60,6 +68,7 @@ void maat_stat_init(struct _Maat_feather_t* feather) FS_register_ratio(feather->stat_handle, feather->fs_column_id[COLUMN_TABLE_HIT_CNT], feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], + 1, FS_STYLE_COLUMN, FS_CALC_SPEED, "hit_rate"); diff --git a/src/inc_internal/field_stat.h b/src/inc_internal/field_stat.h index 07e8a5f..6bdf657 100644 --- a/src/inc_internal/field_stat.h +++ b/src/inc_internal/field_stat.h @@ -49,7 +49,8 @@ void FS_stop(screen_stat_handle_t* handle); int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); //numerator_id and denominator_id must be column/field/status style. -int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); +//scaling: negative value: zoom in; positive value: zoom out; +int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,int scaling,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name); //id: when id's type is FIELD , column_id is ignore. int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value); From ab8a55678c5ad2ceb5df2ff4ba2c8d1a1b7e8d21 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Thu, 18 Feb 2016 14:53:06 +0800 Subject: [PATCH 05/31] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E3=80=8Agettimeofday()?= =?UTF-8?q?=20should=20never=20be=20used=20to=20measure=20time=E3=80=8B?= =?UTF-8?q?=E7=9A=84=E5=BB=BA=E8=AE=AE=EF=BC=8C=E7=94=A8clock=5Fgettime?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2gettimeofday=E3=80=82=E5=A2=9E=E5=8A=A0active?= =?UTF-8?q?=5Fthread=E7=9A=84=E7=BB=9F=E8=AE=A1=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 69 +++++++++++++++++++++++----------- src/entry/Maat_rule.cpp | 22 ++++------- src/entry/Maat_rule_internal.h | 9 +++-- src/entry/Maat_stat.cpp | 28 ++++++++++---- src/entry/Makefile | 2 +- src/entry/aligment_int64.h | 43 +++++++++++++++++++++ 6 files changed, 125 insertions(+), 48 deletions(-) create mode 100644 src/entry/aligment_int64.h diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index b720d1b..bd5b1aa 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -9,6 +9,7 @@ #include "Maat_rule.h" #include "Maat_rule_internal.h" #include "dynamic_array.h" +#include "aligment_int64.h" #include "config_monitor.h" #include "map_str2int.h" #include "rulescan.h" @@ -42,14 +43,13 @@ struct _Maat_table_info_t * acqurie_table(struct _Maat_feather_t* _feather,int t } inline void INC_SCANNER_REF(_Maat_scanner_t*scanner,int thread_num) { - int offset=(CPU_CACHE_ALIGMENT/sizeof(int))*thread_num; - scanner->ref_cnt[offset]++; + aligment_int64_array_add(scanner->ref_cnt, thread_num, 1); return; } inline void DEC_SCANNER_REF(_Maat_scanner_t*scanner,int thread_num) { - int offset=(CPU_CACHE_ALIGMENT/sizeof(int))*thread_num; - scanner->ref_cnt[offset]--; + + aligment_int64_array_add(scanner->ref_cnt, thread_num, -1); return; } @@ -434,6 +434,7 @@ Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* feather->garbage_q=MESA_lqueue_create(0,0); feather->effect_interval_ms=60*1000; feather->scan_interval_ms=1*1000; + feather->thread_call_cnt=aligment_int64_array_alloc(max_thread_num); return feather; } int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size) @@ -714,10 +715,10 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id scan_result_t *region_result=NULL; _compile_result_t compile_result[rule_num];//dynamic array struct _Maat_table_info_t *p_table=NULL; - struct timeval start,end; + struct timespec start,end; if(_feather->perf_on==1) { - gettimeofday(&start,NULL); + clock_gettime(CLOCK_MONOTONIC,&start); } _mid=grab_mid(mid,_feather, thread_num, 0); p_table=acqurie_table(_feather, table_id,TABLE_TYPE_EXPR); @@ -741,7 +742,7 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id { sub_type=make_sub_type(table_id,charset,0); } - + aligment_int64_array_add(_feather->thread_call_cnt, thread_num, 1); scan_data_t scan_data; scan_data.text_data.text=data; scan_data.text_data.tlen=data_len; @@ -800,9 +801,14 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id DEC_SCANNER_REF(my_scanner, thread_num); if(_feather->perf_on==1) { - gettimeofday(&end,NULL); + clock_gettime(CLOCK_MONOTONIC,&end); maat_stat_table(p_table,data_len,&start, &end); } + else + { + maat_stat_table(p_table,data_len,NULL, NULL); + } + if(compile_ret==0&&hit_region_cnt>0) { return -2; @@ -837,10 +843,10 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id intval_scan_data.sub_type=make_sub_type(table_id,CHARSET_NONE, 0); intval_scan_data.int_data=intval; _Maat_table_info_t* p_table=NULL; - struct timeval start,end; + struct timespec start,end; if(_feather->perf_on==1) { - gettimeofday(&start,NULL); + clock_gettime(CLOCK_MONOTONIC,&start); } p_table=acqurie_table(_feather,table_id,TABLE_TYPE_INTVAL); if(p_table==NULL) @@ -856,6 +862,7 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id { return 0; } + aligment_int64_array_add(_feather->thread_call_cnt, thread_num, 1); region_result=my_scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*thread_num; @@ -879,9 +886,13 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id DEC_SCANNER_REF(my_scanner,thread_num); if(_feather->perf_on==1) { - gettimeofday(&end,NULL); + clock_gettime(CLOCK_MONOTONIC,&end); maat_stat_table(p_table,0,&start, &end); } + else + { + maat_stat_table(p_table,0,NULL, NULL); + } if(compile_ret==0&®ion_ret>0) { return -2; @@ -904,10 +915,10 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id struct _Maat_feather_t* _feather=(_Maat_feather_t*)feather; struct _Maat_scanner_t* my_scanner=NULL; - struct timeval start,end; + struct timespec start,end; if(_feather->perf_on==1) { - gettimeofday(&start,NULL); + clock_gettime(CLOCK_MONOTONIC,&start); } p_table=acqurie_table(_feather, table_id, TABLE_TYPE_IP); if(p_table==NULL) @@ -923,6 +934,8 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id { return 0; } + aligment_int64_array_add(_feather->thread_call_cnt, thread_num, 1); + ip_scan_data.rule_type=RULETYPE_IPv4; ip_scan_data.sub_type=make_sub_type(table_id,CHARSET_NONE, 0); switch(addr->addrtype) @@ -970,9 +983,13 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id DEC_SCANNER_REF(my_scanner,thread_num); if(_feather->perf_on==1) { - gettimeofday(&end,NULL); + clock_gettime(CLOCK_MONOTONIC,&end); maat_stat_table(p_table,0,&start, &end); } + else + { + maat_stat_table(p_table,0,NULL, NULL); + } if(compile_ret==0&®ion_ret>0) { return -2; @@ -1053,10 +1070,10 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para _compile_result_t compile_result[rule_num];//dynamic array scan_data_t region_scan_data; _Maat_table_info_t* p_table=NULL; - struct timeval start,end; + struct timespec start,end; if(sp->feather->perf_on==1) { - gettimeofday(&start,NULL); + clock_gettime(CLOCK_MONOTONIC,&start); } _mid=grab_mid(mid, sp->feather, sp->thread_num,0); if(data==NULL||data_len==0) @@ -1080,6 +1097,8 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para { return -1; } + aligment_int64_array_add(sp->feather->thread_call_cnt, sp->thread_num, 1); + region_result=scanner->region_rslt_buff+MAX_SCANNER_HIT_NUM*sp->thread_num; *detail_ret=0; if(sp->do_merge==1) @@ -1186,9 +1205,13 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para } if(sp->feather->perf_on==1) { - gettimeofday(&end,NULL); + clock_gettime(CLOCK_MONOTONIC,&end); maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end); } + else + { + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,NULL, NULL); + } if(compile_ret==0&&hit_region_cnt>0) { return -2; @@ -1309,15 +1332,16 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int char* digest_buff=NULL; struct _OUTER_scan_status_t* _mid=NULL; pthread_rwlock_t *GIE_rwlock=&(sp->feather->scanner->digest_rwlock[sp->table_id]); - struct timeval start,end; + struct timespec start,end; if(sp->feather->perf_on==1) { - gettimeofday(&start,NULL); + clock_gettime(CLOCK_MONOTONIC,&start); } if(sp->acc_scan_len+(unsigned long long)data_len > sp->total_len) { return 0; } + aligment_int64_array_add(sp->feather->thread_call_cnt, sp->thread_num, 1); pthread_mutex_lock(&(sp->fuzzy_mutex)); sp->acc_scan_len+=fuzzy_feed(sp->fuzzy_hash_handle, data, (unsigned int)data_len,offset); pthread_mutex_unlock(&(sp->fuzzy_mutex)); @@ -1363,10 +1387,13 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int } if(sp->feather->perf_on==1) { - gettimeofday(&end,NULL); + clock_gettime(CLOCK_MONOTONIC,&end); maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end); } - + else + { + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,NULL, NULL); + } if(compile_ret==0&&hit_region_cnt>0) { return -2; diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 6c8fcb0..68b3d98 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -17,6 +17,7 @@ #include "Maat_rule_internal.h" #include "json2iris.h" #include "dynamic_array.h" +#include "aligment_int64.h" #include "config_monitor.h" #include "map_str2int.h" @@ -218,17 +219,7 @@ int cnt_maskbits(struct in6_addr mask) } return bits_cnt; } -int aligment_int_array_sum(int * array,int size) -{ - int sum=0,i=0; - int offset=0; - for(i=0;icfg_num=0; scanner->max_thread_num=scan_thread_num; //optimized for CPU cache_alignment 64 - scanner->ref_cnt=(int*)calloc(CPU_CACHE_ALIGMENT,scan_thread_num); + scanner->ref_cnt=aligment_int64_array_alloc(scan_thread_num); scanner->region_update_q=MESA_lqueue_create(0,0); scanner->region=rulescan_initialize(scan_thread_num); rulescan_set_param(scanner->region,rs_scan_type); @@ -2109,7 +2100,7 @@ void garbage_bury(MESA_lqueue_head garbage_q,void *logger) long data_size=0; const long q_cnt=MESA_lqueue_get_count(garbage_q); int i=0,bury_cnt=0; - int ref_cnt=0; + long long ref_cnt=0; int have_timeout=0; time_t now=time(NULL); for(i=0;igroup_rule); break; case GARBAGE_SCANNER: - ref_cnt=aligment_int_array_sum(bag->scanner->ref_cnt,bag->scanner->max_thread_num); + ref_cnt=aligment_int64_array_sum(bag->scanner->ref_cnt,bag->scanner->max_thread_num); if(ref_cnt==0) { @@ -2142,7 +2133,7 @@ void garbage_bury(MESA_lqueue_head garbage_q,void *logger) else { MESA_handle_runtime_log(logger,RLOG_LV_INFO,maat_module, - "scanner %p version %d force destroyed,ref_cnt %d.", + "scanner %p version %d force destroyed,ref_cnt %lld.", bag->scanner,bag->scanner->version,ref_cnt); } @@ -2459,6 +2450,7 @@ void *thread_rule_monitor(void *arg) free(feather->p_table_info[i]); feather->p_table_info[i]=NULL; } + free(feather->thread_call_cnt); free(feather); return NULL; } diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index a2b223b..26c01af 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -49,7 +49,7 @@ typedef int atomic_t; #define MAX_FAILED_NUM 128 -#define MAX_MAAT_STAT_NUM 64 +#define MAX_MAAT_STAT_NUM 64 #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif @@ -234,7 +234,7 @@ struct _Maat_table_info_t //for stat>>>>>>>> int stat_line_id; long long scan_cnt; - long long scan_cpu_time; //microseconds + long long scan_cpu_time; //nano long long input_bytes; long long stream_num; long long hit_cnt; @@ -292,7 +292,7 @@ struct _Maat_scanner_t { int version; time_t last_update_time; - int *ref_cnt; //optimized for cache_alignment 64 + long long *ref_cnt; //optimized for cache_alignment 64 rule_scanner_t region; pthread_rwlock_t digest_rwlock[MAX_TABLE_NUM]; GIE_handle_t* digest_handle[MAX_TABLE_NUM]; @@ -340,6 +340,7 @@ struct _Maat_feather_t long long outer_mid_cnt; long long inner_mid_cnt; long long hit_cnt; + long long *thread_call_cnt;//size indicate by scan_thread_num, }; struct _maat_garbage_t { @@ -374,7 +375,7 @@ inline void ipv6_ntoh(unsigned int *v6_addr) return; } void maat_stat_init(struct _Maat_feather_t* feather); -void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timeval* start, struct timeval* end); +void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timespec* start, struct timespec* end); void maat_stat_output(struct _Maat_feather_t* feather); diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index 828c9ae..2ade65c 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -1,7 +1,10 @@ #include "Maat_rule_internal.h" +#include "aligment_int64.h" +#include #include enum MAAT_FS_STATUS{ STATUS_VERSION=0, + STATUS_THRED_NUM, STATUS_TABLE_NUM, STATUS_OUTER_MID_NUM, STATUS_INNER_MID_NUM, @@ -32,6 +35,7 @@ void maat_stat_init(struct _Maat_feather_t* feather) FS_set_para(feather->stat_handle, CREATE_THREAD, &value, sizeof(value)); feather->fs_status_id[STATUS_VERSION]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"version"); + feather->fs_status_id[STATUS_THRED_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"active_thread"); feather->fs_status_id[STATUS_TABLE_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"table_num"); feather->fs_status_id[STATUS_OUTER_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"outer_mid"); feather->fs_status_id[STATUS_INNER_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"inner_mid"); @@ -40,7 +44,6 @@ void maat_stat_init(struct _Maat_feather_t* feather) feather->fs_column_id[COLUMN_TABLE_RULE_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"rule"); feather->fs_column_id[COLUMN_TABLE_REGEX_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"regex"); feather->fs_column_id[COLUMN_TABLE_STREAM_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"stream"); - feather->fs_column_id[COLUMN_TABLE_SCAN_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"IN_Tps"); feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"IN_Bps"); if(feather->perf_on==1) { @@ -54,6 +57,10 @@ void maat_stat_init(struct _Maat_feather_t* feather) FS_STYLE_COLUMN, FS_CALC_SPEED, "PROC_Bps"); + } + feather->fs_column_id[COLUMN_TABLE_SCAN_CNT]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_SPEED,"IN_Tps"); + if(feather->perf_on==1) + { FS_register_ratio(feather->stat_handle, feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], feather->fs_column_id[COLUMN_TABLE_CPU_TIME], @@ -87,22 +94,28 @@ void maat_stat_init(struct _Maat_feather_t* feather) FS_start(feather->stat_handle); return; } -void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timeval* start, struct timeval* end) +void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timespec* start, struct timespec* end) { p_table->scan_cnt++; p_table->input_bytes+=scan_len; - p_table->scan_cpu_time+=(end->tv_sec-start->tv_sec)*1000000+end->tv_usec-start->tv_usec; + if(start!=NULL&&end!=NULL) + { + p_table->scan_cpu_time+=(end->tv_sec-start->tv_sec)*1000000000+end->tv_nsec-start->tv_nsec; + } return; } void maat_stat_output(struct _Maat_feather_t* feather) { long value=0; long long total_cfg_num=0, total_input_bytes=0, total_regex_num=0; - long long total_scan_cnt=0, total_cpu_time=0,total_stream_cnt=0; + long long total_scan_cnt=0, total_cpu_time=0,total_stream_cnt=0,active_thread_num=0; int i=0; + time_t now; struct _Maat_table_info_t* p_table=NULL; - + time(&now); + active_thread_num=aligment_int64_array_cnt(feather->thread_call_cnt, feather->scan_thread_num); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_VERSION], 0,FS_OP_SET,feather->maat_version); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_THRED_NUM], 0,FS_OP_SET,active_thread_num); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TABLE_NUM], 0,FS_OP_SET,feather->table_cnt); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_OUTER_MID_NUM], 0,FS_OP_SET,feather->outer_mid_cnt); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_INNER_MID_NUM], 0,FS_OP_SET,feather->inner_mid_cnt); @@ -161,7 +174,7 @@ void maat_stat_output(struct _Maat_feather_t* feather) p_table->stat_line_id, feather->fs_column_id[COLUMN_TABLE_CPU_TIME], FS_OP_ADD, - p_table->scan_cpu_time); + p_table->scan_cpu_time/1000); total_cpu_time+=p_table->scan_cpu_time; p_table->scan_cpu_time=0; } @@ -204,7 +217,8 @@ void maat_stat_output(struct _Maat_feather_t* feather) feather->total_stat_id, feather->fs_column_id[COLUMN_TABLE_CPU_TIME], FS_OP_ADD, - total_cpu_time); + total_cpu_time/1000); + printf("%lld us %s",total_cpu_time/1000,ctime(&now)); } FS_operate(feather->stat_handle, feather->total_stat_id, diff --git a/src/entry/Makefile b/src/entry/Makefile index 8a8fcd7..4ba933e 100644 --- a/src/entry/Makefile +++ b/src/entry/Makefile @@ -6,7 +6,7 @@ CCC = g++ CFLAGS = -Wall -g -fPIC CFLAGS += $(OPTFLAGS) LDDICTATOR = -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,free -Wl,-wrap,realloc -LDFLAGS = -lMESA_handle_logger -lMESA_htable -lpthread -lm -lrulescan -lpcre -lMESA_field_stat +LDFLAGS = -lMESA_handle_logger -lMESA_htable -lpthread -lrt -lm -lrulescan -lpcre -lMESA_field_stat #LDFLAGS += $(LDDICTATOR) MAILLIB = ../lib diff --git a/src/entry/aligment_int64.h b/src/entry/aligment_int64.h new file mode 100644 index 0000000..a152593 --- /dev/null +++ b/src/entry/aligment_int64.h @@ -0,0 +1,43 @@ +#ifndef H_ALIGMENT_INT64_H_INCLUDE +#define H_ALIGMENT_INT64_H_INCLUDE + +#include +inline long long *aligment_int64_array_alloc(int size) +{ + long long *ret=NULL; + ret=(long long*)calloc(CPU_CACHE_ALIGMENT,size); + return ret; +} +inline long long aligment_int64_array_sum(long long * array,int size) +{ + long long sum=0; + int offset=0,i=0; + for(i=0;i0) + { + cnt++; + } + } + return cnt; +} +#endif + From ef53a9a33afd1ccd95a28d5570f7511eecc60fb0 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 19 Feb 2016 10:25:23 +0800 Subject: [PATCH 06/31] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E4=BF=A1=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_stat.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index 2ade65c..8908363 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -218,7 +218,6 @@ void maat_stat_output(struct _Maat_feather_t* feather) feather->fs_column_id[COLUMN_TABLE_CPU_TIME], FS_OP_ADD, total_cpu_time/1000); - printf("%lld us %s",total_cpu_time/1000,ctime(&now)); } FS_operate(feather->stat_handle, feather->total_stat_id, From 99ac553d1d6b139e515df13374a27d36783570d3 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 19 Feb 2016 13:13:11 +0800 Subject: [PATCH 07/31] =?UTF-8?q?=E4=B8=8D=E5=86=8D=E7=BB=9F=E8=AE=A1GROUP?= =?UTF-8?q?=E7=B1=BB=E9=85=8D=E7=BD=AE=E7=9A=84=E6=95=B0=E9=87=8F=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E9=81=BF=E5=85=8D=E8=99=9A=E6=8B=9FGROUP=E6=83=85?= =?UTF-8?q?=E5=86=B5=E4=B8=8B=E5=B0=86=E5=85=B6=E7=B4=AF=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E6=99=AE=E9=80=9A=E5=9F=9F=E9=85=8D=E7=BD=AE=E8=A1=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 68b3d98..32376e5 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -1620,7 +1620,8 @@ void update_group_rule(struct _Maat_table_info_t* table,const char* table_line,s if(db_group_rule.is_valid==FALSE) { del_group_rule(table, &db_group_rule,scanner,logger); - table->cfg_num--; + //leave no trace for virtual group rule +// table->cfg_num--; } else { @@ -1636,7 +1637,7 @@ void update_group_rule(struct _Maat_table_info_t* table,const char* table_line,s else { //no need to free db_group_rule,it was saved in scanner->compile_hash - table->cfg_num++; +// table->cfg_num++; } } From a05f374f4d36b75b2c1433f61b5a35570e82e0fa Mon Sep 17 00:00:00 2001 From: zhengchao Date: Mon, 22 Feb 2016 14:10:21 +0800 Subject: [PATCH 08/31] =?UTF-8?q?=E4=BF=AE=E6=94=B9str2int=5Fmap=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E5=AE=89=E5=85=A8=E6=A8=A1=E5=BC=8F=E7=9A=84=E5=B9=B6?= =?UTF-8?q?=E5=8F=91=E9=94=81=E6=95=B0=E9=87=8F=EF=BC=8Cthread=5Fsafe?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/map_str2int.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entry/map_str2int.cpp b/src/entry/map_str2int.cpp index 8cad88d..66ec288 100644 --- a/src/entry/map_str2int.cpp +++ b/src/entry/map_str2int.cpp @@ -22,7 +22,7 @@ MESA_htable_handle map_create(void) MESA_htable_handle string2int_map; MESA_htable_create_args_t hargs; memset(&hargs,0,sizeof(hargs)); - hargs.thread_safe=1; + hargs.thread_safe=8; hargs.hash_slot_size = 4*1024; hargs.max_elem_num = 0; hargs.eliminate_type = HASH_ELIMINATE_ALGO_LRU; From df4f30f62b7ec4fc9978064b7e4a49b580661c8d Mon Sep 17 00:00:00 2001 From: zhengchao Date: Tue, 23 Feb 2016 16:44:39 +0800 Subject: [PATCH 09/31] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index bd5b1aa..27289d1 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -1428,7 +1428,7 @@ int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCA struct _OUTER_scan_status_t* _mid=NULL; int map_ret=-1; _mid=grab_mid(mid,_feather, 0, 0); - if(*mid==NULL) + if(_mid==NULL) { _mid=_make_outer_status(_feather); *mid=_mid; @@ -1439,7 +1439,7 @@ int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCA map_ret=map_str2int(_feather->scanner->district_map,(const char*)value,&(_mid->district_id)); if(map_ret<0) { - //May be the district not effected yet. + //May be the district is not effected yet. } _mid->is_set_district=1; break; From f7b4bc2815d381fe750c6e5e2d183ccbaafecbf5 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 4 Mar 2016 10:57:41 +0800 Subject: [PATCH 10/31] =?UTF-8?q?Maat=5Frule.h=E4=B8=AD=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AE=8F=E5=AE=9A=E4=B9=89=EF=BC=8C=E4=BF=9D=E8=AF=81=E5=BF=85?= =?UTF-8?q?=E9=A1=BB=E4=BD=BF=E7=94=A8C++=E7=BC=96=E8=AF=91=E5=99=A8?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inc/Maat_rule.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inc/Maat_rule.h b/inc/Maat_rule.h index 0f595fc..a6e7be4 100644 --- a/inc/Maat_rule.h +++ b/inc/Maat_rule.h @@ -13,6 +13,9 @@ */ #ifndef H_MAAT_RULE_H_INCLUDE #define H_MAAT_RULE_H_INCLUDE +#ifndef __cplusplus +#error("This file should be compiled with C++ compiler") +#endif #include "stream.h" enum MAAT_CHARSET { From 27100b172779bd645ff592ca51cdde46c556e4a7 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Tue, 8 Mar 2016 14:47:21 +0800 Subject: [PATCH 11/31] =?UTF-8?q?=E5=8A=A0=E5=BC=BA=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E6=89=AB=E6=8F=8F=E8=BE=93=E5=85=A5=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 27289d1..5da7a5e 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -716,6 +716,10 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id _compile_result_t compile_result[rule_num];//dynamic array struct _Maat_table_info_t *p_table=NULL; struct timespec start,end; + if(data==NULL||data_len<=0) + { + return 0; + } if(_feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&start); @@ -1071,15 +1075,16 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para scan_data_t region_scan_data; _Maat_table_info_t* p_table=NULL; struct timespec start,end; + if(data==NULL||data_len<=0) + { + return 0; + } if(sp->feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&start); } _mid=grab_mid(mid, sp->feather, sp->thread_num,0); - if(data==NULL||data_len==0) - { - return 0; - } + if(scanner==NULL) { return 0; From 4006771fca6338b58cffdf4e9d10f531135c2115 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 11 Mar 2016 14:11:31 +0800 Subject: [PATCH 12/31] =?UTF-8?q?=E5=9C=A8ip=E5=9C=B0=E5=9D=80=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E4=B8=AD=E5=A2=9E=E5=8A=A0=E5=B7=B2=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?ipv4/ipv6=E8=A7=84=E5=88=99=E6=95=B0=E7=9A=84=E5=88=A4=E5=AE=9A?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8Drulescan=E8=BE=93=E5=87=BA=E6=8A=A5?= =?UTF-8?q?=E8=AD=A6=E4=BF=A1=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 8 ++++++++ src/entry/Maat_rule.cpp | 16 ++++++++++++++++ src/entry/Maat_rule_internal.h | 12 ++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 5da7a5e..f11f717 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -933,6 +933,14 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id { return 0; } + if(p_table->ipv4_rule_cnt==0&&addr->addrtype==ADDR_TYPE_IPV4) + { + return 0; + } + if(p_table->ipv6_rule_cnt==0&&addr->addrtype==ADDR_TYPE_IPV6) + { + return 0; + } my_scanner=_feather->scanner; if(my_scanner==NULL) { diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 32376e5..f043cf7 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -1870,6 +1870,14 @@ void update_ip_rule(struct _Maat_table_info_t* table,const char* table_line,stru if(ret>0) { table->cfg_num--; + if(ip_rule->addr_type==4) + { + table->ipv4_rule_cnt--; + } + else + { + table->ipv6_rule_cnt--; + } } } else @@ -1885,6 +1893,14 @@ void update_ip_rule(struct _Maat_table_info_t* table,const char* table_line,stru else { table->cfg_num++; + if(ip_rule->addr_type==4) + { + table->ipv4_rule_cnt++; + } + else + { + table->ipv6_rule_cnt++; + } } } error_out: diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index 26c01af..71af01a 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -228,8 +228,16 @@ struct _Maat_table_info_t int do_charset_merge; int cfg_num; int cross_cache_size; - int expr_rule_cnt; //expr_type=0,1,3 - int regex_rule_cnt; //expr_type=2 + union + { + int expr_rule_cnt; //expr_type=0,1,3 + int ipv4_rule_cnt; + }; + union + { + int regex_rule_cnt; //expr_type=2 + int ipv6_rule_cnt; + }; struct _plugin_table_info *cb_info; //for stat>>>>>>>> int stat_line_id; From b8ad5c8d8e348886ebcd54da6a33ce0ac6f0ad9c Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 11 Mar 2016 15:45:26 +0800 Subject: [PATCH 13/31] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=BE=E7=BD=AEMAAT?= =?UTF-8?q?=5FOPT=5FSCAN=5FDETAIL=E6=9C=AA=E7=94=9F=E6=95=88=E7=9A=84bug?= =?UTF-8?q?=EF=BC=9B=E5=9C=A8rulescan=E4=B8=8D=E8=BF=94=E5=9B=9E=E5=91=BD?= =?UTF-8?q?=E4=B8=AD=E4=BD=8D=E7=BD=AE=E6=97=B6=EF=BC=8C=E4=B8=8D=E5=A1=AB?= =?UTF-8?q?=E5=85=85hit=5Fdetail=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 6 +++--- src/entry/Maat_rule.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index f11f717..8cde22e 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -434,6 +434,7 @@ Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* feather->garbage_q=MESA_lqueue_create(0,0); feather->effect_interval_ms=60*1000; feather->scan_interval_ms=1*1000; + feather->rule_scan_type=2; feather->thread_call_cnt=aligment_int64_array_alloc(max_thread_num); return feather; } @@ -541,7 +542,6 @@ int Maat_initiate_feather(Maat_feather_t feather) _feather->scanner=_feather->update_tmp_scanner; _feather->update_tmp_scanner=NULL; _feather->still_working=1; - _feather->rule_scan_type=2; if(_feather->scanner!=NULL) { _feather->maat_version=_feather->scanner->version; @@ -794,7 +794,7 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); - if(hit_detail!=NULL) + if(hit_detail!=NULL||_feather->rule_scan_type==0) { *detail_ret=fill_region_hit_detail(data,_mid->inner, region_result,hit_region_cnt, @@ -1193,7 +1193,7 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); - if(hit_detail!=NULL) + if(hit_detail!=NULL||sp->feather->rule_scan_type==0) { if(sp->scan_buff!=NULL) { diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index f043cf7..ae7e2a9 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_5_20160211=1; +int MAAT_FRAME_VERSION_1_5_20160311=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"CHARSET_NONE","GBK","BIG5","UNICODE","UTF-8"}; From 665b21f5dd1c6ae8eb2a00cfa18ae8eeaf291714 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 16 Mar 2016 12:48:43 +0800 Subject: [PATCH 14/31] =?UTF-8?q?=E4=BF=AE=E5=A4=8DMaat=5Fsummon=5Ffeather?= =?UTF-8?q?=E4=B8=AD=E5=A2=9E=E9=87=8F=E7=9B=AE=E5=BD=95=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E7=9A=84=E7=AC=94=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 8cde22e..00013cf 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -587,7 +587,7 @@ Maat_feather_t Maat_summon_feather(int max_thread_num, { goto error_out; } - ret=Maat_set_feather_opt(feather, MAAT_OPT_FULL_CFG_DIR, inc_cfg_dir, strlen(inc_cfg_dir)+1); + ret=Maat_set_feather_opt(feather, MAAT_OPT_INC_CFG_DIR, inc_cfg_dir, strlen(inc_cfg_dir)+1); if(ret<0) { goto error_out; From 392e172711580bff57bd3d142488ea73626dc423 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 25 Mar 2016 11:55:15 +0800 Subject: [PATCH 15/31] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=9D=8E=E4=BD=B3?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=EF=BC=9ALRU=E6=A8=A1=E5=BC=8F=E4=BC=9A?= =?UTF-8?q?=E9=A2=91=E7=B9=81=E5=9C=A8=E9=93=BE=E8=A1=A8=E4=B8=AD=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=EF=BC=8C=E4=B8=BA=E9=99=8D=E4=BD=8ECPU=E5=BC=80?= =?UTF-8?q?=E9=94=80=EF=BC=8C=E5=B0=86MESA=5Fhtable=E7=9A=84=E6=B7=98?= =?UTF-8?q?=E6=B1=B0=E5=8F=82=E6=95=B0=E6=94=B9=E4=B8=BAFIFO=E3=80=82?= =?UTF-8?q?=E6=9C=AA=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC=E5=8F=B7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index ae7e2a9..f0ae3a0 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -674,7 +674,7 @@ struct _Maat_scanner_t* create_maat_scanner(unsigned int version,int scan_thread hargs.thread_safe=0; hargs.hash_slot_size = 1024*1024; hargs.max_elem_num = 0; - hargs.eliminate_type = HASH_ELIMINATE_ALGO_LRU; + hargs.eliminate_type = HASH_ELIMINATE_ALGO_FIFO; hargs.expire_time = 0; hargs.key_comp = NULL; hargs.key2index = NULL; From 422899cc816ab95ff85d347bf9814f4cadd6e946 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Mon, 28 Mar 2016 16:21:36 +0800 Subject: [PATCH 16/31] =?UTF-8?q?=E4=BD=BF=E7=94=A8MESA=5Ffs2=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E7=BB=9F=E8=AE=A1=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E5=AF=B9MESA=5Ffieldstat=E9=93=BE=E6=8E=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 2 +- src/entry/Maat_rule_internal.h | 2 +- src/entry/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index f0ae3a0..d24b010 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "Maat_rule.h" #include "Maat_rule_internal.h" diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index 71af01a..d79ec31 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include "dynamic_array.h" #include "UniversalBoolMatch.h" #include "rulescan.h" diff --git a/src/entry/Makefile b/src/entry/Makefile index 4ba933e..6ef9b6e 100644 --- a/src/entry/Makefile +++ b/src/entry/Makefile @@ -6,7 +6,7 @@ CCC = g++ CFLAGS = -Wall -g -fPIC CFLAGS += $(OPTFLAGS) LDDICTATOR = -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,free -Wl,-wrap,realloc -LDFLAGS = -lMESA_handle_logger -lMESA_htable -lpthread -lrt -lm -lrulescan -lpcre -lMESA_field_stat +LDFLAGS = -lMESA_handle_logger -lMESA_htable -lpthread -lrt -lm -lrulescan -lpcre -lMESA_field_stat2 #LDFLAGS += $(LDDICTATOR) MAILLIB = ../lib From f3f43fd4999f532872faa3a5e8077e78d8a65346 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Sun, 3 Apr 2016 12:29:41 +0800 Subject: [PATCH 17/31] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E5=AD=97=E9=85=8D=E7=BD=AE=E8=BD=AC=E7=A0=81=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0"unicode=5Fascii=5Fesc","unicode=5Fa?= =?UTF-8?q?scii=5Faligned","unicode=5Fncr=5Fdec","unicode=5Fncr=5Fhex"?= =?UTF-8?q?=E5=85=B14=E7=A7=8Dunicode=E7=BD=91=E9=A1=B5=E7=BC=96=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0"url=5Fencode=5Fgb2312","url=5Fencod?= =?UTF-8?q?e=5Futf8"=E5=85=B12=E7=A7=8DURL=E7=BC=96=E7=A0=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inc/Maat_rule.h | 8 +- src/entry/Maat_rule.cpp | 171 ++++++++++++++++++++++++++++++--- src/entry/Maat_rule_internal.h | 2 +- src/entry/great_index_engine.c | 4 +- src/entry/json2iris.cpp | 2 +- src/entry/map_str2int.cpp | 2 +- test/maat_json.json | 54 +++++++++++ test/table_info.conf | 4 +- 8 files changed, 228 insertions(+), 19 deletions(-) diff --git a/inc/Maat_rule.h b/inc/Maat_rule.h index a6e7be4..f7399c1 100644 --- a/inc/Maat_rule.h +++ b/inc/Maat_rule.h @@ -24,7 +24,13 @@ enum MAAT_CHARSET CHARSET_BIG5, CHARSET_UNICODE, CHARSET_UTF8, // 4 - CHARSET_BIN //5 + CHARSET_BIN, //5 + CHARSET_UNICODE_ASCII_ESC, // Unicode Escape format, prefix backslash-u hex, e.g. "\u627;" + CHARSET_UNICODE_ASCII_ALIGNED,//Unicode Escape format, prefix backslash-u with 4 bytes aligned, e.g. "\u0627" + CHARSET_UNICODE_NCR_DEC, //SGML Numeric character reference,decimal base, e.g. "ا" + CHARSET_UNICODE_NCR_HEX, //SGML Numeric character reference,hexdecimal base, e.g. "ا" + CHARSET_URL_ENCODE_GB2312, //URL encode with GB2312, e.g. the chinese word "china" was encoded to %D6%D0%B9%FA + CHARSET_URL_ENCODE_UTF8 //11, URL encode with UTF8,e.g. the chinese word "china" was encoded to %E4%B8%AD%E5%9B%BD }; enum MAAT_ACTION { diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index d24b010..7d0b605 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -29,7 +29,8 @@ int MAAT_FRAME_VERSION_1_5_20160311=1; const char *maat_module="MAAT Frame"; -const char* CHARSET_STRING[]={"CHARSET_NONE","GBK","BIG5","UNICODE","UTF-8"}; +const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", + "unicode_ascii_esc","unicode_ascii_aligned","unicode_ncr_dec","unicode_ncr_hex","url_encode_gb2312","url_encode_utf8",""}; int converHextoint(char srctmp) { if(isdigit(srctmp)) @@ -79,6 +80,7 @@ iconv_t maat_iconv_open(struct _Maat_scanner_t* scanner,enum MAAT_CHARSET to,enu cd=scanner->iconv_handle[to][from]; return cd; } + int iconv_convert(struct _Maat_scanner_t* scanner,enum MAAT_CHARSET from,enum MAAT_CHARSET to,char *src,int srclen,char *dst,int *dstlen) { size_t ret; @@ -104,7 +106,8 @@ int iconv_convert(struct _Maat_scanner_t* scanner,enum MAAT_CHARSET from,enum MA if(ret!=(size_t)(-1)) { - if(to==CHARSET_UNICODE)//jump unicode 2 bytes head 0xFF 0xFE + if(to==CHARSET_UNICODE&& + (*(unsigned short*)pOutBuff==0xFFFE||*(unsigned short*)pOutBuff==0XFEFF))//jump unicode 2 bytes BOM, 0xFF 0xFE { copy_len=iOutBuffLen-iLeftLen-2; copy_buf=pOutBuff+2; @@ -133,7 +136,137 @@ int iconv_convert(struct _Maat_scanner_t* scanner,enum MAAT_CHARSET from,enum MA } } +int URLEncode(const char* str, const int strSize, char* result, const int resultSize) +{ + int i; + int j = 0;//for result index + char ch; + if ((str==NULL) || (result==NULL) || (strSize<=0) || (resultSize<=0)) + { + return -1; + } + + for ( i=0; (i='A') && (ch<'Z')) || + ((ch>='a') && (ch<'z')) || + ((ch>='0') && (ch<'9'))) + { + result[j++] = ch; + } + else if (ch == ' ') + { + result[j++] = '+'; + } + else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') + { + result[j++] = ch; + } + else + { + if (j+3 < resultSize) + { + sprintf(result+j, "%%%02X", (unsigned char)ch); + j += 3; + } + else + { + return -1; + } + } + } + + result[j] = '\0'; + return j; +} +int uni2ascii(const char* fmt,const char* src, const int srclen, char* dst, const int dstsize) +{ + int i=0,j=0; + assert(srclen%2==0);//unicode must be 2 bytes aligned. + while(i0) + { + map_register(string2int_map,CHARSET_STRING[i], i); + } + else + { + break; + } + } + +/* map_register(string2int_map,"gbk", CHARSET_GBK); map_register(string2int_map,"big5", CHARSET_BIG5); map_register(string2int_map,"unicode", CHARSET_UNICODE); map_register(string2int_map,"utf8", CHARSET_UTF8); + map_register(string2int_map,"unicode_hex", CHARSET_UNICODE_ASCII_ESC); + map_register(string2int_map,"unicode_hex", CHARSET_UNICODE_ASCII_ESC); +*/ map_register(string2int_map,"yes", 1); map_register(string2int_map,"no", 0); @@ -277,6 +425,7 @@ int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* MESA_handle_runtime_log(logger, RLOG_LV_FATAL,maat_module, "Maat read table info %s error.\n",table_info_path); } + i=0; while(NULL!=fgets(line,sizeof(line),fp)) { i++; @@ -301,9 +450,9 @@ int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* { if(ret[j]<0) { - fprintf(stderr,"Maat read table info %s line %d error.\n",table_info_path,i); + fprintf(stderr,"Maat read table info %s line %d error:unknown column.\n",table_info_path,i); MESA_handle_runtime_log(logger, RLOG_LV_FATAL,maat_module, - "Maat read table info %s line %d error.\n",table_info_path,i); + "Maat read table info %s line %d error:unknown column.\n",table_info_path,i); goto error_jump; } } @@ -324,9 +473,9 @@ int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* } else { - fprintf(stderr,"Maat read table info %s line %d error.\n",table_info_path,i); + fprintf(stderr,"Maat read table info %s line %d error:unknown dest charset %s.\n",table_info_path,i,sub_token); MESA_handle_runtime_log(logger, RLOG_LV_FATAL,maat_module, - "Maat read table info %s line %d error.\n",table_info_path,i); + "Maat read table info %s line %d error: unknown dest charset %s.\n",table_info_path,i,sub_token); goto error_jump; } @@ -1261,12 +1410,12 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule { continue; } - region_str_len=strlen(sub_key_array[k])*2+1; + region_str_len=strlen(sub_key_array[k])*8+1; // 1 byte map to 8 bytes maximum, e.g. "ا" or "\u63221;" region_string=(char*)calloc(sizeof(char),region_str_len); if(table->src_charset!=dst_charset)//need convert { - ret=iconv_convert(scanner,table->src_charset, dst_charset, + ret=universal_charset_convert(scanner,table->src_charset, dst_charset, sub_key_array[k],strlen(sub_key_array[k]), region_string, ®ion_str_len); if(ret<0) @@ -1279,7 +1428,7 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule free(region_string); continue; } - //if convert take no effect + //if convert take no effect and src charset is one of the dst. if(region_str_len==(int)strlen(sub_key_array[k])&& 0==memcmp(sub_key_array[k],region_string,region_str_len)&& TRUE==table->src_charset_in_dst) diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index d79ec31..f7f9ef0 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -36,7 +36,7 @@ typedef int atomic_t; #define FALSE 0 #define MAX_TABLE_NUM 256 -#define MAX_CHARSET_NUM 6 +#define MAX_CHARSET_NUM 16 #define MAX_TABLE_NAME_LEN 256 #define MAX_TABLE_LINE_SIZE (1024*4) #define MAX_EXPR_KEYLEN 1024 diff --git a/src/entry/great_index_engine.c b/src/entry/great_index_engine.c index 683085f..c907384 100644 --- a/src/entry/great_index_engine.c +++ b/src/entry/great_index_engine.c @@ -97,7 +97,7 @@ GIE_handle_t * GIE_create(const GIE_create_para_t * para) idtable_args.hash_slot_size = HTABLE_SIZE; idtable_args.max_elem_num = 4 * HTABLE_SIZE; idtable_args.expire_time = 0; - idtable_args.eliminate_type = HASH_ELIMINATE_ALGO_LRU; + idtable_args.eliminate_type = HASH_ELIMINATE_ALGO_FIFO; idtable_args.key_comp = NULL; idtable_args.key2index = NULL; idtable_args.data_free = idtable_free; @@ -108,7 +108,7 @@ GIE_handle_t * GIE_create(const GIE_create_para_t * para) indextable_args.hash_slot_size = HTABLE_SIZE; indextable_args.max_elem_num = 4 * HTABLE_SIZE; indextable_args.expire_time = 0; - indextable_args.eliminate_type = HASH_ELIMINATE_ALGO_LRU; + indextable_args.eliminate_type = HASH_ELIMINATE_ALGO_FIFO; indextable_args.key_comp = NULL; indextable_args.key2index = NULL; indextable_args.data_free = indextable_free; diff --git a/src/entry/json2iris.cpp b/src/entry/json2iris.cpp index 397aa85..d515995 100644 --- a/src/entry/json2iris.cpp +++ b/src/entry/json2iris.cpp @@ -89,7 +89,7 @@ int set_iris_descriptor(const char* json_file,cJSON *json,struct iris_descriptio hargs.thread_safe=1; hargs.hash_slot_size = 1024; hargs.max_elem_num = 0; - hargs.eliminate_type = HASH_ELIMINATE_ALGO_LRU; + hargs.eliminate_type = HASH_ELIMINATE_ALGO_FIFO; hargs.expire_time = 0; hargs.key_comp = NULL; hargs.key2index = NULL; diff --git a/src/entry/map_str2int.cpp b/src/entry/map_str2int.cpp index 66ec288..2e8752e 100644 --- a/src/entry/map_str2int.cpp +++ b/src/entry/map_str2int.cpp @@ -25,7 +25,7 @@ MESA_htable_handle map_create(void) hargs.thread_safe=8; hargs.hash_slot_size = 4*1024; hargs.max_elem_num = 0; - hargs.eliminate_type = HASH_ELIMINATE_ALGO_LRU; + hargs.eliminate_type = HASH_ELIMINATE_ALGO_FIFO; hargs.expire_time = 0; hargs.key_comp = NULL; hargs.key2index = NULL; diff --git a/test/maat_json.json b/test/maat_json.json index 4ee7c21..9895d59 100644 --- a/test/maat_json.json +++ b/test/maat_json.json @@ -216,6 +216,60 @@ ] } ] + }, + { + "compile_id": 129, + "service": 1, + "action": 1, + "do_blacklist": 1, + "do_log": 1, + "effective_rage": 0, + "user_region": "utf8_涓枃", + "is_valid": "yes", + "groups": [ + { + "group_name": "group_9", + "regions": [ + { + "table_name": "HTTP_URL", + "table_type": "none", + "table_content": { + "keywords": "C#涓浗", + "expr_type": "and", + "match_method": "sub", + "format": "uncase plain" + } + } + ] + } + ] + }, + { + "compile_id": 130, + "service": 1, + "action": 1, + "do_blacklist": 1, + "do_log": 1, + "effective_rage": 0, + "user_region": "utf8_缁磋", + "is_valid": "yes", + "groups": [ + { + "group_name": "group_10", + "regions": [ + { + "table_name": "KEYWORDS_TABLE", + "table_type": "none", + "table_content": { + "keywords": "2010鈥撡娰壻勝壺壻冑", + "expr_type": "and", + "match_method": "sub", + "format": "uncase plain" + } + } + ] + } + ] } ], "plugin_table": [ diff --git a/test/table_info.conf b/test/table_info.conf index 0facdd5..a4cb5b9 100644 --- a/test/table_info.conf +++ b/test/table_info.conf @@ -8,8 +8,8 @@ #id name type src_charset dst_charset do_merge 0 COMPILE compile GBK GBK no 0 1 GROUP group GBK GBK no 0 -2 HTTP_URL expr GBK GBK/BIG5/UNICODE/UTF8 yes 128 -3 KEYWORDS_TABLE expr GBK GBK/BIG5/UNICODE/UTF8 yes 0 +2 HTTP_URL expr UTF8 GBK/BIG5/UNICODE/UTF8/url_encode_gb2312/url_encode_utf8 yes 128 +3 KEYWORDS_TABLE expr UTF8 GBK/BIG5/UNICODE/UTF8/unicode_ascii_esc/unicode_ascii_aligned/unicode_ncr_dec/unicode_ncr_hex yes 0 4 IP_CONFIG ip GBK GBK no 0 5 CONTENT_SIZE intval GBK GBK no 0 6 QD_ENTRY_INFO plugin GBK GBK no 0 From 72f6e611ed68325052811c63bb7cc8475e7043fc Mon Sep 17 00:00:00 2001 From: zhengchao Date: Sun, 3 Apr 2016 17:13:07 +0800 Subject: [PATCH 18/31] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BD=AC=E7=A0=81?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=9A=84=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 2 +- test/maat_json.json | 35 +- test/maat_test.cpp | 129 ++++++- .../original_Uygur_webpage.html | 166 +++++++++ test/testdata_uni2ascii/original_uy.txt | 2 + test/testdata_uni2ascii/qq_mail_https.txt | 326 ++++++++++++++++++ test/testdata_uni2ascii/sina_read_mail.txt | 1 + test/testdata_uni2ascii/sohu_mail_unicode.txt | 1 + 8 files changed, 656 insertions(+), 6 deletions(-) create mode 100644 test/testdata_uni2ascii/original_Uygur_webpage.html create mode 100644 test/testdata_uni2ascii/original_uy.txt create mode 100644 test/testdata_uni2ascii/qq_mail_https.txt create mode 100644 test/testdata_uni2ascii/sina_read_mail.txt create mode 100644 test/testdata_uni2ascii/sohu_mail_unicode.txt diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 7d0b605..6294157 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_5_20160311=1; +int MAAT_FRAME_VERSION_1_6_20160403=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", diff --git a/test/maat_json.json b/test/maat_json.json index 9895d59..48fff9f 100644 --- a/test/maat_json.json +++ b/test/maat_json.json @@ -232,10 +232,10 @@ "regions": [ { "table_name": "HTTP_URL", - "table_type": "none", + "table_type": "string", "table_content": { "keywords": "C#涓浗", - "expr_type": "and", + "expr_type": "none", "match_method": "sub", "format": "uncase plain" } @@ -259,9 +259,36 @@ "regions": [ { "table_name": "KEYWORDS_TABLE", - "table_type": "none", + "table_type": "string", "table_content": { - "keywords": "2010鈥撡娰壻勝壺壻冑", + "keywords": "2010&賷賶賱賶丿賶賰賶", + "expr_type": "and", + "match_method": "sub", + "format": "uncase plain" + } + } + ] + } + ] + }, + { + "compile_id": 131, + "service": 1, + "action": 1, + "do_blacklist": 1, + "do_log": 1, + "effective_rage": 0, + "user_region": "utf8_缁磋2", + "is_valid": "yes", + "groups": [ + { + "group_name": "group_11", + "regions": [ + { + "table_name": "KEYWORDS_TABLE", + "table_type": "string", + "table_content": { + "keywords": "爻賶賷丕爻賶賷", "expr_type": "and", "match_method": "sub", "format": "uncase plain" diff --git a/test/maat_test.cpp b/test/maat_test.cpp index f9943b2..800320f 100644 --- a/test/maat_test.cpp +++ b/test/maat_test.cpp @@ -14,7 +14,10 @@ #include //fstat #include //fstat #include - +#include +extern int my_scandir(const char *dir, struct dirent ***namelist, + int(*filter)(const struct dirent *), + int(*compar)(const void *, const void *)); void Maat_read_entry_start_cb(int update_type,void* u_para) { return; @@ -56,6 +59,31 @@ void print_maat_ret(int ret) } return; } +const char* print_maat_rule(struct Maat_rule_t* result,int ret) +{ + static char buff[1024]={0}; + int i=0,j=0; + switch(ret) + { + case -1: + snprintf(buff,sizeof(buff),"ret=%d,scan error.",ret); + break; + case -2: + snprintf(buff,sizeof(buff),"ret=%d,hit current region,but not hit compile rule.",ret); + break; + case 0: + snprintf(buff,sizeof(buff),"ret=0,nothing hit."); + break; + default://>0 + j=snprintf(buff,sizeof(buff),"hit %d rules, hit ruleid=",ret); + for(i=0;id_name, ".") == 0) || (strcmp(namelist[i]->d_name, "..") == 0)) + { + continue; + } + snprintf(file_path,sizeof(file_path),"%s/%s",test_data_dir,namelist[i]->d_name); + fp=fopen(file_path,"rb"); + if(fp==NULL) + { + printf("fopen %s error.\n",file_path);; + continue; + } + printf("%s processing %s\n",__FUNCTION__,file_path); + sp=Maat_stream_scan_string_start(feather,table_id,0); + if(sp==NULL) + { + printf("stream scan start failed.\n"); + continue; + } + read_len=fread(buff,1,sizeof(buff),fp); + while(read_len>0) + { + + ret=Maat_stream_scan_string(&sp,CHARSET_NONE,buff,read_len + ,result,found_pos,4,mid); + read_len=fread(buff,1,sizeof(buff),fp); + if(ret>0) + { + printf("UNI2ASCII file %s,%s\n",file_path,print_maat_rule(result,ret)); + } + } + Maat_stream_scan_string_end(&sp); + fclose(fp); + + } + for(i=0;i + + + + 賲蹠乇賰賶夭賶賷 禺賶夭賲蹠鬲賱蹠乇賳賶 趩蹎乇賶丿蹠倬 卅蹠賯賶賱 賰蹎乇爻賶鬲賶卮貙 蹕蹠夭賶倬賶爻賶賳賶 亘蹠噩丕賳賶丿賶賱 卅丕丿丕 賯賶賱賶倬 丿丕丿賶賱 夭賶賲賲賶诏蹠 卅蹛賱賶卮- 鬲蹠诃乇賶鬲丕睾 鬲賵乇賶 + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +
+ + + +
+
+
+
    +
    +
    +
      +
    • +
    +
    +
    +
    +
    + +
    + +
    +
    + + +

    + 賲蹠乇賰賶夭賶賷 禺賶夭賲蹠鬲賱蹠乇賳賶 趩蹎乇賶丿蹠倬 卅蹠賯賶賱 賰蹎乇爻賶鬲賶卮貙 蹕蹠夭賶倬賶爻賶賳賶 亘蹠噩丕賳賶丿賶賱 卅丕丿丕 賯賶賱賶倬 丿丕丿賶賱 夭賶賲賲賶诏蹠 卅蹛賱賶卮 +

    + 亘蹏卅丕賷卮蹠賲2016-03-31 11:17:39卮賶賳噩丕诃 诏蹛夭賶鬲賶 +
    +
    +

     卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶诃 2010鈥撡娰壻勝壺壻冑 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶 賷賶睾賶賳賶丿賶賳 亘蹏賷丕賳賯賶 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶 鬲賵睾乇賶爻賶丿丕 卅賵賲蹏賲賶賷 亘丕賷丕賳

    +

    賷丕蹕 鬲蹏诃

    +

        鈥光官傐曎勜ㄙ勠曍辟嗁 賲蹏噩蹠爻爻蹠賲賱蹠卮貙 卅蹠賯賶賱 賰蹎乇爻賶鬲賶卮貙 賰蹐趩 賯賵卮蹏卮鈥衡 噩 賰 倬 賲蹠乇賰賶夭賶賷 賰賵賲賶鬲蹛鬲賶 爻賶賷丕爻賶賷 亘賶賷蹏乇賵爻賶賳賶诃 卅蹠夭丕爻賶貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 卮蹏噩賶爻賶 噩丕诃 趩蹐賳卮賷蹠賳賳賶诃 爻賶賷丕爻賶賷 賰蹛诃蹠卮賰蹠 賯賵賷睾丕賳 亘蹏 鬲蹠賱賶倬賶 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶诃 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶賳賶诃 賷蹎賳賶賱賶卮賶賳賶 賰蹎乇爻賶鬲賶倬 亘蹛乇賶倬貙 卅蹏賳賶 倬賶乇賶賳爻賶倬 亘賶賱蹠賳 鬲蹠賲賶賳賱蹠倬貙 卅蹠夭丕賱丕乇賳賶诃 賷蹛诃賶 蹕蹠夭賶賷蹠鬲鬲蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶賳賶 賷丕禺卮賶 卅賶卮賱蹠卮 卅賶卮蹠賳趩賶 蹕蹠 卅賶乇丕丿賶爻賶賳賶 賰蹐趩蹠賷鬲鬲賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶诏蹠 卅賶夭趩賶賱 賷蹐賰爻蹠賰 卅蹠诰賲賶賷蹠鬲 亘蹛乇賶倬 賰蹠賱丿賶貙 卮蹏噩賶 噩丕诃 趩蹐賳卮賷蹠賳 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶诏蹠 賳丕诰丕賷賶鬲賶 賰蹎诃蹐賱 亘蹎賱丿賶 蹕蹠 卅蹏賳賶 賯賵賱賱賶丿賶貙 2010 鈥 賷賶賱賶 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶 賷賶睾賶賳賶 卅蹛趩賶賱睾丕賳丿賶賳 亘蹏賷丕賳貙 卮蹏噩賶 噩丕诃 趩蹐賳卮賷蹠賳 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶賳賶 賰蹐趩蹠賷鬲賶卮 鬲賵睾乇賶爻賶丿丕 賰蹎倬 賯蹛鬲賶賲 鬲蹠爻鬲賶賯賶賷 賷賵賱賷蹏乇蹏賯 亘蹠乇丿賶.

    +

        賳蹠趩趩蹠 賷賶賱丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 倬丕乇鬲賶賷蹠 乇蹠诰亘蹠乇賱賶賰賶丿蹠 趩賶诃 鬲蹏乇蹏卮賳賶 亘丕卮鬲賶賳 鈥 卅丕禺賶乇 蹕蹠夭賶倬賶爻賶賳賶 卅丕丿丕 賯賶賱賶卮賳賶诃 亘賶乇賶賳趩賶 鬲蹠賱賶倬賶 賯賶賱賶倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 蹕蹠鬲蹠賳倬蹠乇蹕蹠乇賱賶賰 亘賶乇賱賶賰 爻蹠倬 鬲蹠卮賰賶賱丕鬲賶賱賶賯 賲蹏诰賶賲 乇賵賱賶賳賶 鬲賵賱蹏賯 噩丕乇賶 賯賶賱丿蹏乇蹏倬貙 卅賵乇鬲丕賯 鬲賵賳蹏卮賳賶 賰蹠诃 丿丕卅賶乇賶丿蹠 賲蹏噩蹠爻爻蹠賲賱賶丿賶貨 丿賶賯賯蹠鬲賳賶 卅賶噩鬲賶賲丕卅賶賷 賲蹏賯賶賲賱賶賯 蹕蹠 卅蹠亘蹠丿賶賷 卅蹠賲賶賳賱賶賰賰蹠 賲蹠乇賰蹠夭賱蹠卮鬲蹐乇蹐倬貙 丿丕卅賶賲賶賷 賰賵賲賶鬲蹛鬲 賷賶睾賶賳賶 卅蹛趩賶倬貙 亘賶乇 賯丕鬲丕乇 賲蹏诰賶賲 賲蹠爻賶賱賶賱蹠乇 鬲賵睾乇賶爻賶丿丕 鬲蹠丿亘賶乇貙 鬲蹠賰賱賶倬賱蹠乇賳賶 卅賵鬲鬲蹏乇賶睾丕 賯賵賷丿賶貨 卅丕賷賱賶賯 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶 卅蹛趩賶卮賳賶 卅賶噩丕丿賶賷 賷賵賱睾丕 賯賵賷蹏倬貙 賰蹛诃賶卮賶倬 亘賶乇賱賶賰賰蹠 賰蹠賱诏蹠賳 倬賶賰賶乇賱蹠乇賳賶 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲貙 禺蹠賱賯 诰蹎賰蹐賲賶鬲賶賳賶诃 倬丕賷丿賶賱賶賳賶卮賶睾丕 爻蹏賳丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卮賶賳噩丕诃 卅蹏賷睾蹏乇 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 11 鈥 賳蹎蹕蹠鬲賱賶賰 賰賵賲賶鬲蹛鬲賶 1 鈥 賷賶睾賶賳賶丿賶賳 亘蹏賷丕賳賯賶 蹕蹠夭賶倬賶爻賶賳賶 卅丕丿丕 賯賶賱賶卮 禺丕鬲賶乇賶爻賶诏蹠 賳蹠夭蹠乇 爻丕賱睾丕賳丿丕貙 賰蹎倬賱賶诏蹠賳 鬲蹠賰賱賶倬貙 鬲蹠蹕爻賶賷蹠賱蹠乇貙 亘賶乇 賯丕鬲丕乇 鬲蹠賰卮蹐乇蹐倬 鬲蹠鬲賯賶賯 賯賶賱賶卮 丿賵賰賱丕鬲賱賶乇賶賳賶诃 诰蹠賲賲賶爻賶丿蹠 卮賶賳噩丕诃丿賶賰賶 诰蹠乇 丿蹠乇賶噩賶賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鬲蹠卮賰賶賱丕鬲賱賶乇賶 蹕蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕賱賶乇賶賳賶诃 卮賶賳噩丕诃賳賶诃 卅賶賯鬲賶爻丕丿賶賷貙 卅賶噩鬲賶賲丕卅賶賷 鬲蹠乇蹠賯賯賶賷丕鬲賶 卅蹐趩蹐賳 賯蹠賱亘賱蹠乇賳賶 賲蹏噩蹠爻爻蹠賲賱蹠倬貙 卅蹠賯賶賱 賰蹎乇爻賶鬲賶倬貙 賰蹐趩 趩賶賯丕乇睾丕賳賱賶賯賶丿賶賳 卅賶亘丕乇蹠鬲 噩丕賳賱賶賯 卅蹠賲蹠賱賶賷蹠鬲 禺丕鬲賶乇賶賱蹠賳诏蹠賳 亘賵賱蹏倬貙 亘蹏賱丕乇 卮賶賳噩丕诃丿賶賰賶 诰蹠乇 丿蹠乇賶噩賶賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鬲蹠卮賰賶賱丕鬲賱賶乇賶 蹕蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕賱賶乇賶賳賶诃 丿賶賯賯蹠鬲賳賶 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶诃 賲蹠乇賰賶夭賶賷 禺賶夭賲賶鬲賶诏蹠 賲蹠乇賰蹠夭賱蹠卮鬲蹐乇蹐倬 賮蹏賳賰爻賶賷蹠爻賶賳賶 卅丕丿丕 賯賶賱賶倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賰蹛诃賶卮賶卮 卅丕爻丕爻賶丿賶賰賶 丿蹛賲賵賰乇丕鬲賶賷蹠 賯蹠丿賶賲賶賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐倬貙 卅賶爻鬲賶賱 蹕蹠 卅賶賯鬲賶丿丕乇 賯蹏乇蹏賱蹏卮賶賳賶 賰蹐趩蹠賷鬲賶倬貙 卅蹠賲蹠賱賶賷 卅蹐賳蹐賲賳賶 卅丕卮蹏乇蹏卮 丿丕蹕丕賲賶丿賶賰賶 賲蹠夭賲蹏鬲 賯蹠丿蹠賲賱賶乇賶賳賶诃 卮丕诰賶鬲賶.

    +

        賰蹐趩賳賶 賲蹠乇賰蹠夭賱蹠卮鬲蹐乇蹐倬貙 卅賶鬲鬲賶倬丕賯賱賶賯賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐倬貙 賯蹠賱亘賱蹠乇賳賶 賲蹏噩蹠爻爻蹠賲賱蹠倬貙 亘賶乇賱賶賰鬲蹠 诏蹐夭蹠賱 卮賶賳噩丕诃 賯蹏乇蹏倬 趩賶賯賶卮

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 卅蹠夭丕爻賶 蹕蹛賷 鬲賷蹠賳噩蹛 賰蹛爻蹠賱賱賶賰 爻蹠蹕蹠亘賶丿賶賳 賳丕賲乇丕鬲賱賶卮賶倬 賰蹠鬲賰蹠賳 亘賶乇 賯丕夭丕賯 卅丕卅賶賱賶爻賶賳賶诃 賯賶賷賶賳趩賶賱賶賯鬲賶賳 賯蹏鬲蹏賱蹏卮賶睾丕 20 賷賶賱 賷丕乇丿蹠賲 亘蹠乇丿賶貙 卅蹠诃 丿蹠爻賱蹠倬鬲蹠 賲蹠亘賱蹠睾 趩賶賯賶乇賶倬 賷蹛诃賶 卅蹎賷 爻蹛賱賶倬 亘蹛乇賶卮貙 賯賵賷 卅蹛賱賶倬 亘蹛乇賶卮鬲賶賳貙 卅蹠乇 禺賵噩丕賷賶賳賳賶诃 賯賵賲蹏賱 卮蹠诰賶乇賶丿蹠 賲蹏賯賶賲 禺賶夭賲蹠鬲 鬲蹛倬賶倬貙 卅賵賱鬲蹏乇丕賯賱賶卮賶卮賶 蹕蹠 卅蹏賳賶诃 卅賶賰賰賶 亘丕賱賶爻賶賳賶诃 卅賵鬲鬲蹏乇丕 賲蹠賰鬲蹠倬賳賶貙 卅丕賱賶賷 賲蹠賰鬲蹠倬賳賶 鬲丕賲丕賲賱丕倬貙 禺賶夭賲蹠鬲賰蹠 趩賶賯賶卮賶睾賶趩蹠 卅蹏賱丕乇睾丕 卅賶夭趩賶賱 卅賶賯鬲賶爻丕丿賶賷 噩蹠诰蹠鬲鬲賶賳 賷丕乇丿蹠賲 賯賶賱丿賶. 趩賶诃诏賶賱 賳丕诰賶賷蹠賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 卅蹠夭丕爻賶 卅丕賲賶賳蹠 爻丕蹕蹏鬲 50 賷丕卮鬲賶賳 卅丕卮賯丕賳貙 卅丕卅賶賱蹠 卅蹠诰蹕丕賱賶 卅丕賳趩蹠 賷丕禺卮賶 亘賵賱賲賶睾丕賳 賷蹠賰賰蹠 爻賵丿丕 鈥 爻丕賳丕卅蹠鬲趩賶貙 卅蹏 卅賶賯鬲賶爻丕丿趩丕賳賱賶賯 亘賶賱蹠賳 鬲蹏乇賲蹏卮 賰蹠趩蹐乇蹐倬貙 賰蹎倬 賷賶賱賱丕乇丿賶賳 亘蹏賷丕賳 賷賶睾賯丕賳 100 賲賶诃 賷蹐蹠賳丿賶賳 賰蹎倬乇蹠賰 倬蹏賱賶睾丕 賰賶趩賶賰 趩賶诃诏賶賱 丿蹠乇賷丕爻賶睾丕 倬賵賱丕鬲 卅丕乇睾丕賲趩賶賱賶賯 卅丕爻賲丕 賰蹎蹕乇蹐賰 爻丕賱丿蹏乇蹏倬貙 卅賶賰賰賶 賯賶乇睾丕賯鬲賶賰賶 卅蹐趩 賰蹠賳鬲鬲賶賰賶 丿蹛诰賯丕賳 鈥 趩丕乇蹕賶趩賶賱丕乇賳賶诃 賷賵賱 賷蹐乇蹐卮賶诏蹠 夭賵乇 賯賵賱丕賷賱賶賯 賷丕乇賶鬲賶倬 亘蹠乇丿賶...

    +

        賷蹛賯賶賳賯賶 賷賶賱賱丕乇丿賶賳 亘蹏賷丕賳 诰蹠乇 賲賶賱賱蹠鬲貙 诰蹠乇 爻丕诰蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕賱賶乇賶 賲賶賱賱蹠鬲賱蹠乇 卅賶鬲鬲賶倬丕賯賱賶賯賶賳賶 亘丕卮賱丕賲趩賶賱賶賯 亘賶賱蹠賳 賯賵睾丿丕倬貙 賲賶賱賱蹠鬲賱蹠乇 卅賶鬲鬲賶倬丕賯賱賶賯賶睾丕 亘蹏夭睾蹏賳趩賶賱賶賯 賯賶賱賶丿賶睾丕賳 亘丕乇賱賶賯 爻蹎夭貙 诰蹠乇賶賰蹠鬲賱蹠乇诏蹠 亘丕賷乇賶賯賶 乇賵卮蹠賳 诰丕賱丿丕 賯丕乇卮賶 鬲蹏乇蹏倬貙 卅蹠賲蹠賱賶賷 诰蹠乇賶賰賶鬲賶 亘賶賱蹠賳 賲賶賱賱蹠鬲賱蹠乇賳賶诃 卅賶賳丕賯 卅蹎鬲蹐卮賶貙 亘賶乇 賷丕賯賶丿賶賳 亘丕卮 趩賶賯賶乇賶卮賶貙 卅賶賳丕賯 乇丕蹕丕噩賱賶賳賶卮賶睾丕 鬲蹐乇鬲賰蹠 亘賵賱蹏倬貙 倬丕乇鬲賶賷蹠 鈥 诏蹏乇蹏诰賱丕乇貙 鬲蹠卮賰賶賱丕鬲賱丕乇貙 诰蹠乇 賲賶賱賱蹠鬲貙 诰蹠乇 賯丕鬲賱丕賲丿賶賰賶賱蹠乇賳賶诃 亘蹐賷蹐賰 卅賶鬲鬲賶倬丕賯賱賶賯賶貙 亘蹐賷蹐賰 亘賶乇賱賶卮賶卮賶賳賶 卅賶賱诏賶乇賶 爻蹐乇丿賶.

    +

        2016 鈥 賷賶賱賶 1 鈥 卅丕賷丿丕 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 亘蹠賳诏蹏诃鬲賶诃賶 乇蹠诰亘蹠乇賱賶乇賶 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅賵乇诏賶賳賶丿賶賳 賲丕乇丕賱亘蹛卮賶 賳丕诰賶賷蹠爻賶賳賶诃 丿蹎賱蹠鬲亘丕睾 賷蹛夭賶爻賶 賯蹏乇蹏賯鬲蹛乇蹠賰 賰蹠賳鬲賶丿蹠 鬲蹏乇蹏卮賱蹏賯 禺賶夭賲蹠鬲 诏蹏乇蹏倬倬賶爻賶丿賶賰賶賱蹠乇 鬲賵睾乇賶爻賶丿丕 賷蹛夭賶賱睾丕賳 亘賶乇賱蹠卮賲蹠 卅賶賲夭丕賱賶賯 禺蹠鬲賳賶 鬲丕倬卮蹏乇蹏蹕丕賱丿賶貙 禺蹠鬲賳賶 賲蹠夭賰蹏乇 賰蹠賳鬲鬲賶賰賶 鈥光关嗀 倬蹛卮賯蹠丿蹠賲鈥衡嘿勠曍必 丿賶賳賶賷 夭丕鬲賱丕乇 蹕蹠 卅丕賲賲丕 蹕蹠賰賶賱賶丿賶賳 亘賵賱蹏倬 17 賰賶卮賶 亘賶乇賱賶卮賶倬 賷丕夭睾丕賳 亘賵賱蹏倬貙 卅蹏賱丕乇 禺蹠鬲鬲蹠 倬蹐鬲蹐賳 賰蹠賳鬲鬲賶賰賶賱蹠乇诏蹠 蹕丕賰丕賱賶鬲蹠賳 賰蹐趩賱蹐賰 卅丕乇夭蹏爻賶賳賶 卅賶倬丕丿賶賱蹠倬: 鈥光官冔曎嗀 鬲蹏乇蹏卮賱蹏賯 賰丕丿賶乇 卅蹛賳诏蹏爻蹏賲 夭蹠賷賳賶丿賶賳賳賶诃 賰蹠賳鬲賶賲賶夭丿蹠 賷蹠賳蹠 丿丕蹕丕賲賱賶賯 亘賶乇 賷賶賱 鬲蹏乇蹏卮賶賳賶 卅蹐賲賶丿 賯賶賱賶賲賶夭鈥衡 丿蹠倬 賷丕夭睾丕賳賶丿賶.

    +

        卅賶賰賰賶 賷賶賱丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 亘賶乇 鬲蹏鬲丕卮 卅賵乇蹏賳賱丕卮鬲蹏乇蹏卮賶 亘賵賷賶趩蹠 卮賶賳噩丕诃丿賶賰賶 诰蹠乇 丿蹠乇賶噩賶賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鬲蹠卮賰賶賱丕鬲賱賶乇賶丿賶賳 1900丿賶賳 賰蹎倬乇蹠賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕爻賶 蹕蹠 630丿賶賳 賰蹎倬乇蹠賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 賰丕丿賶乇賶 卮賶賳噩丕诃丿賶賰賶 14 蹕賶賱丕賷蹠鬲貙 卅賵亘賱丕爻鬲貙 卮蹠诰蹠乇丿賶賰賶 1066 賰蹠賳鬲賰蹠 趩賵诃賯蹏乇 趩蹎賰蹐倬貙 卅蹐趩 卅蹠賱 倬丕卅丕賱賶賷賶鬲賶賳賶 賰蹠诃 賯丕賳丕鬲 賷丕賷丿蹏乇蹏倬貙 卅丕賲賲丕 亘賶賱蹠賳 鬲丕賲丕賯鬲丕貙 卅蹠賲诏蹠賰鬲蹠 亘賶賱賱蹠 亘賵賱蹏倬貙 卅蹠诃 夭賵乇 丿蹠乇賶噩賶丿蹠 卅蹠賱乇丕賷賶賳賶 賲蹏噩蹠爻爻蹠賲賱蹠倬貙 卅丕賲賲賶賳賶诃 賰蹎诃賱賶賳賶 卅蹏鬲蹏倬貙 诰蹠乇 賲賶賱賱蹠鬲 卅丕賲賲賶睾丕 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 卅蹎夭賱賶乇賶诏蹠 賳丕诰丕賷賶鬲賶 賷蹛賯賶賳 卅賶賰蹠賳賱賶賰賶賳賶 诰蹠賯賶賯賶賷 诰蹛爻 賯賶賱丿蹏乇丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 賷蹠賳蹠 倬丕乇鬲賶賷蹠 鈥 诏蹏乇蹏诰賱丕乇貙 鬲蹠卮賰賶賱丕鬲賱丕乇 诰蹠賲賰丕乇賱賶賯賶賳賶 賰蹐趩蹠賷鬲賶卮賳賶 賲蹏诰賶賲 禺賶夭賲蹠鬲 賯賶賱賶倬貙 丿蹛賲賵賰乇丕鬲賶賰 倬丕乇鬲賶賷蹠 鈥 诏蹏乇蹏诰賱丕乇貙 爻賵丿丕 鈥 爻丕賳丕卅蹠鬲趩賶賱蹠乇 亘賶乇賱蹠卮賲賶爻賶貙 禺蹠賱賯 鬲蹠卮賰賶賱丕鬲賱賶乇賶 蹕蹠 倬丕乇鬲賶賷蹠 鈥 诏蹏乇蹏诰爻賶夭 夭丕鬲賱丕乇賳賶诃 丿蹛賲賵賰乇丕鬲賶賰 诰賵賯蹏賯賶睾丕 鬲賵賱蹏賯 诰蹎乇賲蹠鬲 賯賶賱賶倬貙 鬲蹠鬲賯賶賯 賯賶賱賶卮貙 賰蹛诃賶卮賶卮 卅丕爻丕爻賶丿丕 倬賶賱丕賳 鬲蹐夭蹐卮 賯丕鬲丕乇賱賶賯 賲蹏诰賶賲 卅賶卮賱丕乇丿丕 卅蹏賱丕乇丿賶賳 鬲蹠賰賱賶倬 鈥 倬賶賰賶乇 卅蹛賱賶卮賯丕 卅蹠诰賲賶賷蹠鬲 亘蹛乇賶倬貙 卅蹏賱丕乇賳賶诃 蹕蹠夭賶倬賶爻賶賳賶 卅蹐賳蹐賲賱蹐賰 卅丕丿丕 賯賶賱賶卮賶睾丕 倬丕卅丕賱 爻蹠诰賳蹠 诰丕夭賶乇賱丕倬 亘蹛乇賶倬貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶诃 卅賶爻賱丕诰丕鬲貙 鬲蹠乇蹠賯賯賶賷丕鬲貙 賲蹏賯賶賲賱賶賯賶睾丕 卅蹠賯賶賱 鈥 倬丕乇丕爻賶鬲賶 蹕蹠 賰蹐趩賶賳賶 亘蹛睾賶卮賱賶丿賶.

    +

        蹕蹠夭賶倬賶賱蹠乇賳賶 丿丕丿賶賱 夭賶賲賲賶诏蹠 卅蹛賱賶倬貙 賷丕禺卮賶 卅蹠賯賶賱 賰蹎乇爻賶鬲賶倬貙 卅賶賳丕賯賱賶賯賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐倬貙 卅蹠亘蹠丿賶賷 卅蹠賲賶賳賱賶賰賳賶 賯賵睾丿丕卮

    +

        賲蹠賲賱賶賰蹠鬲賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 卮賶賳噩丕诃丿賶賰賶 卅蹠夭丕爻賶貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 乇蹠卅賶爻賶 賳蹏乇賱丕賳 卅丕亘賶賱賲蹠噩賶賳 12 鈥 賲丕乇鬲 爻賶賷丕爻賶賷 賰蹛诃蹠卮 賲蹠賲賱賶賰蹠鬲賱賶賰 12 鈥 賳蹎蹕蹠鬲賱賶賰 賰賵賲賶鬲蹛鬲賶賳賶诃 4 鈥 賷賶睾賶賳賶丿丕 鈥光关曍驰曍ㄙ壻娰勝壻冑嗁 鬲蹐诏賶鬲賶卮賳賶 趩賵诃賯蹏乇 卅賶賱诏賶乇賶 爻蹐乇蹐倬貙 丿蹎賱蹠鬲賳賶诃 亘賶禺蹠鬲蹠乇賱賶賰賶賳賶 賯蹠鬲卅賶賷 賯賵睾丿丕賷賱賶鈥衡 丿蹛诏蹠賳 鬲蹛賲賶丿丕 爻蹎夭 賯賶賱賶倬貙 丿蹎賱蹠鬲賳賶诃 卅蹠诃 賷蹏賯賶乇賶 賰蹛诃賶卮賶卮 爻蹠诰賳賶爻賶丿蹠 丿賶賳 卅蹠爻蹠亘賶賷賱賶賰賶 卅賶丿賶賷蹠爻賶丿賶賳 卅賶亘丕乇蹠鬲 鈥光官娯з呚з 爻蹐倬蹠鬲賱賶賰 卅蹎爻賲蹠鈥衡嘿嗁 賷賵賯賶鬲賶倬貙 丿蹎賱蹠鬲賳賶诃 亘賶禺蹠鬲蹠乇賱賶賰賶賳賶 賯賵睾丿丕倬貙 鈥光关ㄙ壺 亘蹠賱亘丕睾貙 亘賶乇 賷賵賱鈥衡 卅賶爻鬲乇丕鬲蹛诏賶賷蹠爻賶賳賶 卅賵诃蹏卮賱蹏賯 賷賵賱睾丕 賯賵賷蹏卮賯丕 賰丕倬丕賱蹠鬲賱賶賰 賯賶賱賶卮賳賶 卅賵鬲鬲蹏乇賶睾丕 賯賵賷丿賶.

    +

        鈥光关促壻嗀и 卅丕蹕丕夭賶鈥衡 禺蹠賱賯 爻丕乇賶賷賶丿丕 賷丕诃乇賶丿賶貙 亘蹏 卮賶賳噩丕诃丿賶賰賶 23 賲賶賱賷賵賳 诰蹠乇 賲賶賱賱蹠鬲 卅丕賲賲賶賳賶诃 卅賵乇鬲丕賯 賯蹠賱亘 爻丕丿丕爻賶! 賷蹛賯賶賳賯賶 賳蹠趩趩蹠 賷賶賱丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅賶噩鬲賶賲丕卅賶賷 賲蹏賯賶賲賱賶賯 蹕蹠 卅蹠亘蹠丿賶賷 卅蹠賲賶賳賱賶賰鬲賶賳 卅賶亘丕乇蹠鬲 亘蹏 亘丕卮 賳賶卮丕賳賳賶 趩蹎乇賶丿蹠倬貙 鈥光关堏 禺賶賱 賰蹐趩鈥衡嘿冔 夭蹠乇亘蹠 亘蹛乇賶卮貙 丿賶賳 卅蹠爻蹠亘賶賷賱賶賰賶 卅賶丿賶賷蹠爻賶賳賶诃 爻賶诃賶倬 賰賶乇賶卮賶賳賶 趩蹠賰賱蹠卮貙 丿賶賳 卅賶賳丕賯賱賶賯賶睾丕 鬲蹠爻賶乇 賷蹠鬲賰蹐夭賶丿賶睾丕賳 卅丕賲賶賱賱丕乇賳賶 鬲蹐诏賶鬲賶卮貙 鬲賶賳趩 卮賶賳噩丕诃 賯蹏乇蹏卮賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮 賯丕鬲丕乇賱賶賯 鬲蹛賲賶賱丕乇 亘賵賷賶趩蹠 鬲蹐乇賱蹐賰 鬲蹠賰卮蹐乇蹐倬 鬲蹠鬲賯賶賯 賯賶賱賶卮賳賶 賯丕賳丕鬲 賷丕賷丿蹏乇蹏倬貙 鈥光关迟壻娯ж迟壻 賰蹛诃蹠卮 爻丕丿丕爻賶鈥衡嘿嗁 賷丕诃乇丕鬲鬲賶.

    +

        鈥光官娵愗操壻勜ж必壻冑 80 鈥撠 90 鈥 賷賶賱賱丕乇丿丕 鬲蹏睾蹏賱睾丕賳賱丕乇睾丕 賯丕乇賶鬲賶賱睾丕賳 賯丕賳蹏賳 鈥 鬲蹐夭蹐賲 鬲蹠乇亘賶賷蹠爻賶 蹕蹠 卅賶卮賯丕 卅賵乇蹏賳賱丕卮鬲蹏乇蹏卮 賲蹏賱丕夭賶賲賶鬲賶 卅蹏夭丕賯 卅蹐賳蹐賲賱蹐賰 禺賶夭賲蹠鬲 賲蹛禺丕賳賶夭賲賶賳賶 卅賵乇賳賶鬲賶倬貙 噩蹠賲卅賶賷蹠鬲賳賶诃 卅蹠亘蹠丿賶賷 卅蹠賲賶賳賱賶賰賶诏蹠 鬲蹠爻賶乇 賷蹠鬲賰蹐夭蹐蹕丕鬲賯丕賳 賷賵卮蹏乇蹏賳 卅丕賲賶賱賱丕乇賳賶 賲蹠賳亘蹠丿賶賳 鬲蹐诏賶鬲賶卮 賰蹛乇蹠賰鈥衡贺 鈥光关曎嗃囏ㄙ壻 卮賶賳噩丕诃丿賶賰賶 卅丕夭 爻丕賳賱賶賯 賲賶賱賱蹠鬲 卅丕賲賲賶賳賶诃 賲蹠丿蹠賳賶賷蹠鬲 爻丕倬丕爻賶 蹕蹠 鬲蹠乇亘賶賷蹠賱賶賳賶卮 丿蹠乇賶噩賶爻賶賳賶 卅蹎爻鬲蹐乇蹐倬貙 鬲賵賯賯蹏夭 賷賶賱賱賶賯 賲蹠噩亘蹏乇賶賷蹠鬲 賲丕卅丕乇賶倬賶賳賶 丿蹠賱 噩丕賷賶丿丕 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇蹐卮貙 噩蹠賳蹏亘賶賷 卮賶賳噩丕诃丿賶賰賶 卅蹐趩 蹕賶賱丕賷蹠鬲貙 亘賶乇 卅賵亘賱丕爻鬲鬲丕 12 賷賶賱賱賶賯 诰蹠賯爻賶夭 賲蹠噩亘蹏乇賶賷蹠鬲 賲丕卅丕乇賶倬賶賳賶 鬲蹛夭 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇蹐卮 賰蹛乇蹠賰鈥衡贺 鈥光关促壻嗀и嗁壼 鬲蹛乇乇賵乇賱蹏賯賯丕 賯丕乇卮賶 鬲蹏乇蹏卮 賰蹐乇賶卮賶賳賶诃 卅丕賱丕诰賶丿賶賱賶賰賶诏蹠 賲丕爻 賰蹛賱賶丿賶睾丕賳 夭賵乇丕蹕丕賳賱賶賯貙 鬲蹛乇乇賵乇賱蹏賯 噩賶賳丕賷賶 賯賶賱賲賶卮賶睾丕 賯丕賯卮丕鬲賯蹏趩 夭蹠乇亘蹠 亘蹛乇賶丿賶睾丕賳 賷蹠乇賱賶賰 賳賶夭丕賲 亘蹠賱诏賶賱賶賲賶賱蹠乇賳賶 鬲蹐夭蹐卮 賰蹛乇蹠賰鈥衡... 亘蹏 亘賶乇 賯丕鬲丕乇 鬲蹠賰賱賶倬賱蹠乇 卅賵賲蹏賲賶賷蹠鬲賰蹠 夭賶趩 亘丕睾賱丕賳睾丕賳.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鈥光关壺壻呚ж壻 賲蹏賯賶賲賱賶賯 蹕蹠 卅蹠亘蹠丿賶賷 卅蹠賲賶賳賱賶賰鈥衡贺 鈥光关促壻嗀и嗁 賯丕賳蹏賳 亘賵賷賶趩蹠 卅賶丿丕乇蹠 賯賶賱賶卮鈥衡 亘丕卮 鬲蹛賲賶爻賶丿賶賰賶 丿丕卅賶賲賶賷 賰賵賲賶鬲蹛鬲 賷賶睾賶賳賶 卅蹛趩賶倬貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲睾丕 14 倬丕乇趩蹠 鬲蹠賰賱賶倬 鬲丕倬卮蹏乇丿賶. 鈥光关ωз矩堎嗁堎 乇丕賷賵賳賳賶诃 卅賶鬲鬲賶倬丕賯貙 賲蹏賯賶賲 蹕蹠夭賶賷賶鬲賶賳賶 賯蹠鬲卅賶賷 賯賵睾丿丕卮 鬲賵睾乇賶爻賶丿賶賰賶 賯丕乇丕乇鈥衡嘿嗁 趩賶賯賶乇賶倬貙 夭賵乇丕蹕丕賳賱賶賯貙 鬲蹛乇乇賵乇賱蹏賯 噩賶賳丕賷賶 诰蹠乇賶賰蹠鬲賱賶乇賶诏蹠 賯丕賯卮丕鬲賯蹏趩 夭蹠乇亘蹠 亘蹛乇賶卮貙 卮賶賳噩丕诃賳賶诃 卅賶噩鬲賶賲丕卅賶賷 賲蹏賯賶賲賱賶賯賶賳賶 賯賵睾丿丕卮 鬲賵睾乇賶爻賶丿丕 趩丕賯賶乇賶賯 趩賶賯丕乇丿賶... 亘蹏 亘賶乇 賯丕鬲丕乇 诰蹠乇賶賰蹠鬲賱蹠乇 卅蹠賲蹠賱賶賷蹠鬲賳賶诃 爻賶賳賶賯賶丿賶賳 卅蹎鬲鬲賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 賲蹏賯賶賲賱賶賯賯丕 卅丕賱丕賯賶丿丕乇 賲蹏诰賶賲 賲蹠爻賶賱賶丿蹠 卅蹛賳賶賯 倬賵夭賶鬲爻賶賷蹠 亘賶賱丿蹐乇丿賶. 賷蹛賯賶賳賯賶 賷賶賱賱丕乇丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賶賲賶夭丿賶賰賶 诰蹠乇 丿蹠乇賶噩賶賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鬲蹠卮賰賶賱丕鬲賱賶乇賶 卅賵禺卮賶賲賶睾丕賳 卮蹠賰賶賱丿蹠 噩蹠賲卅賶賷 5400 賯蹛鬲賶賲丿賶賳 賰蹎倬乇蹠賰 爻蹎诰亘蹠鬲 賷賶睾賶賳賶貙 賱蹛賰爻賶賷蹠貙 卮賶賰丕賷蹠鬲 賷賶睾賶賳賶 卅蹛趩賶倬貙 诰蹠乇 賲賶賱賱蹠鬲 卅丕賲賲賶賳賶 賲賶賱賱賶賷 亘蹎賱诏蹐賳趩賶賱賶賰 蹕蹠 丿賶賳 卅蹠爻蹠亘賶賷賱賶賰賶 卅賶丿賶賷蹠爻賶賳賶诃 爻賶诃賶倬 賰賶乇賶卮賶诏蹠 賯蹠鬲卅賶賷 賯丕乇卮賶 鬲蹏乇蹏卮賯丕 賷蹛鬲蹠賰賱蹠倬 蹕蹠 鬲蹠乇亘賶賷蹠賱蹠倬貙 噩蹠賲卅賶賷蹠鬲鬲賶賰賶 诰蹠乇 爻丕诰蹠丿賶賰賶賱蹠乇賳賶诃 賰蹐趩賱蹐賰 卅賶賳賰丕爻賶賳賶 賯賵夭睾賶丿賶.

    +

        卮蹏賳賶诃 亘賶賱蹠賳 亘賶賱賱蹠 诰蹠乇 丿蹠乇賶噩賶賱賶賰 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鬲蹠卮賰賶賱丕鬲賱賶乇賶 蹕蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕賱賶乇賶 鈥光关ㄛ曍 卅丕趩賯蹏趩鈥衡贺壻 卅蹏賳賶蹕蹛乇爻丕賱 倬丕賷丿賶賱賶賳賶倬貙 鬲賵睾乇丕 卅蹛鬲賶賯丕丿 卅丕乇賯賶賱賶賯 爻賶賯賶倬 趩賶賯賶乇賶卮貙 賲蹠丿蹠賳賶賷蹠鬲 卅丕乇賯賶賱賶賯 爻蹏爻賱丕卮鬲蹏乇蹏卮貙 賯丕賳蹏賳 卅賶丿丕乇蹠 賯賶賱賶卮 卅丕乇賯賶賱賶賯 趩蹠賰賱蹠卮貙 倬蹠賳賳賶 卅賵賲蹏賲賱丕卮鬲蹏乇蹏卮鬲賶賳 卅賶亘丕乇蹠鬲 鈥光关嗀嗁 鬲蹠诃 亘丕卮賯蹏乇蹏卮鈥衡贺 趩賶诃 鬲蹏乇蹏倬貙 鈥光官勠愘冐迟壻娵 卅蹎賲賶賰賶鈥衡贺 鈥光关曍篡嬞壻傌ж嗁夆衡嘿勜ж辟嗁壼 乇賵賱賶丿賶賳 鬲賵賱蹏賯 倬丕賷丿賶賱賶賳賶倬貙 丿賶賳 卅蹠爻蹠亘賶賷賱賶賰賶 卅賶丿賶賷蹠爻賶賳賶诃 夭賶賷賶賳賶賳賶 賰蹠诃 鬲蹠卮蹕賶賯 賯賶賱賶倬貙 卅丕爻丕爻賶賷 卅蹛賯賶賲 卅丕蹕丕夭賶賳賶 卅丕爻丕爻賶賷 賯丕鬲賱丕賲睾丕 賷蹠鬲賰蹐夭蹐倬貙 賰賶卮賶賱蹠乇賳賶 賷丕禺卮賶 鬲蹠乇亘賶賷蹠賱蹠倬貙 賯蹠賱亘賱蹠乇賳賶 鬲蹠爻賶乇賱蹠賳丿蹐乇蹐倬貙 鈥光关曍驰曍ㄙ壻娰勝壻冑嗁 鬲蹐诏賶鬲賶卮鈥衡嘿嗁 卅賶賱诏賶乇賶 爻蹐乇蹐卮 丿丕蹕丕賲賶丿丕 爻賶賷丕爻賶賷 賰蹛诃蹠卮 亘賶乇賱賶賰 爻蹛倬賶賳賶诃 卅丕賲賲賶蹕賶 禺賶夭賲蹠鬲鬲賶賰賶 卅蹠蹕夭蹠賱賱賶賰賶 蹕蹠 乇賵賱賶賳賶 噩丕乇賶 賯賶賱丿蹏乇丿賶.

    +

        賲丕诰賶乇賱賶賯 亘賶賱蹠賳 卅賶夭丿賶賳賶倬貙 丿丕丿賶賱 卅蹠賲蹠賱賶賷蹠鬲鬲賶賳 卅蹎鬲賰蹐夭蹐倬貙 卅蹠賲蹠賱賶賷 卅蹐賳蹐賲诏蹠 卅蹠诰賲賶賷蹠鬲 亘蹛乇賶倬貙 賰蹛诃賶卮賶卮 卮蹠賰賱賶丿蹠 賷蹛诃賶賱賶賯 賷丕乇賶鬲賶卮

    +

        23 鈥 賲丕乇鬲 趩蹐卮鬲賶賳 亘蹏乇蹏賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 亘賶乇 賲蹠賷丿丕賳 賯賶夭睾賶賳 爻蹎诰亘蹠鬲 賷賶睾賶賳賶 卅蹎鬲賰蹐夭丿賶. 賷賶睾賶賳睾丕 賯丕鬲賳丕卮賯丕賳 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕賱賶乇賶貙 賲蹏鬲蹠禺蹠爻爻賶爻賱蹠乇貙 賷蹠鬲鬲蹠 賮蹏賳賰爻賶賷蹠賱賶賰 鬲丕乇賲丕賯 蹕蹠 亘賶乇 賯賶爻賶賲 卅丕爻丕爻賶賷 賯丕鬲賱丕賲 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賲蹠爻卅蹏賱賱賶乇賶 鈥光关曎嗀曎嗁壽嬞 賷蹛夭丕 鈥 賯賶卮賱丕賯賱丕乇賳賶 賯賵睾丿丕卮鈥衡 丿蹛诏蹠賳 鬲蹛賲賶賳賶 趩蹎乇賶丿蹠倬 亘蹠爻 鈥 亘蹠爻鬲蹠 倬賶賰賶乇 亘丕賷丕賳 賯賶賱丿賶. 亘蹏 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 2014 鈥 賷賶賱賶 卅丕賷賱賶賯 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶 卅蹎鬲賰蹐夭蹐卮賳賶 賷賵賱睾丕 賯賵賷睾丕賳丿賶賳 亘蹏賷丕賳 卅蹎鬲賰蹐夭蹐賱诏蹠賳 19 鈥 賯蹛鬲賶賲賱賶賯 卅丕賷賱賶賯 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶.

    +

        賷蹛賯賶賳賯賶 賷賶賱賱丕乇丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 丿賶賯賯蹠鬲賳賶 鈥光关嗀 卅賵賲蹏賲賷蹐夭賱蹐賰鈥衡 卅賶爻鬲乇丕鬲蹛诏賶賷蹠賱賶賰 卅賵乇蹏賳賱丕卮鬲蹏乇賲賶爻賶睾丕 賲蹠乇賰蹠夭賱蹠卮鬲蹐乇蹐倬貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶诃 賲蹏诰賶賲 鬲蹠丿亘賶乇 卅賵乇蹏賳賱丕卮鬲蹏乇賲賶爻賶賳賶 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇蹐卮賰蹠 鬲蹐乇鬲賰蹠 亘賵賱蹏卮賳賶 趩蹎乇賶丿蹠倬貙 賰蹛诃賶卮賶卮 倬丕卅丕賱賶賷賶鬲賶賳賶诃 卅蹐賳蹐賲賱蹐賰 卮蹠賰賱賶 卅蹐爻鬲賶丿蹠 倬丕卅丕賱 卅賶夭丿賶賳賶倬貙 倬丕乇鬲賶賷蹠貙 诰蹎賰蹐賲蹠鬲 鬲丕乇賲丕賯賱賶乇賶 亘賶賱蹠賳 亘賵賱睾丕賳 禺賶夭賲蹠鬲 卅丕賱丕賯賶爻賶 鬲蹐夭蹐賲賶賳賶 賷蹠賳賶賲蹏 賲蹏賰蹠賲賲蹠賱賱蹠卮鬲蹐乇蹐倬貙 卅賵禺卮賶賲賶睾丕賳 卮蹠賰賶賱丿蹠 賲蹠禺爻蹏爻 賰蹛诃賶卮賶卮貙 賳賶卮丕賳賱賶賯 賰蹛诃賶卮賶卮貙 爻丕诰蹠賱蹠乇 亘賵賷賶趩蹠 賰蹛诃賶卮賶卮貙 鬲蹠賰賱賶倬 亘蹛噩賶乇賶卮 卅蹠诰蹕丕賱賶 亘賵賷賶趩蹠 賰蹛诃賶卮賶卮賳賶 賯丕賳丕鬲 賷丕賷丿蹏乇蹏倬貙 賰蹛诃賶卮賶卮 卅蹐賳蹐賲賶賳賶 賷蹠賳賶賲蹏 卅丕卮蹏乇丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 2014 鈥 賷賶賱賶丿賶賳 亘丕卮賱丕倬 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賰蹛诃賶卮賶卮 卅丕爻丕爻賶丿賶賰賶 丿蹛賲賵賰乇丕鬲賶賷蹠 賯蹠丿賶賲賶賳賶 卅蹐夭賱蹐賰爻賶夭 鬲蹛夭賱賶鬲賶卮 卅蹐爻鬲賶丿蹠 卅賶夭丿賶賳賶倬 蹕蹠 卅蹏賳賶 賰蹛诃蹠賷鬲賶倬貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 蹕蹠 噩蹠賲卅賶賷蹠鬲鬲賶賰賶 诰蹠乇 爻丕诰蹠賳賶诃 賷蹐賰爻蹠賰 丿賶賯賯賶鬲賶賳賶 賯賵夭睾賶丿賶 蹕蹠 鬲賵賱蹏賯 賲蹏卅蹠賷賷蹠賳賱蹠卮鬲蹐乇蹐卮賶诏蹠 卅蹛乇賶卮鬲賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鈥光关壺迟勜и矩ж嗁 卅賵賲蹏賲賷蹐夭賱蹐賰 趩賵诃賯蹏乇賱丕卮鬲蹏乇蹏卮鈥衡嘿嗁 亘丕卮 鬲蹛賲丕 賯賶賱賶倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 11 鈥 賳蹎蹕蹠鬲賱賶賰 賰賵賲賶鬲蹛鬲賶賳賶诃 7 鈥 賯蹛鬲賶賲賱賶賯 丿丕卅賶賲賶賷 賰賵賲賶鬲蹛鬲 賷賶睾賶賳賶賳賶 卅蹛趩賶倬貙 賲蹠賲蹏乇賶賷蹠鬲 卅賶卮賱賶乇賶賳賶 賲蹠禺爻蹏爻 賰蹛诃賶卮賶倬貙 賷賶倬蹠賰 賷賵賱賶 卅賶賯鬲賶爻丕丿 亘蹠賱亘蹛睾賶 賷丕丿乇賵賱蹏賯 乇丕賷賵賳賶 賯蹏乇蹏卮貙 賲蹠賲蹏乇賶賷 鬲蹠爻鬲賶賯 鬲蹐夭蹐賲賶 卅賶爻賱丕诰丕鬲賶賳賶 趩賵诃賯蹏乇賱丕卮鬲蹏乇蹏卮 賯丕鬲丕乇賱賶賯 賷蹠鬲鬲蹠 鬲蹠賰賱賶倬 賱丕賷賶诰蹠爻賶賳賶 卮蹠賰賶賱賱蹠賳丿蹐乇蹐倬貙 卅賶爻賱丕诰丕鬲賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮鬲賶賰賶 鬲蹠丿亘賶乇 亘蹠賱诏賶賱蹠卮賰蹠 賲蹠爻賱賶诰蹠鬲 亘蹛乇賶卮 乇賵賱賶賳賶 噩丕乇賶 賯賶賱丿蹏乇丿賶貨 鈥光关促壻嗀и嗁 賯丕賳蹏賳 亘賵賷賶趩蹠 卅賶丿丕乇蹠 賯賶賱賶卮鈥衡嘿嗁 亘丕卮 鬲蹛賲丕 賯賶賱賶倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 11 鈥 賳蹎蹕蹠鬲賱賶賰 賰賵賲賶鬲蹛鬲賶賳賶诃 10 鈥 賯蹛鬲賶賲賱賶賯 丿丕卅賶賲賶賷 賰賵賲賶鬲蹛鬲 賷賶睾賶賳賶賳賶 卅蹛趩賶倬貙 賲蹠賲蹏乇賶賷蹠鬲 卅賶卮賱賶乇賶賳賶 賲蹠禺爻蹏爻 賰蹛诃賶卮賶倬貙 賯丕賳蹏賳 卅賶丿丕乇蹠 賯賶賱賶丿賶睾丕賳 卮賶賳噩丕诃 賯蹏乇蹏卮 卅蹐趩蹐賳 卅蹠賯賶賱 賰蹎乇爻蹠鬲鬲賶貨 鬲蹠诃乇賶鬲丕睾 1 鈥 賲蹏夭賱蹏賯賶 鬲蹠亘賶卅賶賷 賲蹏诰丕倬賶夭蹠鬲 乇丕賷賵賳賶 賯蹏乇蹏卮賳賶 賲蹠禺爻蹏爻 賰蹛诃賶卮賶倬貙 丿蹛賲賵賰乇丕鬲賶賰 賳丕夭丕乇蹠鬲 賯賶賱賶卮 禺賶夭賲賶鬲賶賳賶 賰蹐趩蹠賷鬲賶卮 卅蹐爻鬲賶丿蹠 卅賶夭丿蹠賳丿賶貨 鈥光关促壻嗀и 卅賶禺鬲賶爻丕爻賱賶賯賱丕乇賳賶 鬲蹠乇蹠賯賯賶賷 賯賶賱丿蹏乇蹏卮鈥衡嘿嗁 亘丕卮 鬲蹛賲丕 賯賶賱賶倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 11 鈥 賳蹎蹕蹠鬲賱賶賰 賰賵賲賶鬲蹛鬲賶賳賶诃 11 鈥 賯蹛鬲賶賲賱賶賯 丿丕卅賶賲賶賷 賰賵賲賶鬲蹛鬲 賷賶睾賶賳賶賳賶 卅蹛趩賶倬 賲蹠賲蹏乇賶賷蹠鬲 卅賶卮賱賶乇賶賳賶 賲蹠禺爻蹏爻 賰蹛诃賶卮賶倬貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 鈥光关壺壺池ж迟勝壻傎勜ж 卅丕乇賯賶賱賶賯 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶 賯蹏丿乇蹠鬲 鬲丕倬賯蹏夭蹏卮鈥衡 卅賶爻鬲乇丕鬲蹛诏賶賷蹠賱賶賰 卅賵乇蹏賳賱丕卮鬲蹏乇賲賶爻賶賳賶 卅蹠賲蹠賱賶賷 诰蹠乇賶賰賶鬲賶 卅丕乇賯賶賱賶賯 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 2014 鈥 賷賶賱賶 鬲蹏賳噩賶 賯蹛鬲賶賲 賰蹛诃賶卮賶卮 禺賶夭賲賶鬲賶 賷賶賱賱賶賯 倬賶賱丕賳賶賳賶 鬲蹐夭丿賶貙 卅賶賰賰賶 賷賶賱丿賶賳 亘蹏賷丕賳 噩蹠賲卅賶賷 26 鬲蹐乇賱蹐賰 賰蹛诃賶卮賶卮 倬賶賱丕賳賶賳賶 鬲蹐夭丿賶貙 鈥光官娰壻勝勝壻 賰蹛诃賶卮賶卮 倬賶賱丕賳賶賳賶 亘蹛賰賶鬲賶卮 蹕蹠 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇蹐卮 鬲賵睾乇賶爻賶丿賶賰賶 蹕丕賯賶鬲賱賶賯 賷賵賱睾丕 賯賵賷蹏卮 趩丕乇賶爻賶鈥衡嘿嗁 鬲蹐夭蹐倬貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 丿丕卅賶賲賶賷 賰賵賲賶鬲蹛鬲賶賳賶诃 鬲蹠爻鬲賶賯賱賶卮賶 诰蹠賲 鬲蹠卮賰賶賱賱蹠倬 賷賵賱睾丕 賯賵賷蹏卮賶睾丕 爻蹏賳蹏倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賰蹛诃賶卮賶卮 倬丕卅丕賱賶賷賶鬲賶賳賶 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 卅賵乇蹏賳賱丕卮鬲蹏乇賲賶賱賶乇賶丿丕 鬲蹛禺賶賲蹏 賳丕賲丕賷丕賳 賯賶賱賶倬貙 鬲蹐乇賱蹐賰 賰蹛诃賶卮賶卮 倬丕卅丕賱賶賷蹠鬲賱賶乇賶賳賶 鬲蹛禺賶賲蹏 賯蹛賱賶倬賱丕卮鬲蹏乇丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 2014 鈥 賷賶賱賶 2 鈥 卅丕賷丿丕 鬲蹏賳噩賶 賯蹛鬲賶賲賱賶賯 卅丕賷賱賶賯 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶 卅丕趩鬲賶貙 诰丕夭賶乇睾賶趩蹠 賲賶賱賱賶賷 鬲蹛亘丕亘蹠鬲 丿賵乇賶诏蹠乇賱賶賰賶賳賶 乇丕蹕丕噩賱丕賳丿蹏乇蹏卮貙 爻丕賳丕卅蹠鬲 乇丕賷賵賳賱賶乇賶賳賶诃 卅蹛賳蹛乇诏賶賷蹠賳賶 鬲蹛噩蹠倬貙 亘蹏賱睾賶賲賶賳賶 卅丕夭丕賷鬲賶卮賳賶 趩蹎乇賶丿賶诏蹠賳 诰丕賱丿丕 19 賯蹛鬲賶賲賱賶賯 卅丕賷賱賶賯 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶 卅丕趩鬲賶貙 賰蹛诃賶卮賶卮 鬲蹛賲賶爻賶賳賶诃 賰蹎倬賶賳趩賶爻賶丿蹠 卅賵賲蹏賲賶賷蹠鬲賰蹠 賲蹏賳丕爻賶蹕蹠鬲賱賶賰 鈥光官冑壼嗁壻 賲蹠爻賶賱賶賱蹠乇鈥衡嘿嗁 趩賶賯賶卮 賯賶賱賶倬 卅賵鬲鬲蹏乇賶睾丕 賯賵賷睾丕賳 賰蹛诃賶卮賶卮 倬賶賰賶乇賱賶乇賶 倬丕乇鬲賰賵賲貙 禺蹠賱賯 诰蹎賰蹐賲賶鬲賶 鬲蹠乇賶倬賶丿賶賳 賯賵亘蹏賱 賯賶賱賶賳賶倬貙 賲賵賱 賳蹠鬲賶噩蹠 亘蹛乇賶倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶賳賶诃 亘賶乇 趩賵诃 賷丕乇賯賶賳 賳蹏賯鬲賶爻賶睾丕 卅丕賷賱丕賳丿賶.

    +

        2016 鈥 賷賶賱賶 趩丕睾丕賳 鬲蹐诏賶卮賶 亘賶賱蹠賳賱丕 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 爻丕賷丕诰蹠鬲趩賶賱賶賰賳賶 乇丕蹕丕噩賱丕賳丿蹏乇蹏卮賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮 賳賶卮丕賳賱賶賯 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶貙 卮賶賳噩丕诃賳賶诃 卅丕賱丕诰賶丿蹠 鬲賶乇丕賳爻賮賵乇賲賵鬲賵乇 卅蹛賱蹛賰鬲賶乇 鬲賵乇賶 賯蹏乇蹏賱蹏卮賶 蹕蹠 卅蹛賱蹛賰鬲賶乇 卅蹛賳蹛乇诏賶賷蹠 賲蹠禺爻蹏爻 賰蹛诃賶卮賶卮 爻蹎诰亘蹠鬲 賷賶睾賶賳賶賳賶 卅丕趩鬲賶貙 亘蹏 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 倬丕乇鬲诏蹏乇蹏倬倬賶爻賶賳賶诃 賷蹛诃賶 賷賶賱丿賶賰賶 賷蹛诃賶 诰蹠乇賶賰賶鬲賶丿蹠 賷蹛诃賶賱賶賯 賷丕乇丕鬲賯丕賳賱賶賯賶貙 卮蹏賳丿丕賯賱丕 賰蹛诃賶卮賶卮 卅丕爻丕爻賶丿賶賰賶 丿蹛賲賵賰乇丕鬲賶賷蹠 卮蹠賰賱賶賳賶 賰蹛诃蹠賷鬲賶卮鬲賶賰賶 賲蹏诰賶賲 卅蹏爻蹏賱 亘賵賱蹏倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賰蹛诃賶卮賶卮 卅丕爻丕爻賶丿賶賰賶 丿蹛賲賵賰乇丕鬲賶賷蹠 賯蹏乇蹏賱蹏卮賶賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮鬲蹠 卅蹐賱诏賶賱賶賰 乇賵賱 卅賵賷賳賶丿賶.

    +

        倬蹐鬲蹐賳 賰蹐趩 亘賶賱蹠賳 卅賶卮賱蹠卮賰蹠 賲丕诰賶乇 亘賵賱蹏倬貙 鬲蹠乇蹠賯賯賶賷丕鬲賳賶 賰蹎夭賱蹠倬 卅賶賯鬲賶爻丕丿賶賷貙 卅賶噩鬲賶賲丕卅賶賷 卅賶卮賱丕乇睾丕 賲蹏賱丕夭賶賲蹠鬲 賯賶賱賶卮

    +

        噩 賰 倬 賲蹠乇賰賶夭賶賷 賰賵賲賶鬲蹛鬲賶 爻賶賷丕爻賶賷 亘賶賷蹏乇賵爻賶賳賶诃 卅蹠夭丕爻賶貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 卮蹏噩賶爻賶 噩丕诃 趩蹐賳卮賷蹠賳 2014 鈥 賷賶賱賶賳賶诃 卅丕禺賶乇賶丿丕 鈥光关促壻嗀и嗁 卅蹠诃 倬丕賰賶夭 噩丕賷 賯賶賱賶倬 賯蹏乇蹏倬 趩賶賯賶卮鈥衡贺曎 卅蹛賰賵賱賵诏賶賷蹠 賲蹠丿蹠賳賶賷賱賶賰賶 賯蹏乇蹏賱蹏卮賶 鬲蹛賲賶爻賶賳賶 鬲蹠賳鬲蹠賳賶賱賶賰 卅賵鬲鬲蹏乇賶睾丕 賯賵賷丿賶 诰蹠賲 亘蹏 禺賶夭賲蹠鬲賳賶 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賲蹠爻卅蹏賱 亘賵賱蹏卮賶睾丕 鬲丕倬卮蹏乇丿賶.

    +

        亘賶乇 賷賶賱丿賶賳 賰蹛賷賶賳 鈥光官矩з冑壺 卮賶賳噩丕诃 賯蹏乇蹏卮鈥衡 卅賶丿賶賷蹠爻賶 賰賶卮賶賱蹠乇 賯蹠賱亘賶丿賶賳 卅賵乇蹏賳 卅丕賱丿賶貙 卮賶賳噩丕诃丿賶賰賶 诰蹠乇 賲賶賱賱蹠鬲 禺蹠賱賯 倬丕賰賶夭 卮賶賳噩丕诃 賯蹏乇蹏卮賯丕 賯賶夭睾賶賳 卅丕鬲賱丕賳丿賶貙 卮賶賳噩丕诃賳賶诃 鬲丕睾賱賶乇賶 鬲蹛禺賶賲蹏 賷蹛卮賶賱賱賶賯賯丕 倬蹐乇賰蹠賳丿賶貙 爻蹐賷賶 鬲蹛禺賶賲蹏 爻蹐夭蹐賱丿賶貙 诰丕蹕丕爻賶 鬲蹛禺賶賲蹏 爻丕倬賱丕卮鬲賶... 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 倬丕賰賶夭 卮賶賳噩丕诃 賯蹏乇蹏卮 禺賶夭賲賶鬲賶賳賶 趩賶诃 鬲蹏鬲蹏倬貙 鬲蹠诃乇賶鬲丕睾賳賶诃 噩蹠賳蹏亘賶 蹕蹠 卮賶賲丕賱賶睾丕 賷蹛卮賶賱賱賶賯 卅蹏乇蹏賯賶賳賶 趩丕趩鬲賶.

    +

        賷蹛賯賶賳賯賶 賷賶賱賱丕乇丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 鈥光关嗀 卅賵賲蹏賲賷蹐夭賱蹐賰鈥衡 卅賶爻鬲乇丕鬲蹛诏賶賷蹠賱賶賰 卅賵乇蹏賳賱丕卮鬲蹏乇賲賶爻賶 亘賵賷賶趩蹠 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 卅賵乇蹏賳賱丕卮鬲蹏乇睾丕賳 賲蹠禺爻蹏爻 禺賶夭賲蹠鬲賱蹠乇賳賶 夭賶趩 趩蹎乇賶丿蹠倬貙 禺蹠賱賯 爻賶賷丕爻賶賷 賲蹠爻賱賶诰蹠鬲 賰蹛诃賶卮賶賳賶诃 卅丕賱丕賯蹠 丿丕卅賶乇賶爻賶 賰蹠诃貙 卅賶禺鬲賶爻丕爻賱賶賯賱丕乇 鬲賵倬賱丕賳睾丕賳 亘賵賱蹏卮鬲蹠賰 卅蹠蹕夭蹠賱賱賶賰賶賳賶 鬲賶乇賶卮賶倬 噩丕乇賶 賯賶賱丿蹏乇蹏倬貙 倬丕賰賶夭 卮賶賳噩丕诃 賯蹏乇蹏賱蹏卮賶貙 卅丕丿蹠鬲鬲賶賳 鬲丕卮賯賶乇賶 賳蹛賮賶鬲 鈥 诏丕夭 亘丕賷賱賶賯賶賳賶 趩丕乇賱丕卮 鈥 卅蹛趩賶卮貙 禺丕爻 賷蹛賲蹠賰 鈥 卅賶趩賲蹠賰 賰蹠爻倬賶賳賶 乇丕蹕丕噩賱丕賳丿蹏乇蹏卮 賯丕鬲丕乇賱賶賯 禺賶夭賲蹠鬲賱蹠乇丿蹠 賲蹠爻卅蹏賱賶賷蹠鬲賳賶 丿丕丿賶賱 夭賶賲賲賶爻賶诏蹠 卅蹛賱賶倬貙 丿丕丿賶賱 卅蹠賲蹠賱賶賷蹠鬲鬲賶賳 卅蹎鬲賰蹐夭蹐倬貙 鬲蹠卮蹠亘亘蹏爻賰丕乇 亘賵賱蹏倬貙 卅蹠賯賶賱 賰蹎乇爻賶鬲賶卮 爻蹐倬賶鬲賶賳賶 卅蹎爻鬲蹐乇蹐卮賰蹠 賰蹐趩蹠倬貙 爻蹎夭賶 乇丕爻鬲 亘賵賱蹏卮貙 鬲蹠丿亘賶乇賶 卅蹠賲蹠賱賶賷 亘賵賱蹏卮貙 诰蹠乇賶賰賶鬲賶 鬲賵睾乇丕 亘賵賱蹏卮賳賶 卅賶卮賯丕 卅丕卮蹏乇蹏倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 賷丕禺卮賶 卅丕蹕丕夭賶賳賶 賷丕诃乇丕鬲鬲賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 賲蹠丿蹠賳賶賷蹠鬲貙 鬲丕乇賶禺 賲丕鬲蹛乇賶賷丕賱 禺賶夭賲賶鬲賶賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮鬲蹠 賷蹛诃賶賱賶賯 賷丕乇賶鬲賶倬貙 卅丕夭 爻丕賳賱賶賯 賲賶賱賱蹠鬲賱蹠乇賳賶诃 100 賷賶賱賱賶賯 卅蹠賲蹠賱賶賷 禺丕鬲賶乇賶爻賶貙 卮賶賳噩丕诃賳賶诃 鈥光关堏 卅蹠賱鈥衡 倬丕卅丕賱賶賷賶鬲賶 卅蹠賲蹠賱賶賷 禺丕鬲賶乇賶爻賶貙 賷丕倬賵賳 亘丕爻賯蹏賳趩賶賱賶乇賶睾丕 賯丕乇卮賶 卅蹏乇蹏卮 禺丕鬲賶乇賶爻賶貙 睾蹠乇亘賶賷 乇丕賷賵賳賳賶 賰蹠诃 卅蹛趩賶卮貙 卅蹠噩丿丕丿賱賶乇賶賲賶夭 賯丕鬲丕乇賱賶賯 鬲丕乇賶禺賶賷 賲丕鬲蹛乇賶賷丕賱賱丕乇賳賶 鬲賵倬賱丕倬 鬲蹐夭丿賶貙 亘蹠夭賶 賳蹠卮乇 亘蹏賷蹏賲賱賶乇賶 卅蹛賱賶賲賶夭賳賶诃 趩蹛诏乇丕 賲蹠丿蹠賳賶賷蹠鬲 鬲丕乇賶禺賶 賰賶鬲丕亘賱賶乇賶賳賶诃 卅蹐賱诏賶爻賶 亘賵賱丿賶貙 亘蹠夭賶賱賶乇賶 卮賶賳噩丕诃賳賶诃 賷丕倬賵賳 亘丕爻賯蹏賳趩賶賱賶乇賶睾丕 賯丕乇卮賶 卅蹏乇蹏卮 鬲丕乇賶禺賶賷 賲丕鬲蹛乇賶賷丕賱賱賶乇賶丿賶賰賶 亘賵卮賱蹏賯賳賶 鬲賵賱丿蹏乇蹏倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 鬲丕乇賶禺賳賶 卅蹠爻鬲蹠 鬲蹏鬲蹏倬貙 卅蹠賱賳賶 卅賶丿丕乇蹠 賯賶賱賶卮貙 卅賶鬲鬲賶倬丕賯賱賶卮賶卮貙 卅丕丿蹠賲 鬲蹠乇亘賶賷蹠賱蹠卮 賮蹏賳賰爻賶賷蹠爻賶賳賶 鬲賵賱蹏賯 噩丕乇賶 賯賶賱丿蹏乇丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 賷蹠賳蹠 卅賶爻賱丕诰丕鬲貙 鬲蹠乇蹠賯賯賶賷丕鬲賯丕 賰蹐趩蹠卮貙 禺蹠賱賯 鬲蹏乇賲蹏卮賶睾丕 卅蹠诰賲賶賷蹠鬲 亘蹛乇賶卮貙 卮賶賳噩丕诃賳賶 賯丕賳蹏賳 亘賵賷賶趩蹠 卅賶丿丕乇蹠 賯賶賱賶卮鬲賶賰賶 卅賶卮賱蹠卮 蹕蹠 賳蹠鬲賶噩蹠 賷丕乇賶鬲賶卮賯丕 卅蹠诰賲賶賷蹠鬲 亘蹛乇賶倬貙 賲蹠賲蹏乇賶賷蹠鬲 卅賶卮賱賶乇賶賳賶 賲蹠禺爻蹏爻 賰蹛诃賶卮賶卮 卅丕乇賯賶賱賶賯 卅賶爻賱丕诰丕鬲賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮鬲蹠 鬲蹠丿亘賶乇 亘蹠賱诏賶賱蹠卮鬲賶賳 賲蹠爻賱賶诰蹠鬲 亘蹛乇賶卮 乇賵賱賶賳賶 噩丕乇賶 賯賶賱丿蹏乇丿賶 诰蹠賲 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 鬲蹐乇賱蹐賰 卅賶爻鬲乇丕鬲蹛诏賶賷蹠賱賶賰 卅賵乇蹏賳賱丕卮鬲蹏乇賲賶賱賶乇賶賳賶 卅蹠賲蹠賱賶賷 诰蹠乇賶賰賶鬲賶 卅丕乇賯賶賱賶賯 卅賶夭趩賶賱賱丕卮鬲蹏乇丿賶.

    +

        卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅丕賲賲丕 賰蹎诃蹐賱 亘蹎賱賶丿賶睾丕賳 卅賶卮賱丕乇賳賶 賰蹎诃賱賶诏蹠 倬蹐賰蹐倬貙 爻賶賷丕爻賶賷 賰蹛诃蹠卮賳賶诃 禺蹠賱賯 卅蹐趩蹐賳 賰蹛诃賶卮賶卮貙 禺蹠賱賯賳賶 賰蹎夭賱蹠卮貙 禺蹠賱賯 卅蹐趩蹐賳 卅蹠賯賶賱 賰蹎乇爻賶鬲賶卮貙 禺蹠賱賯 卅蹐趩蹐賳 賰蹐趩 賯賵卮蹏卮賶賳賶 卅丕诃賱賶賯 卅賶卮賯丕 卅丕卮蹏乇丿賶. 賷蹛賯賶賳賯賶 賷賶賱賱丕乇丿賶賳 亘蹏賷丕賳 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲賳賶诃 鈥光关曎勝 鬲蹏乇賲蹏卮賶 卅蹠賱丕貙 卅丕賲賲丕 亘賶乇賶賳趩賶貙 卅丕爻丕爻賶賷 賯丕鬲賱丕賲 賲蹏诰賶賲鈥衡 鬲蹠賱賶倬賶賳賶 卅蹠爻鬲丕賷賶丿賶賱 卅賶夭趩賶賱賱丕卮鬲蹏乇蹏倬貙 禺蹠賱賯 卅蹐趩蹐賳 蹕蹠夭賶倬賶爻賶賳賶 卅丕丿丕 賯賶賱賶卮鬲丕 趩賶诃 鬲蹏乇蹏倬貙 卅賶卮賯丕 卅賵乇蹏賳賱丕卮鬲蹏乇蹏卮貙 賲丕卅丕乇賶倬貙 丿丕蹕丕賱丕卮貙 卅賶噩鬲賶賲丕卅賶賷 賰丕倬丕賱蹠鬲 賯丕鬲丕乇賱賶賯 诰蹠乇 賲賶賱賱蹠鬲 卅丕賲賲賶賳賶诃 賲蹠賳倬蹠卅賶鬲賶诏蹠 賲蹏賳丕爻賶蹕蹠鬲賱賶賰 賲蹠爻賶賱賶賱蹠乇賳賶 夭賶趩 趩蹎乇賶丿蹠倬 倬丕卅丕賱 卅蹠賯賶賱 賰蹎乇爻蹠鬲鬲賶. 賯賶夭 卅賶爻鬲蹏丿蹛賳鬲賱丕乇賳賶 卅賶卮賯丕 卅賵乇蹏賳賱丕卮鬲蹏乇蹏卮貙 賰蹠爻倬賶賷 賲丕卅丕乇賶倬 蹕蹠 賰蹠爻倬賶賷 鬲蹛禺賳賶賰丕 賲丕诰丕乇賶鬲賶 亘賵賷賶趩蹠 鬲蹠乇亘賶賷蹠賱蹠卮賳賶 賰蹐趩蹠賷鬲賶卮貙 卅蹐乇蹐賲趩賶賳賶诃 卅丕鬲賲賵爻賮蹛乇丕 亘蹏賱睾賶賳賶卮賶賳賶 鬲賶夭诏賶賳賱蹠卮貙 賷蹛夭賶賱丕乇丿賶賰賶 卅丕乇鬲蹏賯 卅蹠賲诏蹠賰趩賶賱蹠乇賳賶 賷蹎鬲賰蹠卮賳賶 鬲蹛夭賱賶鬲賶卮 蹕蹠 賷蹛夭丕 賷蹏賯賶乇賶 卅蹐賳蹐賲賱蹐賰 爻蹏 鬲蹛噩蹠卮 賯蹏乇蹏賱蹏卮賶 賯丕鬲丕乇賱賶賯 賯丕乇丕賱賲賶賱丕乇賳賶 趩賵诃賯蹏乇 鬲蹠賰卮蹐乇蹐倬 鬲蹠鬲賯賶賯 賯賶賱賶倬貙 禺蹠賱賯 鬲蹏乇賲蹏卮賶 賯蹏乇蹏賱蹏卮賶賳賶 卅賶賱诏賶乇賶 爻蹐乇蹐卮 卅蹐趩蹐賳 卅蹠賲蹠賱賶賷 鬲蹠丿亘賶乇 賰蹎乇爻賶鬲賶倬貙 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇蹐卮賰蹠 鬲蹐乇鬲賰蹠 亘賵賱丿賶. 賯賶賷賶賳趩賶賱賶賯賶 亘丕乇 诰蹠乇 賲賶賱賱蹠鬲 卅丕賲賲賶賳賶诃 卅賶卮賱蹠倬趩賶賯賶乇賶卮 蹕蹠 鬲蹏乇賲蹏卮賶睾丕 賰蹎诃蹐賱 亘蹎賱蹐倬 卅賵鬲鬲蹏乇賶睾丕 賯賵賷睾丕賳 賯賵賷貙 賰丕賱丕 诏蹎卮賶 鬲賵賱蹏賯賱賶賲賶爻賶 亘蹛乇賶卮 爻丕賱賲賶賯賶賳賶 卅丕卮蹏乇蹏卮貙 趩蹛诏乇丕 乇丕賷賵賳丿賶賰賶 卅丕夭 爻丕賳賱賶賯 賲賶賱賱蹠鬲 乇丕賷賵賳賱賶乇賶賳賶诃 卅蹠賲賶賳 鬲丕倬賯蹏夭蹏倬 禺蹠賱賯賳賶 亘蹛賷賶鬲賶卮貙 卅賵賱鬲蹏乇丕賯賱丕卮鬲蹏乇蹏倬 趩丕乇蹕賶趩賶賱賶賯賳賶 诏蹐賱賱蹠賳丿蹐乇蹐卮 賯蹏乇蹏賱蹏卮賶貙 趩丕乇蹕賶趩賶賱丕乇賳賶诃 賷丕賷賱丕賯 诰賵賯蹏賯 鈥 賲蹠賳倬蹠卅賶鬲賶賳賶 賯賵睾丿丕卮賳賶 賰蹐趩蹠賷鬲賶卮 噩蹠诰蹠鬲賱蹠乇丿賶賰賶 鬲蹠賰賱賶倬賱賶乇賶賳賶诃 诰蹠賲賲賶爻賶 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 鬲蹠乇賶倬賶丿賶賳 賯賵亘蹏賱 賯賶賱賶賳賶倬 卅蹠賲蹠賱賶賷賱蹠卮鬲蹐乇蹐賱丿賶.

    +

        诰蹠乇 賲賶賱賱蹠鬲貙 诰蹠乇 爻丕诰蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮 卅蹠夭丕賱賶乇賶 卮賶賳噩丕诃賳賶诃 卅賶賯鬲賶爻丕丿賶賷貙 卅賶噩鬲賶賲丕卅賶賷 卅賶卮賱賶乇賶丿賶賰賶 禺蹏卮丕賱賱賶賳丕乇賱賶賯 卅蹎夭诏賶乇賶卮賱蹠乇賳賶 亘賶蹕丕爻賶鬲蹠 賰蹎乇丿賶 蹕蹠 卅蹏賳賶诃睾丕 賯丕鬲賳丕卮鬲賶貙 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 爻賶賷丕爻賶賷 賰蹛诃蹠卮 蹕蹠 爻賶賷丕爻賶賷 賰蹛诃蹠卮賰蹠 賯丕鬲賳丕卮賯丕賳 倬丕乇鬲賶賷蹠 鈥 诏蹏乇蹏诰賱丕乇貙 鬲蹠卮賰賶賱丕鬲賱丕乇貙 诰蹠乇 賲賶賱賱蹠鬲貙 诰蹠乇 爻丕诰蹠 夭丕鬲賱丕乇 卮賶賳噩丕诃丿賶賰賶 诰蹠乇 賲賶賱賱蹠鬲 禺蹠賱賯 亘賶賱蹠賳 賲蹐乇賶賳賶 鈥 賲蹐乇賶诏蹠 鬲賶乇蹠倬 卅賶賱诏賶乇賶賱蹠倬貙 卮丕賳賱賶賯 賳蹠鬲賶噩蹠 蹕蹠 卮丕賳賱賶賯 爻蹠诰賶倬蹠 賷丕乇丕鬲鬲賶.

    +
    + +
    +

    卅蹠爻賰蹠乇鬲賶卮:

    + 鬲賵乇賶賲賶夭丿賶賰賶 卅蹠爻蹠乇賱蹠乇賳賶诃 賳蹠卮賶乇 诰賵賯蹏賯賶 卮賶賳噩丕诃 卅蹏賷睾蹏乇 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 卅丕禺亘丕乇丕鬲 卅賶卮禺丕賳賶爻賶睾丕 鬲蹠蹕蹠貙 诰蹠乇賯丕賷爻賶 鬲丕乇丕鬲賯蹏賱丕乇 賰蹎趩蹐乇蹐倬 鬲丕乇賯丕鬲賯丕賳丿丕 芦鬲蹠诃乇賶鬲丕睾 鬲賵乇賶鈥衡 丿蹠倬 賲蹠賳亘蹠賳賶 卅蹛賳賶賯 卅蹠爻賰蹠乇鬲賶卮賶 賰蹛乇蹠賰貙 亘賵賱賲賶爻丕 賯丕賳蹏賳賶賷 噩丕蹕丕亘賰丕乇賱賶賯賶 爻蹐乇蹐卮鬲蹠 賯賶賱賶賳賶丿蹏. +
    + +
    + + + + + + +
    + +
    +
    + + +
    + + + +
    + +
    + + +
    + +
    + +
    + + +
    + + + + + \ No newline at end of file diff --git a/test/testdata_uni2ascii/original_uy.txt b/test/testdata_uni2ascii/original_uy.txt new file mode 100644 index 0000000..3bf7f2c --- /dev/null +++ b/test/testdata_uni2ascii/original_uy.txt @@ -0,0 +1,2 @@ +锘 + 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賳賶诃 2010鈥撡娰壻勝壺壻冑 卅丕倬鬲賵賳賵賲 乇丕賷賵賳賱蹏賯 倬丕乇鬲賰賵賲 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶 賷賶睾賶賳賶丿賶賳 亘蹏賷丕賳賯賶 爻賶賷丕爻賶賷 賰蹛诃蹠卮 禺賶夭賲賶鬲賶 鬲賵睾乇賶爻賶丿丕 卅賵賲蹏賲賶賷 亘丕賷丕賳 diff --git a/test/testdata_uni2ascii/qq_mail_https.txt b/test/testdata_uni2ascii/qq_mail_https.txt new file mode 100644 index 0000000..d6aca74 --- /dev/null +++ b/test/testdata_uni2ascii/qq_mail_https.txt @@ -0,0 +1,326 @@ +锘绛斿: weiyu - QQ閭
    绛斿: weiyu
    鍙戜欢浜猴細閮戣秴 <littlefang@126.com>    
    鏃   闂达細2016骞3鏈31鏃(鏄熸湡鍥) 涓嬪崍5:52绾枃鏈 |
    鏀朵欢浜猴細
    test <testyouxiang2000@qq.com>

     

     

    鍙件浜: 閮戣秴 [mailto:littlefang@126.com]
    鍙戦佹椂闂: 2016331 17:07
    鏀件浜: 'monitor5210@sina.com' <monitor5210@sina.com>
    涓婚: weiyu

     

     ئاپتونوم رايوننىڭ 2010鈥يىلىدىكى ئاپتونوم رايونلۇق پارتكوم سىياسىي كېڭەش خىزمىتى يىغىنىدىن بۇيانقى سىياسىي كېڭەش خىزمىتى توغرىسىدا ئومۇمىي بايان

     

    +
    +يىلىدىكى + + diff --git a/test/testdata_uni2ascii/sina_read_mail.txt b/test/testdata_uni2ascii/sina_read_mail.txt new file mode 100644 index 0000000..fcbd9fe --- /dev/null +++ b/test/testdata_uni2ascii/sina_read_mail.txt @@ -0,0 +1 @@ +锘縶"result":true,"errno":0,"msg":"","data":{"from":"testyouxiang2000@sohu.com","to":"\"testyouxiang2013\" ","cc":"","bcc":"","date":1459416272,"subject":"weiyu_fromsohu","priority":false,"notification_to":false,"xmsgid":"","isstar":false,"size":5778,"body":"

     <\/span><\/p>\n\n

    <\/span><\/span><\/span><\/span> \u0626\u0627\u067e\u062a\u0648\u0646\u0648\u0645 \u0631\u0627\u064a\u0648\u0646\u0646\u0649\u06ad\n2010\u2013\u064a\u0649\u0644\u0649\u062f\u0649\u0643\u0649 \u0626\u0627\u067e\u062a\u0648\u0646\u0648\u0645 \u0631\u0627\u064a\u0648\u0646\u0644\u06c7\u0642 \u067e\u0627\u0631\u062a\u0643\u0648\u0645 \u0633\u0649\u064a\u0627\u0633\u0649\u064a \u0643\u06d0\u06ad\u06d5\u0634 \u062e\u0649\u0632\u0645\u0649\u062a\u0649 \u064a\u0649\u063a\u0649\u0646\u0649\u062f\u0649\u0646 \u0628\u06c7\u064a\u0627\u0646\u0642\u0649\n\u0633\u0649\u064a\u0627\u0633\u0649\u064a \u0643\u06d0\u06ad\u06d5\u0634 \u062e\u0649\u0632\u0645\u0649\u062a\u0649 \u062a\u0648\u063a\u0631\u0649\u0633\u0649\u062f\u0627 \u0626\u0648\u0645\u06c7\u0645\u0649\u064a \u0628\u0627\u064a\u0627\u0646<\/strong><\/span><\/o:p><\/span><\/p>


    <\/strong><\/span><\/p>

    THIS THE END<\/strong><\/span><\/p>




    <\/a><\/div>\n


    ","ishtml":true,"attlist":[],"mid":"0468E2CEF23DB6E2F922C3916ACC53D99300000000000001","fid":"new","sendstatus":null,"neednotify":false}} \ No newline at end of file diff --git a/test/testdata_uni2ascii/sohu_mail_unicode.txt b/test/testdata_uni2ascii/sohu_mail_unicode.txt new file mode 100644 index 0000000..1b156ec --- /dev/null +++ b/test/testdata_uni2ascii/sohu_mail_unicode.txt @@ -0,0 +1 @@ +锘縶"status": 1, "body": {"noconv": 0, "xtype": "", "encoding": 1, "type": 6, "charset": "", "force_charset": 0, "filename": "", "use_disp": 1, "subtype": "alternative", "length": 4040, "parts": [{"noconv": 0, "xtype": "", "encoding": 4, "type": 7, "charset": "", "force_charset": 0, "filename": "", "use_disp": 1, "subtype": "plain", "length": 564, "parts": "", "disposition": 0, "offset": 599, "form_name": "", "parameter": [["charset", "utf-8"]], "id": "", "d_filename": "", "description": ""}, {"noconv": 0, "xtype": "", "encoding": 4, "type": 7, "charset": "", "force_charset": 0, "filename": "", "use_disp": 1, "subtype": "html", "length": 3153, "parts": "", "disposition": 0, "offset": 1295, "form_name": "", "parameter": [["charset", "utf-8"]], "id": "", "d_filename": "", "description": ""}], "disposition": 0, "offset": 467, "form_name": "", "parameter": [["boundary", "----_=_NextPart_000_5b646341bfe7432f8237183bcf2e000e"]], "id": "", "d_filename": "", "description": ""}, "star": 0, "envelope": {"display_date": ["17:24", "3\u5206\u949f"], "cc": [], "references": [], "bcc": [], "subject": "weiyu_fromsohu", "from": [["", "testyouxiang2000@sohu.com"]], "from_after_1st_unread": [], "to": [["testyouxiang2013", "testyouxiang2013@sina.com"]], "userhdrs": [["X-Sohu-DeliverStatus", "<1459416272.ccab860401154443bf3d649ea1f67123.testyouxiang2000@sohu.com>"]], "message_id": "<1459416272.ccab860401154443bf3d649ea1f67123.testyouxiang2000@sohu.com>", "reply_to": [], "date": "Thu, 31 Mar 2016 17:24:32 +0800", "in_reply_to": [], "received": 0, "sender": [], "return_path": [], "mail_followup_to": [], "date_sent": 1459416272}, "maximum": "", "single": 1, "rowid": 478, "offset": 0, "path": "160331.8a5792b78519408ebc5c6966694f6557", "folder": 3, "size": 4507, "mailfrom": "testyouxiang2000@sohu.com", "name": "160331.8a5792b78519408ebc5c6966694f6557", "thread": 364, "mbox": 0, "have_forward": 0, "mid": "LMEQAAAANGZO37CWOMHAAAAAGIYDELRUGMXDCNBYFYYTMNTTDEAAAADUMVZXI6LPOV4GSYLOM4ZDAMBQIBZW62DVFZRW63LTE4AAAABRGYYDGMZRFY4GCNJXHEZGENZYGUYTSNBQHBSWEYZVMM3DSNRWGY4TIZRWGU2TO2IAAAAAA2M3CEAAA2IAAAAAA4YOAAAAA3LFONZWCZ3FF5ZGMYZYGIZHGEQAAAAHOZLJPF2V6ZTSN5WXG33IOUXGK3LM.2e987ff5eb62a18f10f1d758d6c9d00f", "display": "

     

    \n\n

     ئاپتونوم رايوننىڭ\n2010–يىلىدىكى ئاپتونوم رايونلۇق پارتكوم سىياسىي كېڭەش خىزمىتى يىغىنىدىن بۇيانقى\nسىياسىي كېڭەش خىزمىتى توغرىسىدا ئومۇمىي بايان


    THIS THE END






    \n


    ", "content": "\u0626\u0627\u067e\u062a\u0648\u0646\u0648\u0645 \u0631\u0627\u064a\u0648\u0646\u0646\u0649\u06ad 2010\u2013\u064a\u0649\u0644\u0649\u062f\u0649\u0643\u0649 \u0626\u0627\u067e\u062a\u0648\u0646\u0648\u0645 \u0631\u0627\u064a\u0648\u0646\u0644\u06c7\u0642 \u067e\u0627\u0631\u062a\u0643\u0648\u0645 \u0633\u0649\u064a\u0627\u0633\u0649\u064a \u0643\u06d0\u06ad\u06d5\u0634 \u062e\u0649\u0632\u0645\u0649\u062a\u0649 \u064a\u0649\u063a\u0649\u0646\u0649\u062f\u0649\u0646 \u0628\u06c7\u064a\u0627\u0646\u0642\u0649 \u0633\u0649", "attach": [], "have_read": 1, "memo": "", "have_reply": 0} \ No newline at end of file From 4a5cd85ecfe1aa0fd3aa9293b600261dee16d40d Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 6 Apr 2016 10:41:59 +0800 Subject: [PATCH 19/31] =?UTF-8?q?=E5=90=88=E5=B9=B6=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=ACmesa=5Ffuzzy=EF=BC=88SFH=EF=BC=89=E5=88=B0maat?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E8=8A=82=E7=9C=81=E5=86=85=E5=AD=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 2 +- src/entry/Maat_rule.cpp | 2 +- src/entry/Makefile | 2 +- .../great_index_engine.h | 0 src/entry/interval_index.c | 669 ++++----- src/{inc_internal => entry}/interval_index.h | 31 +- src/entry/mesa_fuzzy.c | 1267 ++++++++--------- src/{inc_internal => entry}/mesa_fuzzy.h | 0 src/entry/rbtree.c | 548 +++++++ src/entry/rbtree.h | 118 ++ src/entry/rbtree_augmented.h | 241 ++++ src/entry/sfh_internal.h | 106 ++ src/entry/zt_hash.h | 234 +++ test/Makefile | 2 +- test/digest_gen.c | 2 +- test/maat_json.json | 2 +- 16 files changed, 2178 insertions(+), 1048 deletions(-) rename src/{inc_internal => entry}/great_index_engine.h (100%) rename src/{inc_internal => entry}/interval_index.h (92%) rename src/{inc_internal => entry}/mesa_fuzzy.h (100%) create mode 100644 src/entry/rbtree.c create mode 100644 src/entry/rbtree.h create mode 100644 src/entry/rbtree_augmented.h create mode 100644 src/entry/sfh_internal.h create mode 100644 src/entry/zt_hash.h diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 00013cf..883f360 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -1322,7 +1322,7 @@ inline int REACH_QUERY_THRESH(unsigned long long total_len,unsigned long long ac // { // return 1; // } - if(rate<(unsigned long long)(point_size+QUERY_MIN_RATE)) + if(rate>(unsigned long long)(point_size+QUERY_MIN_RATE)) { return 0; } diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 6294157..30ba55a 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_6_20160403=1; +int MAAT_FRAME_VERSION_1_7_20160406=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", diff --git a/src/entry/Makefile b/src/entry/Makefile index 6ef9b6e..4b72255 100644 --- a/src/entry/Makefile +++ b/src/entry/Makefile @@ -16,7 +16,7 @@ LIBMAAT = libmaatframe.a LIBMAAT_SO = libmaatframe.so OBJS=config_monitor.o Maat_rule.o Maat_api.o Maat_stat.o UniversalBoolMatch.o dynamic_array.o cJSON.o\ - json2iris.o map_str2int.o interval_index.o great_index_engine.o mesa_fuzzy.o + json2iris.o map_str2int.o interval_index.o great_index_engine.o mesa_fuzzy.o rbtree.o .c.o: $(CC) -c $(CFLAGS) -I. $(H_DIR) $< diff --git a/src/inc_internal/great_index_engine.h b/src/entry/great_index_engine.h similarity index 100% rename from src/inc_internal/great_index_engine.h rename to src/entry/great_index_engine.h diff --git a/src/entry/interval_index.c b/src/entry/interval_index.c index 581acbe..b993a3f 100644 --- a/src/entry/interval_index.c +++ b/src/entry/interval_index.c @@ -1,7 +1,17 @@ -#include -#include -#include"interval_index.h" - +/********************************************************************* + * File: + * interval_index.c + * Author: + * TangQi + * E-mail: + * tangqi@iie.ac.cn + *********************************************************************/ +#include +#include +#include +#include "interval_index.h" +#include "rbtree.h" +#include "rbtree_augmented.h" /** * There is a trick here. In order to hide specific @@ -16,73 +26,113 @@ * Structure of inner segment **/ typedef struct __IVI_shadow_seg_t{ - IVI_seg_t lightseg; - TAILQ_ENTRY(__IVI_shadow_seg_t) ENTRY; + IVI_seg_t lightseg; /* interval for user, including left edge, right edge, and user's data */ + struct rb_node rb; /* node of rb-tree */ + OFFSET_TYPE max; /* max edge of subtree */ }IVI_shadow_seg_t; -TAILQ_HEAD(TQ, __IVI_shadow_seg_t); - /* Structure of inner InterVal Index */ typedef struct __IVI_shadow_t{ - struct TQ ivi_queue; + struct rb_root root; + + /* statistics */ int segs_cnt; OFFSET_TYPE segs_length; + unsigned long long mem_occupy; //do not include user data }IVI_shadow_t; -/** - * new is closer to head or tail ? - * Return 1 if closer to head than tail - * Else return 0 - */ -int closer_to_head(IVI_shadow_seg_t * head, IVI_shadow_seg_t * tail, OFFSET_TYPE target) + + +IVI_seg_t * IVI_first_seg(IVI_t * handler) { - if(head == NULL || tail == NULL) - return 1; - S_OFFSET_TYPE tmp1 = (S_OFFSET_TYPE)(target - head->lightseg.left); - S_OFFSET_TYPE tmp2 = (S_OFFSET_TYPE)(target - tail->lightseg.left); - S_OFFSET_TYPE distance_to_head = tmp1 > 0 ? tmp1 : -tmp1; - S_OFFSET_TYPE distance_to_tail = tmp2 > 0 ? tmp2 : -tmp2; - return (distance_to_tail - distance_to_head > 0); + assert(handler != NULL); + IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; + struct rb_node *first_node = rb_first(&(shadow_ivi->root)); + if(first_node == NULL) + return NULL; + return (IVI_seg_t *)(rb_entry(first_node, IVI_shadow_seg_t, rb)); +} + + +IVI_seg_t * IVI_last_seg(IVI_t * handler) +{ + assert(handler != NULL); + IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; + struct rb_node *last_node = rb_last(&(shadow_ivi->root)); + if(last_node == NULL) + return NULL; + return (IVI_seg_t *)(rb_entry(last_node, IVI_shadow_seg_t, rb)); +} + + + +IVI_seg_t * IVI_prev_seg(IVI_seg_t * seg) +{ + assert(seg != NULL); + IVI_shadow_seg_t * shadow_seg = (IVI_shadow_seg_t *)seg; + struct rb_node * prev_node = rb_prev(&(shadow_seg->rb)); + if(prev_node == NULL) + return NULL; + return (IVI_seg_t *)(rb_entry(prev_node, IVI_shadow_seg_t, rb)); +} + + + +IVI_seg_t * IVI_next_seg(IVI_seg_t * seg) +{ + assert(seg != NULL); + IVI_shadow_seg_t * shadow_seg = (IVI_shadow_seg_t *)seg; + struct rb_node * next_node = rb_next(&(shadow_seg->rb)); + if(next_node == NULL) + return NULL; + return (IVI_seg_t *)(rb_entry(next_node, IVI_shadow_seg_t, rb)); } IVI_seg_t * IVI_prev_continuous_seg(IVI_seg_t * seg) { - if(NULL == seg) + assert(seg != NULL); + IVI_shadow_seg_t * shadow_seg = (IVI_shadow_seg_t *)seg; + struct rb_node * prev_node = rb_prev(&(shadow_seg->rb)); + if(prev_node == NULL) { return NULL; } - - IVI_shadow_seg_t * _seg = (IVI_shadow_seg_t *)seg; - IVI_shadow_seg_t * prev = TAILQ_PREV(_seg, TQ, ENTRY); - if(NULL == prev) + IVI_seg_t * prev_seg = (IVI_seg_t *)(rb_entry(prev_node, IVI_shadow_seg_t, rb)); + if(!continuous(prev_seg->right, seg->left)) { return NULL; } - if(continuous((prev->lightseg).right, seg->left)) - return (IVI_seg_t *)prev; - return NULL; + return prev_seg; } IVI_seg_t * IVI_next_continuous_seg(IVI_seg_t * seg) { - if(NULL == seg) + assert(seg != NULL); + IVI_shadow_seg_t * shadow_seg = (IVI_shadow_seg_t *)seg; + struct rb_node * next_node = rb_next(&(shadow_seg->rb)); + if(next_node == NULL) { return NULL; } - IVI_shadow_seg_t * _seg = (IVI_shadow_seg_t *)seg; - IVI_shadow_seg_t * next = TAILQ_NEXT(_seg, ENTRY); - if(NULL == next) + IVI_seg_t * next_seg = (IVI_seg_t *)(rb_entry(next_node, IVI_shadow_seg_t, rb)); + if(!continuous(seg->right, next_seg->left)) { return NULL; } - if(continuous(seg->right, (next->lightseg).left)) - return (IVI_seg_t *)next; - return NULL; + return next_seg; +} + + +static inline int __is_overlapped(OFFSET_TYPE left1, OFFSET_TYPE right1, OFFSET_TYPE left2, OFFSET_TYPE right2) +{ + if(!after(left1, right2) && !after(left2, right1)) + return 1; + return 0; } @@ -152,13 +202,42 @@ Relation_t IVI_relative_position(IVI_seg_t * seg1, IVI_seg_t * seg2) IVI_t * IVI_create(void) { IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)malloc(sizeof(IVI_shadow_t)); - TAILQ_INIT(&(shadow_ivi->ivi_queue)); + shadow_ivi->root = RB_ROOT; //init rb tree's root shadow_ivi->segs_cnt = 0; shadow_ivi->segs_length = 0; + shadow_ivi->mem_occupy = sizeof(IVI_shadow_t); return (IVI_t *)shadow_ivi; } + +static void __free_rb_tree(struct rb_node * root, IVI_callback_t cb, void * usr_para) +{ + if(root == NULL) + { + return; + } + if(root->rb_left != NULL) + { + __free_rb_tree(root->rb_left, cb, usr_para); + } + if(root->rb_right != NULL) + { + __free_rb_tree(root->rb_right, cb, usr_para); + } + /* free user data */ + IVI_shadow_seg_t * shadow_seg = rb_entry(root, IVI_shadow_seg_t, rb); + if(cb != NULL) + { + cb((IVI_seg_t *)shadow_seg, usr_para); + } + + /* free seg */ + free(shadow_seg); + shadow_seg = NULL; + return; +} + /** * Name: * IVI_destroy @@ -177,26 +256,11 @@ void IVI_destroy(IVI_t * handler, IVI_callback_t cb, void * usr_para) { return; } - IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; - IVI_shadow_seg_t * tmpseg = TAILQ_FIRST(&(shadow_ivi->ivi_queue)); - IVI_shadow_seg_t * tmp; - /* Free each seg in IVI */ - while(tmpseg != NULL) - { - tmp = TAILQ_NEXT(tmpseg, ENTRY); - /* Free *data in seg */ - if(NULL != cb) - { - cb(&(tmpseg->lightseg), usr_para); - } - free(tmpseg); - tmpseg = tmp; - } - - /* Free IVI */ + __free_rb_tree(shadow_ivi->root.rb_node, cb, usr_para); free(shadow_ivi); handler = NULL; + return; } @@ -224,6 +288,7 @@ IVI_seg_t * IVI_seg_malloc(OFFSET_TYPE left, OFFSET_TYPE right, void * data) shadow_seg->lightseg.left = left; shadow_seg->lightseg.right= right; shadow_seg->lightseg.data = data; + shadow_seg->max = 0; return (IVI_seg_t *)shadow_seg; } @@ -244,6 +309,8 @@ IVI_seg_t * IVI_seg_malloc(OFFSET_TYPE left, OFFSET_TYPE right, void * data) **/ void IVI_seg_free(IVI_seg_t * seg, IVI_callback_t cb, void * usr_para) { + assert(seg != NULL); + /* Free user data first */ if(cb != NULL) { @@ -257,6 +324,70 @@ void IVI_seg_free(IVI_seg_t * seg, IVI_callback_t cb, void * usr_para) } + + +static inline OFFSET_TYPE __interval_tree_get_subtree_max(IVI_shadow_seg_t * node) +{ + OFFSET_TYPE max = node->lightseg.right, subtree_max; + if(node->rb.rb_left) + { + subtree_max = (rb_entry(node->rb.rb_left, IVI_shadow_seg_t, rb))->max; + if(before(max, subtree_max)) + max = subtree_max; + } + if(node->rb.rb_right) + { + subtree_max = (rb_entry(node->rb.rb_right, IVI_shadow_seg_t, rb))->max; + if(before(max, subtree_max)) + max = subtree_max; + } + return max; +} + + +static void __interval_tree_augment_propagate(struct rb_node * rb, struct rb_node * stop) +{ + while(rb != stop) + { + IVI_shadow_seg_t * node = rb_entry(rb, IVI_shadow_seg_t, rb); + OFFSET_TYPE subtree_max = __interval_tree_get_subtree_max(node); + if(node->max == subtree_max) + { + break; + } + node->max = subtree_max; + rb = rb_parent(&node->rb); + } + return; +} + + +static void __interval_tree_augment_copy(struct rb_node * rb_old, struct rb_node * rb_new) +{ + IVI_shadow_seg_t * old = rb_entry(rb_old, IVI_shadow_seg_t, rb); + IVI_shadow_seg_t * new = rb_entry(rb_new, IVI_shadow_seg_t, rb); + new->max = old->max; + return; +} + + +static void __interval_tree_augment_rotate(struct rb_node * rb_old, struct rb_node * rb_new) +{ + IVI_shadow_seg_t * old = rb_entry(rb_old, IVI_shadow_seg_t, rb); + IVI_shadow_seg_t * new = rb_entry(rb_new, IVI_shadow_seg_t, rb); + new->max = old->max; + old->max = __interval_tree_get_subtree_max(old); + return; +} + + +static const struct rb_augment_callbacks __interval_tree_augment_callbacks = { + __interval_tree_augment_propagate, + __interval_tree_augment_copy, + __interval_tree_augment_rotate +}; + + /** * Name: * IVI_insert @@ -273,74 +404,49 @@ void IVI_seg_free(IVI_seg_t * seg, IVI_callback_t cb, void * usr_para) **/ int IVI_insert(IVI_t * handler, IVI_seg_t * seg) { - IVI_shadow_t * shadow_ivi; - IVI_shadow_seg_t *head, *tail, *new_seg, *tmp_seg; - if(NULL == handler || NULL == seg) { return -1; } - shadow_ivi = (IVI_shadow_t *)handler; - new_seg = (IVI_shadow_seg_t *)seg; - head = TAILQ_FIRST(&(shadow_ivi->ivi_queue)); - tail = TAILQ_LAST(&(shadow_ivi->ivi_queue), TQ); - - if(closer_to_head(head, tail, seg->left)) + IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; + struct rb_root * root = &(shadow_ivi->root); + OFFSET_TYPE left = seg->left, right = seg->right; + struct rb_node **link = &root->rb_node, *rb_parent = NULL; + IVI_shadow_seg_t * parent = NULL; + IVI_shadow_seg_t * new_seg = (IVI_shadow_seg_t *)seg; + while(*link) { - TAILQ_FOREACH(tmp_seg, &(shadow_ivi->ivi_queue), ENTRY) + rb_parent = *link; + parent = rb_entry(rb_parent, IVI_shadow_seg_t, rb); + /* is overlapped */ + if(__is_overlapped(left, right, parent->lightseg.left, parent->lightseg.right)) + { + //overlapped, return + return -1; + } + + if(before(parent->max, right)) { - /* Find the first seg whose left is bigger than given seg's right, we will insert new seg before it */ - if(after(tmp_seg->lightseg.left, new_seg->lightseg.right)) - { - TAILQ_INSERT_BEFORE(tmp_seg, new_seg, ENTRY); - shadow_ivi->segs_cnt ++; - shadow_ivi->segs_length += (seg->right - seg->left + 1); - return 0; - } - else if(before(tmp_seg->lightseg.right, new_seg->lightseg.left)) - { - continue; - } - else /* Overlap */ - { - return -1; - } + parent->max = right; } - - /* If have searched to the end of list, we will inset it to the tail */ - TAILQ_INSERT_TAIL(&(shadow_ivi->ivi_queue), new_seg, ENTRY); - shadow_ivi->segs_cnt ++; - shadow_ivi->segs_length += (seg->right - seg->left + 1); - } - else - { - TAILQ_FOREACH_REVERSE(tmp_seg, &(shadow_ivi->ivi_queue), TQ, ENTRY) + if(before(left, parent->lightseg.left)) { - /* Find the first seg whose right is smaller than given seg's left, we will insert new seg after it */ - if(before(tmp_seg->lightseg.right, new_seg->lightseg.left)) - { - TAILQ_INSERT_AFTER(&(shadow_ivi->ivi_queue), tmp_seg, new_seg, ENTRY); - shadow_ivi->segs_cnt ++; - shadow_ivi->segs_length += (seg->right - seg->left + 1); - return 0; - } - else if(after(tmp_seg->lightseg.left, new_seg->lightseg.right)) - { - continue; - } - else /* Overlap */ - { - return -1; - } + link = &parent->rb.rb_left; + } + else + { + link = &parent->rb.rb_right; } - - /* If have searched to the head of list, we will inset it to the head */ - TAILQ_INSERT_HEAD(&(shadow_ivi->ivi_queue), new_seg, ENTRY); - shadow_ivi->segs_cnt ++; - shadow_ivi->segs_length += (seg->right - seg->left + 1); } + new_seg->max = right; + rb_link_node(&new_seg->rb, rb_parent, link); + rb_insert_augmented(&new_seg->rb, root, &__interval_tree_augment_callbacks); + /* updata statistics */ + shadow_ivi->segs_cnt ++; + shadow_ivi->segs_length += seg->right - seg->left + 1; + shadow_ivi->mem_occupy += sizeof(IVI_shadow_seg_t); return 0; } @@ -367,16 +473,56 @@ int IVI_remove(IVI_t * handler, IVI_seg_t * seg) } IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; - IVI_shadow_seg_t * shadow_seg = (IVI_shadow_seg_t *)seg; + struct rb_root * root = &(shadow_ivi->root); + IVI_shadow_seg_t * new_seg = (IVI_shadow_seg_t *)seg; + rb_erase_augmented(&new_seg->rb, root, &__interval_tree_augment_callbacks); - TAILQ_REMOVE(&(shadow_ivi->ivi_queue), shadow_seg, ENTRY); + /* updata statistics */ shadow_ivi->segs_cnt --; - shadow_ivi->segs_length -= (seg->right - seg->left + 1); + shadow_ivi->segs_length -= seg->right - seg->left + 1; + shadow_ivi->mem_occupy -= sizeof(IVI_shadow_seg_t); + return 0; } +static struct rb_node * __min_interval_search_from(struct rb_node * node, OFFSET_TYPE left, OFFSET_TYPE right) +{ + if(node == NULL) + { + return NULL; + } + IVI_shadow_seg_t * seg = rb_entry(node, IVI_shadow_seg_t, rb); + IVI_shadow_seg_t * left_seg = rb_entry(node->rb_left, IVI_shadow_seg_t, rb); + if(node->rb_left != NULL && !before(left_seg->max, left)) + { + struct rb_node * ret = __min_interval_search_from(node->rb_left, left, right); + if(ret != NULL) + { + return ret; + } + else if(__is_overlapped(left, right, seg->lightseg.left, seg->lightseg.right)) + { + return node; + } + else + { + return NULL; + } + } + else if(__is_overlapped(left, right, seg->lightseg.left, seg->lightseg.right)) + { + return node; + } + else + { + return __min_interval_search_from(node->rb_right, left, right); + } +} + + + /** * Name: * IVI_query @@ -397,115 +543,34 @@ int IVI_remove(IVI_t * handler, IVI_seg_t * seg) **/ int IVI_query(IVI_t * handler, OFFSET_TYPE left, OFFSET_TYPE right, IVI_seg_t *** segs) { - IVI_shadow_t * shadow_ivi; - IVI_shadow_seg_t *head, *tail, *tmp, *left_tmp, *right_tmp; - int interval_cnt = 0, i; - if(NULL == handler || after(left, right)) { + //augments error return -1; } - shadow_ivi = (IVI_shadow_t *)handler; - head = TAILQ_FIRST(&(shadow_ivi->ivi_queue)); - tail = TAILQ_LAST(&(shadow_ivi->ivi_queue), TQ); + int interval_cnt = 0, max_cnt = 8; + IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; + struct rb_node * root = shadow_ivi->root.rb_node; + struct rb_node * min_overlap = __min_interval_search_from(root, left, right); + struct rb_node * tmp_node = min_overlap; - /* Traverse from head or tail? We need to decide */ - if(closer_to_head(head, tail, left)) + *segs = (IVI_seg_t **)malloc(max_cnt * sizeof(IVI_seg_t *)); + while (tmp_node != NULL) { - tmp = head; - while(tmp != NULL) + IVI_seg_t * tmp_seg = (IVI_seg_t *)(rb_entry(tmp_node, IVI_shadow_seg_t, rb)); + if(!__is_overlapped(tmp_seg->left, tmp_seg->right, left, right)) { - if(after(left, tmp->lightseg.right)) - { - tmp = TAILQ_NEXT(tmp, ENTRY); - } - else - { - /* Get the seg which left is in or before*/ - left_tmp = tmp; - break; - } + break; } - if(tmp == NULL) + if(interval_cnt > max_cnt) { - *segs = NULL; - return 0; - } - - /* Get the num of overlapped segs */ - while(tmp != NULL) - { - if(!before(right, tmp->lightseg.left)) - { - tmp = TAILQ_NEXT(tmp, ENTRY); - interval_cnt ++; - } - else - { - break; - } - } - - tmp = left_tmp; - if(interval_cnt == 0) - { - *segs = NULL; - return 0; - } - *segs = (IVI_seg_t **)malloc(interval_cnt * sizeof(IVI_seg_t *)); - for(i = 0; i < interval_cnt; i++) - { - (*segs)[i] = (IVI_seg_t *)tmp; - tmp = TAILQ_NEXT(tmp, ENTRY); - } - } - else - { - tmp = tail; - while(tmp != NULL) - { - if(before(right, tmp->lightseg.left)) - { - tmp = TAILQ_PREV(tmp, TQ, ENTRY); - } - else - { - right_tmp = tmp; - break; - } - } - if(tmp == NULL) - { - *segs = NULL; - return 0; - } - - /* Get the num of overlapped segs */ - while(tmp != NULL) - { - if(!after(left, tmp->lightseg.right)) - { - tmp = TAILQ_PREV(tmp, TQ, ENTRY); - interval_cnt ++; - } - else - { - break; - } - } - tmp = right_tmp; - if(interval_cnt == 0) - { - *segs = NULL; - return 0; - } - *segs = (IVI_seg_t **)malloc(interval_cnt * sizeof(IVI_seg_t *)); - for(i = interval_cnt - 1; i >= 0; i--) - { - (*segs)[i] = (IVI_seg_t *)tmp; - tmp = TAILQ_PREV(tmp, TQ, ENTRY); + max_cnt *= 2; + *segs = (IVI_seg_t **)realloc(*segs, max_cnt * sizeof(IVI_seg_t *)); } + (*segs)[interval_cnt] = tmp_seg; + interval_cnt ++; + tmp_node = rb_next(tmp_node); } return interval_cnt; } @@ -531,129 +596,41 @@ int IVI_query(IVI_t * handler, OFFSET_TYPE left, OFFSET_TYPE right, IVI_seg_t ** **/ int IVI_query_continuous(IVI_t * handler, OFFSET_TYPE left, OFFSET_TYPE right, IVI_seg_t *** segs) { - IVI_shadow_t * shadow_ivi; - IVI_shadow_seg_t *head, *tail, *tmp, *left_tmp, *right_tmp; - int interval_cnt = 0, i; - if(NULL == handler || after(left, right)) { + //augments error return -1; } - shadow_ivi = (IVI_shadow_t *)handler; - head = TAILQ_FIRST(&(shadow_ivi->ivi_queue)); - tail = TAILQ_LAST(&(shadow_ivi->ivi_queue), TQ); + int interval_cnt = 0, max_cnt = 8; + IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; + struct rb_node * root = shadow_ivi->root.rb_node; + struct rb_node * min_overlap = __min_interval_search_from(root, left, right); + struct rb_node * tmp_node = min_overlap; - - /* Traverse from head or tail? We need to decide */ - if(closer_to_head(head, tail, left)) + *segs = (IVI_seg_t **)malloc(max_cnt * sizeof(IVI_seg_t *)); + while (tmp_node != NULL) { - tmp = head; - while(tmp != NULL) + IVI_seg_t * tmp_seg = (IVI_seg_t *)(rb_entry(tmp_node, IVI_shadow_seg_t, rb)); + if(!__is_overlapped(tmp_seg->left, tmp_seg->right, left, right)) { - if(after(left, tmp->lightseg.right)) - { - tmp = TAILQ_NEXT(tmp, ENTRY); - } - else - { - /* Get the seg which left is in or before*/ - left_tmp = tmp; - break; - } + break; } - if(tmp == NULL) + if(interval_cnt > max_cnt) { - *segs = NULL; - return 0; + max_cnt += 8; + *segs = (IVI_seg_t **)realloc(*segs, max_cnt * sizeof(IVI_seg_t *)); } - - /* Get the num of overlapped segs */ - while(tmp != NULL) + (*segs)[interval_cnt] = tmp_seg; + interval_cnt ++; + tmp_node = rb_next(tmp_node); + IVI_seg_t * prev_tmp_seg = tmp_seg; + tmp_seg = (IVI_seg_t *)(rb_entry(tmp_node, IVI_shadow_seg_t, rb)); + if(!continuous(prev_tmp_seg->right, tmp_seg->left)) { - if(!before(right, tmp->lightseg.left)) - { - tmp = TAILQ_NEXT(tmp, ENTRY); - interval_cnt ++; - } - else - { - break; - } - - IVI_shadow_seg_t * prev = TAILQ_PREV(tmp, TQ, ENTRY); - if(tmp != NULL && !continuous(prev->lightseg.right, tmp->lightseg.left)) - { - break; - } - } - - tmp = left_tmp; - if(interval_cnt == 0) - { - *segs = NULL; - return 0; - } - *segs = (IVI_seg_t **)malloc(interval_cnt * sizeof(IVI_seg_t *)); - for(i = 0; i < interval_cnt; i++) - { - (*segs)[i] = (IVI_seg_t *)tmp; - tmp = TAILQ_NEXT(tmp, ENTRY); + break; } } - else - { - tmp = tail; - while(tmp != NULL) - { - if(before(right, tmp->lightseg.left)) - { - tmp = TAILQ_PREV(tmp, TQ, ENTRY); - } - else - { - right_tmp = tmp; - break; - } - } - if(tmp == NULL) - { - *segs = NULL; - return 0; - } - - /* Get the num of overlapped segs */ - while(tmp != NULL) - { - if(!after(left, tmp->lightseg.right)) - { - tmp = TAILQ_PREV(tmp, TQ, ENTRY); - interval_cnt ++; - } - else - { - break; - } - IVI_shadow_seg_t * next = TAILQ_NEXT(tmp, ENTRY); - if(tmp != NULL && !continuous(tmp->lightseg.right, next->lightseg.left)) - { - break; - } - } - tmp = right_tmp; - if(interval_cnt == 0) - { - *segs = NULL; - return 0; - } - *segs = (IVI_seg_t **)malloc(interval_cnt * sizeof(IVI_seg_t *)); - for(i = interval_cnt - 1; i >= 0; i--) - { - (*segs)[i] = (IVI_seg_t *)tmp; - tmp = TAILQ_PREV(tmp, TQ, ENTRY); - } - } - return interval_cnt; } @@ -698,6 +675,41 @@ OFFSET_TYPE IVI_seg_length(IVI_t * handler) } +/** + * Name: + * IVI_mem_occupy + * Description: + * Get the memory occupy of given interval index handler + * Params: + * handler: The handler of InterVal Index created by IVI_create. + * Return: + * Return the memory occupy of given interval index handler + **/ +unsigned long long IVI_mem_occupy(IVI_t * handler) +{ + if(handler == NULL) + return 0; + IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; + return shadow_ivi->mem_occupy; +} + + +static void __inorder_traverse(struct rb_node * root, IVI_callback_t cb, void * usr_para) +{ + if(root == NULL) + { + return; + } + + /* save first in case of root is freed in callback */ + struct rb_node * left_node = root->rb_left; + struct rb_node * right_node = root->rb_right; + __inorder_traverse(left_node, cb, usr_para); + IVI_seg_t * seg = (IVI_seg_t *)(rb_entry(root, IVI_shadow_seg_t, rb)); + cb(seg, usr_para); + __inorder_traverse(right_node, cb, usr_para); + return; +} /** * Name: @@ -720,17 +732,6 @@ void IVI_traverse(IVI_t * handler, IVI_callback_t cb, void * usr_para) } IVI_shadow_t * shadow_ivi = (IVI_shadow_t *)handler; - IVI_shadow_seg_t * tmp_seg = TAILQ_FIRST(&(shadow_ivi->ivi_queue)); - IVI_shadow_seg_t * tmp; - /* Traverse the IVI */ - while(tmp_seg != NULL) - { - /* - * The place we can't use TAILQ_FOREACH because we - * do not no what will callback funciton does. - * */ - tmp = TAILQ_NEXT(tmp_seg, ENTRY); - cb((IVI_seg_t *)tmp_seg, usr_para); - tmp_seg = tmp; - } + __inorder_traverse(shadow_ivi->root.rb_node, cb, usr_para); + return; } diff --git a/src/inc_internal/interval_index.h b/src/entry/interval_index.h similarity index 92% rename from src/inc_internal/interval_index.h rename to src/entry/interval_index.h index ad2dca4..a67c7ea 100644 --- a/src/inc_internal/interval_index.h +++ b/src/entry/interval_index.h @@ -6,7 +6,7 @@ * (3) The interval supports rollback. * * author: zhengchao@iie.ac.cn tangqi@iie.ac.cn - * last modify time: 2015-08-29 + * last modify time: 2015-12-04 *************************************************************************/ #ifndef _INTERVAL_INDEX_H_ @@ -16,12 +16,11 @@ extern "C"{ #endif -#include "queue.h" #define SIZE_8 #ifdef SIZE_8 -typedef unsigned long long OFFSET_TYPE; +typedef unsigned long long OFFSET_TYPE; typedef signed long long S_OFFSET_TYPE; #else typedef unsigned int OFFSET_TYPE; @@ -61,6 +60,10 @@ static inline int continuous(OFFSET_TYPE prev, OFFSET_TYPE next) } +IVI_seg_t * IVI_first_seg(IVI_t * handler); +IVI_seg_t * IVI_last_seg(IVI_t * handler); +IVI_seg_t * IVI_prev_seg(IVI_seg_t * seg); +IVI_seg_t * IVI_next_seg(IVI_seg_t * seg); IVI_seg_t * IVI_prev_continuous_seg(IVI_seg_t * seg); IVI_seg_t * IVI_next_continuous_seg(IVI_seg_t * seg); @@ -71,22 +74,22 @@ IVI_seg_t * IVI_next_continuous_seg(IVI_seg_t * seg); typedef enum __Relation_t{ LEFT_NO_OVERLAP = 1, // |___A___| // |___B___| - + LEFT_OVERLAP, // |___A___| // |___B___| CONTAINED, // |___A___| // |_____B_____| - + CONTAIN, // |_____A_____| // |___B___| - + RIGHT_OVERLAP, // |___A___| // |___B___| - + RIGHT_NO_OVERLAP, // |___A___| // |___B___| - + ERROR }Relation_t; @@ -273,6 +276,18 @@ int IVI_seg_cnt(IVI_t * handler); OFFSET_TYPE IVI_seg_length(IVI_t * handler); +/** + * Name: + * IVI_mem_occupy + * Description: + * Get the memory occupy of given interval index handler + * Params: + * handler: The handler of InterVal Index created by IVI_create. + * Return: + * Return the memory occupy of given interval index handler + **/ +unsigned long long IVI_mem_occupy(IVI_t * handler); + /** * Name: diff --git a/src/entry/mesa_fuzzy.c b/src/entry/mesa_fuzzy.c index 97e332f..88a1b6c 100644 --- a/src/entry/mesa_fuzzy.c +++ b/src/entry/mesa_fuzzy.c @@ -5,151 +5,100 @@ #include #include #include +#include #include "mesa_fuzzy.h" #include "interval_index.h" +//#define DEBUG_PRINT +#define INIT_SIZE 128 +#define ENTROPY_THRESHOLD 0.5 +int count = 0; +const char * b64 = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -#define ROLLING_WINDOW 7 -#define BLOCKSIZE_MIN 3 -#define MAXSIZE 10000 -#define HASH_PRIME 0x01000193 -#define HASH_INIT 0x28021967 - -#define DEBUG (0) - -struct roll_state +struct entry { - unsigned char window[ROLLING_WINDOW]; - unsigned int h1, h2, h3; - unsigned int n; + unsigned int * r_array; + unsigned int r_index; + unsigned int r_size; }; +double get_rs_entropy(unsigned int * r_array, unsigned int r_index); +int cmp(const void * a, const void * b); +void sfh_rs_entropy(IVI_seg_t * seg, void * user_para); +void sfh_tune_simulation(IVI_seg_t * seg, void * user_para); -typedef struct -{ - char * left_data; //指向数据的头指针 - unsigned int left_len; //左边保留数据的长度 - - char * hash_result; //这个segment的FNV值 - unsigned long long left_offset; - unsigned long long right_offset; - - struct roll_state * right_status_r; //右边界的rollhash状态 - unsigned int right_status_shash; //右边界的FNV值 - unsigned int right_len;//右边界的长度 - int slice_num; - -}fuzzy_node; - - -typedef struct -{ - unsigned long long orilen; - IVI_t * ivi; //每一个handle里面保存一个IVI指针,一个IVI里面保存的是一个文件里的片 - unsigned long long effective_length; - unsigned long long blocksize; -}fuzzy_handle_inner_t; - - -typedef struct -{ - char * head; //最后输出结果的char数组 - unsigned int size; - unsigned int offset; //数组长度 - unsigned long long first_FNV_offset; - unsigned long long last_FNV_offset; -}final_result; - - -typedef struct -{ - unsigned long long first_FNV_offset; - unsigned long long last_FNV_offset; - unsigned long long hash_length; -}final_length; - - -unsigned int fuzzy_hash_calculate(IVI_seg_t * seg, const char * data, unsigned long long offset, unsigned long long blocksize); -void fuzzy_calculate_self(IVI_seg_t * seg, const char * data, unsigned long long offset, unsigned long long blocksize); -void fuzzy_calculate_self_with_prev(IVI_seg_t * prev_seg, IVI_seg_t * seg, const char * data, unsigned long long blocksize); -void fuzzy_modify_next(IVI_seg_t * seg, IVI_seg_t * next_seg, unsigned long long blocksize); -unsigned long long get_prev_continous_length(IVI_seg_t * seg); -unsigned int segment_overlap(fuzzy_handle_t * handle, fuzzy_node * fnode, unsigned int size, unsigned long long offset, const char * data); -void fuzzy_hash_merge(IVI_seg_t * seg, void * user_para); -void fuzzy_hash_merge_new(IVI_seg_t * seg, void * user_para); -void fuzzy_hash_length(IVI_seg_t * seg, void * user_para); -unsigned long long fuzzy_status(fuzzy_handle_t * handle, int type); -unsigned long long get_blocksize(unsigned long long orilen); - -char * b64 = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - +void write_uint_array(fuzzy_handle_inner_t * handle,unsigned int ** array, unsigned int *index,unsigned int *size,unsigned int value); /** * roll_state初始化 */ -static void roll_init(struct roll_state * self) +static inline void roll_init(struct roll_state_t * self) { - memset(self, 0, sizeof(struct roll_state)); + memset(self, 0, sizeof(struct roll_state_t)); } - /** * 计算roll_hash值,将外部数据读取到窗口中 */ -static void roll_hash(struct roll_state * self, unsigned char c) +static inline void roll_hash(struct roll_state_t * self, unsigned char c) { - self->h2 -= self->h1; - self->h2 += ROLLING_WINDOW * (unsigned int)c; + self->h2 -= self->h1; + self->h2 += ROLLING_WINDOW * (unsigned int)c; - self->h1 += (unsigned int)c; - self->h1 -= (unsigned int)self->window[self->n]; + self->h1 += (unsigned int)c; + self->h1 -= (unsigned int)self->window[self->n]; - self->window[self->n] = c; - self->n++; - if (self->n == ROLLING_WINDOW) - self->n = 0; - self->h3 <<= 5; - self->h3 ^= c; + self->window[self->n] = c; + self->n++; + if (self->n == ROLLING_WINDOW) + { + self->n = 0; + } + self->h3 <<= 5; + self->h3 ^= c; } - /** * 计算窗口里面的roll_hash值,每次roll_hash值满足一定条件,分片 */ -static unsigned int roll_sum(const struct roll_state * self) +static inline unsigned int roll_sum(const struct roll_state_t * self) { - return self->h1 + self->h2 + self->h3; - /* return self->h1 + self->h2; */ + return self->h1 + self->h2 + self->h3; } - /** * 计算分片的FNV值 */ -static unsigned int sum_hash(unsigned char c, unsigned int h) +static inline unsigned int sum_hash(unsigned char c, unsigned int h) { - return (h * HASH_PRIME) ^ c; + return (h * HASH_PRIME) ^ c; } - /** * 创建handle */ fuzzy_handle_t * fuzzy_create_handle(unsigned long long origin_len) { - fuzzy_handle_inner_t * handle = NULL; - unsigned long long tmp_blksize=get_blocksize(origin_len); - if(tmp_blksize==0) - { - return NULL; - } - handle = (fuzzy_handle_inner_t *)malloc(sizeof(fuzzy_handle_inner_t)); - handle->orilen = origin_len; - handle->ivi = IVI_create(); - handle->effective_length = 0; - handle->blocksize=tmp_blksize; - return (fuzzy_handle_t *)handle; + fuzzy_handle_inner_t * handle = NULL; + unsigned long long tmp_blksize = 0; + tmp_blksize = get_blocksize(origin_len); + + if(tmp_blksize==0) + { + return NULL; + } + handle = (fuzzy_handle_inner_t *)calloc(1,sizeof(fuzzy_handle_inner_t)); + handle->fuzzy_node_memory = 0; + handle->IVI_memory = 0; + handle->fuzzy_node_memory += sizeof(fuzzy_handle_inner_t); + handle->orilen = origin_len; + handle->ivi = IVI_create(); + handle->effective_length = 0; + handle->length_increase = 0; + handle->sim_tuned_rs_cnt = 0; + handle->blocksize=tmp_blksize; + handle->do_tune=0; + return (fuzzy_handle_t *)handle; } @@ -158,678 +107,596 @@ fuzzy_handle_t * fuzzy_create_handle(unsigned long long origin_len) */ void fuzzy_node_free(IVI_seg_t * seg, void * usr_para) { - //printf("free seg[%lu, %lu]\n", seg->left, seg->right); - fuzzy_node * temp = (fuzzy_node*)(seg->data); - if(temp->left_data != NULL) - { - free(temp->left_data); - temp->left_data = NULL; - } - if(temp->hash_result != NULL) - { - free(temp->hash_result); - temp->hash_result = NULL; - } - free(temp->right_status_r); - temp->right_status_r = NULL; - free(temp); - temp = NULL; - return; + fuzzy_handle_inner_t * _handle = (fuzzy_handle_inner_t *)usr_para; + sfh_seg_t * temp = (sfh_seg_t*)(seg->data); + _handle->fuzzy_node_memory-=destroy_sfh_seg(temp); + return; } - -/** - * 销毁handle - */ void fuzzy_destroy_handle(fuzzy_handle_t * handle) -{ - IVI_destroy(((fuzzy_handle_inner_t *)handle)->ivi, fuzzy_node_free, NULL); - free((fuzzy_handle_inner_t *)handle); - return; +{ + IVI_destroy(((fuzzy_handle_inner_t *)handle)->ivi, fuzzy_node_free, (void *)handle); + ((fuzzy_handle_inner_t *)handle)->fuzzy_node_memory -= sizeof(fuzzy_handle_inner_t); + free((fuzzy_handle_inner_t *)handle); + return; } - -/** - * 输入数据,并且计算数据的fuzzy_hash值 - */ unsigned int fuzzy_feed(fuzzy_handle_t * handle, const char * data, unsigned int size, unsigned long long offset) { + fuzzy_handle_inner_t * _handle=(fuzzy_handle_inner_t *)handle; if(data == NULL || size == 0) { return 0; } - fuzzy_node * node = (fuzzy_node *)calloc(sizeof(fuzzy_node), 1); - node->right_status_r = (struct roll_state *)calloc(sizeof (struct roll_state), 1); - roll_init(node->right_status_r); - node->slice_num = 0; - unsigned int length = segment_overlap(handle, node, size, offset, data); - if(offset == 0) + unsigned int length = segment_overlap(_handle, size, offset, data); + _handle->effective_length += length; + _handle->length_increase += length; + if(_handle->s_state_cnt>EXPECT_SIGNATURE_LEN&&_handle->do_tune==1) { - ((fuzzy_handle_inner_t *)handle)->effective_length += size - node->right_len; - return (size - node->right_len); + + + unsigned long long check_length = (_handle->effective_length/_handle->s_state_cnt)*EXPECT_SIGNATURE_LEN; + + if(_handle->length_increase > check_length) + { + + + IVI_traverse(_handle->ivi, sfh_tune_simulation, (void *)_handle); + if(_handle->sim_tuned_rs_cnt>EXPECT_SIGNATURE_LEN) + { + _handle->blocksize*=2; + IVI_traverse(_handle->ivi, sfh_tune_seg, (void *)_handle); + } + _handle->sim_tuned_rs_cnt = 0; + _handle->length_increase = 0; + } } - else - { - ((fuzzy_handle_inner_t *)handle)->effective_length += length; - } - return length; //返回已经计算的有效长度 +#if 0 + fuzzy_digest(handle,result, sizeof(result)); + printf("%llu %s\n",offset,result); +#endif + return length; } +void sfh_tune_simulation(IVI_seg_t * seg, void * user_para) +{ + sfh_seg_t * tmp = (sfh_seg_t *)(seg->data); + int i = 0; + fuzzy_handle_inner_t * _handle = (fuzzy_handle_inner_t *)user_para; + unsigned long long blocksize = _handle->blocksize * 2; + for(i = 0; i < tmp->r_cnt; i++) + { + if(tmp->r_array[i] % blocksize == blocksize -1) + { + _handle->sim_tuned_rs_cnt ++; + } + } +} + unsigned long long get_blocksize(unsigned long long orilen) { - double tmp = orilen/(64 * BLOCKSIZE_MIN); - double index = floor(log(tmp)/log(2)); - double tmp_t = pow(2, index); - unsigned long long blocksize = (unsigned long long)(tmp_t * BLOCKSIZE_MIN); - return blocksize; + double tmp = orilen/(64 * BLOCKSIZE_MIN); + double index = floor(log(tmp)/log(2)); + double tmp_t = pow(2, index); + unsigned long long blocksize = (unsigned long long)(tmp_t * BLOCKSIZE_MIN); + if(blocksize == 0) + { + blocksize = BLOCKSIZE_MIN; + } + return blocksize; +// return BLOCKSIZE_MIN; } +sfh_seg_t* create_sfh_seg(fuzzy_handle_inner_t * _handle) +{ + sfh_seg_t*p=calloc(sizeof(sfh_seg_t),1); + roll_init(&(p->r_state)); + p->s_size = INIT_SIZE; + p->r_size = INIT_SIZE; + p->r_array = (unsigned int*)malloc(sizeof(unsigned int)*(p->r_size)); + p->s_array = (struct zt_state_t*)malloc(sizeof(struct zt_state_t)*(p->s_size)); + zt_hash_initial(&(p->s_state)); + zt_hash_initial(&(p->ps)); + _handle->fuzzy_node_memory += sizeof(sfh_seg_t) + sizeof(unsigned int)*(p->r_size) + sizeof(struct zt_state_t)*(p->s_size); + return p; +} +//return freed memory size +int destroy_sfh_seg(sfh_seg_t*p) +{ + int ret_size=0; + //printf("before free p->s_array:\n"); + if(p->s_array != NULL) + { + //printf("p->s_array is not NULL\n"); + free(p->s_array); + p->s_array=NULL; + ret_size+=p->s_size*sizeof(struct zt_state_t); + } + //printf("after free p->s_array\n"); + if(p->r_array != NULL) + { + free(p->r_array); + p->r_array=NULL; + ret_size+=p->r_size*sizeof(unsigned int); + } + //printf("after free p->r_array\n"); + ret_size+=sizeof(sfh_seg_t); + //printf("before free p\n"); + free(p); + p=NULL; + //printf("after free p\n"); + return ret_size; +} /** * 判断数据是否与已经计算过的数据有覆盖 */ -unsigned int segment_overlap(fuzzy_handle_t * handle, fuzzy_node * fnode, unsigned int size, unsigned long long offset, const char * data) +unsigned int segment_overlap(fuzzy_handle_inner_t * _handle, unsigned int size, unsigned long long offset, const char * data) { IVI_seg_t ** overlap_segs = NULL; - IVI_seg_t * seg = IVI_seg_malloc(offset, offset + size -1, (void *)fnode); - int overlap_segnum = 0; + IVI_seg_t *new_seg=NULL,*target_seg=NULL; + sfh_seg_t* sfh_seg=NULL; + int overlap_segnum = 0,i=0,co_seg_num=0,ret=0; unsigned int effective_length = 0; - unsigned int total_length = 0; - unsigned long long blocksize = ((fuzzy_handle_inner_t *)handle)->blocksize; + unsigned long long calc_begin=offset; + unsigned long long calc_end=offset+size-1; + + //printf("size: %u\n",size); + //printf("before query\n"); + /*查询是否有覆盖,如果有覆盖,返回覆盖的segment的片数,如果没有覆盖,返回0*/ + if(offset>0) + { + overlap_segnum = IVI_query(_handle->ivi, offset-1, offset + size, &overlap_segs); + } + else + { + overlap_segnum = IVI_query(_handle->ivi, 0, offset + size, &overlap_segs); + } + IVI_seg_t * co_overlap_segs[overlap_segnum+1]; + assert(overlap_segnum>=0); - /*查询是否有覆盖,如果有覆盖,返回覆盖的segment的片数,如果没有覆盖,返回0*/ - overlap_segnum = IVI_query(((fuzzy_handle_inner_t *)handle)->ivi, offset, offset + size - 1, &overlap_segs); - - /*如果返回值为负数,说明输入的参数有问题,打印错误信息*/ - if(overlap_segnum < 0) - { - printf("fragment info error!\n"); - IVI_seg_free(seg, fuzzy_node_free, NULL); - return 0; - } - - /*如果返回值为0,说明没有覆盖的情况,直接插入就行*/ - if(overlap_segnum == 0) - { - IVI_insert(((fuzzy_handle_inner_t *)handle)->ivi,seg); - effective_length = fuzzy_hash_calculate(seg, data, offset, blocksize); - - total_length = seg->right - seg->left + 1; - return effective_length; - } - - /*如果返回值为覆盖的片数,则需要根据覆盖类型一一进行处理*/ - int flag = 0; - int i; - for(i = 0; i < overlap_segnum; i++) - { - switch(IVI_relative_position(seg, overlap_segs[i])) - { - case LEFT_OVERLAP: //左覆盖,把seg的右值改为overlap_seg的左值 - { - seg->right = overlap_segs[i]->left - 1; - break; - } - case CONTAIN: //包含关系,将左边那部分直接插入,然后改变seg的左值,并将data移动到指定的位置 - { - if(overlap_segs[i]->left >= 1 && overlap_segs[i]->left - 1 >= seg->left) - { - fuzzy_node * node = (fuzzy_node *)calloc(sizeof(fuzzy_node), 1); - memcpy(node, fnode, sizeof(fuzzy_node)); - node->right_status_r = (struct roll_state *)calloc(sizeof (struct roll_state), 1); - roll_init(node->right_status_r); - IVI_seg_t * thseg = IVI_seg_malloc(seg->left, overlap_segs[i]->left - 1, (void *)node); - IVI_insert(((fuzzy_handle_inner_t *)handle)->ivi,thseg); - effective_length += fuzzy_hash_calculate(thseg, data, offset, blocksize); - total_length += thseg->right - thseg->left + 1; - } - seg->left = overlap_segs[i]->right + 1; - data = data + ((seg->left) - offset); - offset = seg->left; - break; - } - case RIGHT_OVERLAP: //右覆盖,把seg的左值改为overlap_seg的右值 - { - seg->left = overlap_segs[i]->right + 1; - data = data + ((seg->left) - offset); - offset = seg->left; - break; - } - case CONTAINED: //如果被包含,就直接舍弃掉这片 - { - flag = 1; - //printf("contained! free seg\n"); - IVI_seg_free(seg, fuzzy_node_free, NULL); - free(overlap_segs); - break; - } - default: - break; - } - if(flag == 1) - { - return 0; - } - - } - - /*将余下的数据插入到区间链表里面,并且进行计算*/ - if(seg->left <= seg->right) - { - IVI_insert(((fuzzy_handle_inner_t *)handle)->ivi, seg); - effective_length += fuzzy_hash_calculate(seg, data, offset, blocksize); - total_length += seg->right - seg->left + 1; - //((fuzzy_handle_inner_t *)handle)->effective_length += effective_length; - } - else - { - IVI_seg_free(seg, fuzzy_node_free, NULL); - } - - free(overlap_segs); - return effective_length; + if(overlap_segnum==0||offsetleft) + { + sfh_seg=create_sfh_seg(_handle); + calc_begin=offset; + if(overlap_segnum == 0) + { + calc_end=offset+size-1; + } + else + { + calc_end=MIN(overlap_segs[0]->left-1,offset+size-1); + } + new_seg = IVI_seg_malloc(calc_begin, calc_end, (void *)sfh_seg); + _handle->s_state_cnt+=sfh_update_seg(_handle, sfh_seg,data+calc_begin-offset, calc_end-calc_begin+1, _handle->blocksize); + effective_length+=(calc_end-calc_begin+1); + co_overlap_segs[co_seg_num]=new_seg; + co_seg_num++; + } + for(i=0;iivi,overlap_segs[i]); + _handle->IVI_memory = IVI_mem_occupy(_handle->ivi); + assert(ret==0); + } + for(i=0;iright+1,calc_begin); + if(i+1left-1,offset+size-1); + } + else + { + calc_end=offset+size-1; + } + if(!after(calc_begin,calc_end)) + { + sfh_seg=(sfh_seg_t*)(co_overlap_segs[i]->data); + _handle->s_state_cnt+=sfh_update_seg(_handle,sfh_seg,data+calc_begin-offset, calc_end-calc_begin+1, _handle->blocksize); + effective_length+=(calc_end-calc_begin+1); + co_overlap_segs[i]->right+=calc_end-calc_begin+1; + calc_begin=calc_end+1; + } + } + target_seg=co_overlap_segs[0]; + for(i=0;idata)->r_index>0&&((sfh_seg_t*)co_overlap_segs[i]->data)->r_index>0) + { + memset(&result_p,0,sizeof(result_p)); + result_p.data=rp_buff; + result_p.size=sizeof(rp_buff); + sfh_output_state(target_seg,&result_p); + memset(&result_n,0,sizeof(result_n)); + result_n.data=rn_buff; + result_n.size=sizeof(rn_buff); + sfh_output_state(co_overlap_segs[i],&result_n); + printf("%s[%llu:%llu] %s[%llu:%llu]\n",rp_buff,target_seg->left, + target_seg->right, + rn_buff,co_overlap_segs[i]->left, + co_overlap_segs[i]->right); + } +#endif + _handle->s_state_cnt+=sfh_merge_seg(_handle,(sfh_seg_t*)target_seg->data, (sfh_seg_t*)co_overlap_segs[i]->data, _handle->blocksize); + target_seg->right=co_overlap_segs[i]->right; + IVI_seg_free(co_overlap_segs[i], fuzzy_node_free, (void *)_handle); + } + //IVI_seg_t * insert_seg=NULL; + //insert_seg = IVI_seg_malloc(target_seg->left, target_seg->right, target_seg->data); + ret=IVI_insert(_handle->ivi,target_seg); + _handle->IVI_memory = IVI_mem_occupy(_handle->ivi); + assert(ret==0); + free(overlap_segs); + return effective_length; } - -/** - * 处理前后分片,计算fuzzy_hash值 - */ -unsigned int fuzzy_hash_calculate(IVI_seg_t * seg, const char * data, unsigned long long offset, unsigned long long blocksize) +int cmp(const void * a, const void * b) { - IVI_seg_t * prev_seg; - IVI_seg_t * next_seg; - unsigned int effective_length = 0; - - prev_seg = IVI_prev_continuous_seg(seg); - next_seg = IVI_next_continuous_seg(seg); - //printf("seg->right = %lu, seg->left = %lu\n", seg->right, seg->left); - unsigned int size = seg->right - seg->left + 1; - fuzzy_node * node = (fuzzy_node *)(seg->data); - if(NULL == prev_seg) - { - //如果不存在前分片,直接初始化roll_state进行计算 - roll_init(node->right_status_r); - fuzzy_calculate_self(seg, data, offset, blocksize); - effective_length = size - node->left_len; - node->left_offset = offset + node->left_len; - } - else - { - //如果存在前分片,取出前分片的右边界的中间状态值进行计算 - - fuzzy_calculate_self_with_prev(prev_seg, seg, data, blocksize); - effective_length = size + ((fuzzy_node *)(prev_seg->data))->right_len; - node->left_offset = offset - ((fuzzy_node *)(prev_seg->data))->right_len; - } - - /* 如果有后分片,并且自己计算的结果里需要分片,则修改后面的分片 */ - if(next_seg != NULL) - { - //如果存在后分片,将本分片的右边界的中间状态值取出来和后分片的左边界的中间状态进行计算 - fuzzy_modify_next(seg, next_seg, blocksize); - - effective_length += ((fuzzy_node *)(next_seg->data))->left_len; - node->right_offset = offset + size + ((fuzzy_node *)(next_seg->data))->left_len; - - } - else - { - effective_length -= node->right_len; - node->right_offset = offset + (size - (node->right_len)); - } - return effective_length; + unsigned int tmp_a = *(unsigned int *)a; + unsigned int tmp_b = *(unsigned int *)b; + if(before(tmp_a, tmp_b)) + { + return -1; + } + else if(after(tmp_a, tmp_b)) + { + return 1; + } + else + { + return 0; + } } - - -void fuzzy_calculate_self(IVI_seg_t * seg, const char * data, unsigned long long offset, unsigned long long blocksize) +double get_rs_entropy(unsigned int * r_array, unsigned int r_index) { - fuzzy_node * node = (fuzzy_node *)(seg->data); - struct roll_state * rs = node->right_status_r; - unsigned long long size = seg->right - seg->left + 1; - unsigned int FNV_hash_value = HASH_INIT; + qsort(r_array, r_index, sizeof(unsigned int), cmp); + unsigned int current_r = r_array[0]; + unsigned int * tmp_r = r_array; + unsigned int count = 0; + double sum = 0; + int i = 0; + for(i = 0; i <= r_index; i++) + { + if(i == r_index || *tmp_r != current_r) + { + double p = (double)count/r_index; + //printf("count : %d\n",count); + //printf("r_index: %u\n",r_index); + //printf("p:%f\n",p); + if(p != 0) + { + sum += p * (log(p)/log(2)); + } + current_r = *tmp_r; + count = 0; + } + else + { + count++; + } + if(i < r_index) + { + tmp_r ++; + } + } + return (-sum); - char * FNV_hash = (char *)malloc(sizeof(char)*size); - unsigned long long fnv_index = 0, i=0, last_slice_index=0; - unsigned int roll_hash_value; - for(i = 0; i < size; i++) - { - roll_hash(rs, data[i]); - roll_hash_value = roll_sum(rs); - FNV_hash_value = sum_hash(data[i], FNV_hash_value); - if(i >= ROLLING_WINDOW - 1 && roll_hash_value % blocksize == blocksize - 1) - { - node->slice_num ++; - - if(node->slice_num == 1) - { - node->left_len = i + 1; - } - last_slice_index = i; - /* 保存FNV的值 */ - FNV_hash[fnv_index ++] = b64[FNV_hash_value % 64]; - //printf("data[%lu]=%c, FNV_hash = %c\n", i, data[i], b64[FNV_hash_value % 64]); - FNV_hash_value = HASH_INIT; - } - } - - /* 一片都没有找到 */ - if(node->slice_num == 0) - { - node->left_len = size; - node->right_len = 0; - } - else - { - node->right_len = size - last_slice_index - 1; - } - node->right_status_shash = FNV_hash_value; - - /* 复制结果到hash_result里 */ - node->hash_result = (char *)malloc(sizeof(char) * (fnv_index + 1)); - memcpy(node->hash_result, FNV_hash, fnv_index); - (node->hash_result)[fnv_index] = '\0'; - - node->left_data = (char *)malloc(sizeof(char) * (node->left_len)); - memcpy(node->left_data, data, node->left_len); - - free(FNV_hash); - return; } - -unsigned long long get_prev_continous_length(IVI_seg_t * seg) +/*void sfh_rs_entropy(IVI_seg_t * seg, void * user_para) { - unsigned long long length = 0; - IVI_seg_t * temp = seg; - while(temp != NULL) - { - length += temp->right - temp->left + 1; - if(length >= ROLLING_WINDOW) - return length; - temp = IVI_prev_continuous_seg(temp); - } - return length; + sfh_seg_t * tmp = (sfh_seg_t *)(seg->data); + int i = 0; + for(i = 0; i < tmp->r_cnt; i++) + { + write_uint_array((unsigned int**)(&(((struct entry *)user_para)->r_array)), &(((struct entry *)user_para)->r_index), + &(((struct entry *)user_para)->r_size), tmp->r_array[i]); + } +}*/ + + + +void sfh_tune_seg(IVI_seg_t * seg, void * user_para) +{ + int i = 0, j = 0; + sfh_seg_t * p = (sfh_seg_t *)(seg->data); + if(p->r_cnt== 0) + { + return; + } + + fuzzy_handle_inner_t * _handle = (fuzzy_handle_inner_t *)user_para; + unsigned long long blocksize = _handle->blocksize; + + struct zt_state_t tmp_zt; + int new_zt_cnt=0; + zt_hash_initial(&tmp_zt); + _handle->s_state_cnt -= p->s_cnt; + + for(j = 0; j < p->r_cnt; j++) + { + if(j == 0) + { + zt_hash_arymul(&tmp_zt, &(p->ps)); + } + else + { + zt_hash_arymul(&tmp_zt, &(p->s_array[j - 1])); + } +// if((p->r_array[j] &(blocksize-1)) == blocksize - 1) + if(p->r_array[j] % blocksize == blocksize - 1) + { + p->r_array[i]=p->r_array[j]; + i++; + if(i>1) + { + p->s_array[new_zt_cnt].val=tmp_zt.val; + new_zt_cnt++; + } + else + { + p->ps.val=tmp_zt.val; + } + zt_hash_initial(&tmp_zt); + } + } + zt_hash_arymul(&tmp_zt, &(p->s_state)); + if(i == 0) + { + zt_hash_initial(&(p->ps)); + } + p->s_state.val = tmp_zt.val; + p->s_cnt = new_zt_cnt; + p->r_cnt = i; + _handle->s_state_cnt += p->s_cnt; + assert(p->r_cnt>=p->s_cnt); + + //printf("after state_cnt:%d,block:%llu\n",_handle->s_state_cnt,_handle->blocksize); } -/** - * 处理前段的保留数据 - */ -void fuzzy_calculate_self_with_prev(IVI_seg_t * prev_seg, IVI_seg_t * seg, const char * data, unsigned long long blocksize) +void write_uint_array(fuzzy_handle_inner_t *_handle,unsigned int ** array,unsigned int *index, unsigned int *size,unsigned int value) { - fuzzy_node * prev_node = (fuzzy_node *)(prev_seg->data); - fuzzy_node * node = (fuzzy_node *)(seg->data); - - /* 使用前段的roll state */ - memcpy(node->right_status_r, prev_node->right_status_r, sizeof(struct roll_state)); - struct roll_state * rs = node->right_status_r; - unsigned long long size = seg->right - seg->left + 1; - unsigned int FNV_hash_value = prev_node->right_status_shash; - - - char * FNV_hash = (char *)malloc(sizeof(char)*size); - unsigned long long fnv_index = 0, i=0, last_slice_index=0; - unsigned int roll_hash_value; - unsigned long long prev_len = get_prev_continous_length(prev_seg); - - for(i = 0; i < size; i++) - { - roll_hash(rs, data[i]); - roll_hash_value = roll_sum(rs); - FNV_hash_value = sum_hash(data[i], FNV_hash_value); - if(i + prev_len >= ROLLING_WINDOW \ - && roll_hash_value % blocksize == blocksize - 1) - { - node->slice_num ++; - if(node->slice_num == 1) - { - node->left_len = i + 1; - } - - last_slice_index = i; - /* 保存FNV的值 */ - FNV_hash[fnv_index ++] = b64[FNV_hash_value % 64]; - //printf("data[%lu]=%c, FNV_hash = %c\n", i, data[i], b64[FNV_hash_value % 64]); - FNV_hash_value = HASH_INIT; - } - } - - /* 一片都没有找到 */ - if(node->slice_num == 0) - { - node->left_len = size; - node->right_len = 0; - } - else - { - node->right_len = size - last_slice_index - 1; - } - node->right_status_shash = FNV_hash_value; - - /* 复制结果到hash_result里 */ - node->hash_result = (char *)malloc(sizeof(char) * (fnv_index + 1)); - memcpy(node->hash_result, FNV_hash, fnv_index); - (node->hash_result)[fnv_index] = '\0'; - - node->left_data = (char *)malloc(sizeof(char) * (node->left_len)); - memcpy(node->left_data, data, node->left_len); - - free(FNV_hash); + if(*index==*size) + { + (*size)*=2; + *array=(unsigned int*)realloc(*array,sizeof(unsigned int)*(*size)); + _handle->fuzzy_node_memory += (*size)/2; + } + (*array)[*index]=value; + (*index)++; + return; } - - -void fuzzy_modify_self_with_prev(IVI_seg_t * prev_seg, IVI_seg_t * seg, char * data, unsigned long long blocksize) +int sfh_update_seg(fuzzy_handle_inner_t * _handle, sfh_seg_t * p, const char * data, unsigned long data_size,unsigned long long blocksize) { - fuzzy_node * prev_node = (fuzzy_node *)(prev_seg->data); - fuzzy_node * node = (fuzzy_node *)(seg->data); - - /* 使用前段的roll state */ - memcpy(node->right_status_r, prev_node->right_status_r, sizeof(struct roll_state)); - struct roll_state * rs = node->right_status_r; - unsigned long long size = seg->right - seg->left + 1; - unsigned int FNV_hash_value = prev_node->right_status_shash; - - - char * FNV_hash = (char *)malloc(sizeof(char)*size); - unsigned long long fnv_index = 0, i=0, last_slice_index=0; - unsigned int roll_hash_value; - unsigned long long prev_len = get_prev_continous_length(prev_seg); - for(i = 0; i < size; i++) - { - roll_hash(rs, data[i]); - roll_hash_value = roll_sum(rs); - FNV_hash_value = sum_hash(data[i], FNV_hash_value); - if(i + prev_len >= ROLLING_WINDOW \ - && roll_hash_value % blocksize == blocksize- 1) - { - node->slice_num ++; - if(node->slice_num == 1) - { - node->left_len = i + 1; - } - - last_slice_index = i; - /* 保存FNV的值 */ - FNV_hash[fnv_index ++] = b64[FNV_hash_value % 64]; - //printf("data[%lu]=%c, FNV_hash = %c\n", i, data[i], b64[FNV_hash_value % 64]); - FNV_hash_value = HASH_INIT; - } - } - - /* 一片都没有找到 */ - if(node->slice_num == 0) - { - node->left_len = size; - node->right_len = 0; - } - else - { - node->right_len = size - last_slice_index - 1; - } - node->right_status_shash = FNV_hash_value; - - /* 复制结果到hash_result里 */ - free(node->hash_result); - node->hash_result = (char *)malloc(sizeof(char) * (fnv_index + 1)); - memcpy(node->hash_result, FNV_hash, fnv_index); - (node->hash_result)[fnv_index] = '\0'; - - //printf("old node->left_data = %s\n", node->left_data); - free(node->left_data); - node->left_data = (char *)malloc(sizeof(char) * (node->left_len)); - memcpy(node->left_data, data, node->left_len); - //printf("new node->left_data = %s\n", node->left_data); - free(FNV_hash); -} - - - -/** - * 处理后段的保留数据 - */ -void fuzzy_modify_next(IVI_seg_t * seg, IVI_seg_t * next_seg, unsigned long long blocksize) -{ - IVI_seg_t * tmp_curr_seg = seg; - IVI_seg_t * tmp_next_seg = next_seg; - while(tmp_next_seg != NULL) - { - fuzzy_node * tmp_next_node = (fuzzy_node *)(tmp_next_seg->data); - if(tmp_next_node->slice_num != 0) - { - break; - } - - /* 下一段没有分片, 则重新计算 */ + unsigned long i = 0; + unsigned int roll_hash_value = 0; + int state_inc_cnt=0; + if(p->msize < ROLLING_WINDOW - 1) + { + for(i = 0; i < ROLLING_WINDOW - p->msize && i < data_size; i++) + { + p->mbuf[p->msize + i] = data[i]; + roll_hash(&(p->r_state), data[i]); + } + p->msize += i; + } + for(; i < data_size; i++) + { + roll_hash(&(p->r_state), data[i]); + roll_hash_value = roll_sum(&(p->r_state)); - char * data = (char *)malloc(sizeof(char) * (tmp_next_node->left_len)); - memcpy(data, tmp_next_node->left_data, tmp_next_node->left_len); - fuzzy_modify_self_with_prev(tmp_curr_seg, tmp_next_seg, data, blocksize); - free(data); - - tmp_curr_seg = tmp_next_seg; - tmp_next_seg = IVI_next_continuous_seg(tmp_next_seg); - } - - unsigned long long prev_len = get_prev_continous_length(tmp_curr_seg); - /* tmp_next_seg中是有分片的 */ - if(tmp_next_seg != NULL) - { - fuzzy_node * tmp_curr_node = (fuzzy_node *)(tmp_curr_seg->data); - fuzzy_node * tmp_next_node = (fuzzy_node *)(tmp_next_seg->data); - - unsigned long long size = tmp_next_node->left_len; - - char * FNV_hash = (char *)malloc(sizeof(char)*size); - unsigned long long fnv_index = 0, i; - unsigned int roll_hash_value; - - struct roll_state rs; - memcpy(&rs, tmp_curr_node->right_status_r, sizeof(struct roll_state)); - char * data = tmp_next_node->left_data; - unsigned int FNV_hash_value = tmp_curr_node->right_status_shash; - for(i = 0; i < size; i++) - { - roll_hash(&rs, data[i]); - roll_hash_value = roll_sum(&rs); - FNV_hash_value = sum_hash(data[i], FNV_hash_value); - - if((i + prev_len >= ROLLING_WINDOW) \ - && roll_hash_value % blocksize == blocksize - 1) - { - tmp_next_node->slice_num ++; - FNV_hash[fnv_index ++] = b64[FNV_hash_value % 64]; - //printf("data[%lu]=%c, FNV_hash = %c\n", i, data[i], b64[FNV_hash_value % 64]); - FNV_hash_value = HASH_INIT; - - if(fnv_index == 1) - { - tmp_next_node->left_len = i + 1; - } - } - } - - tmp_next_node->slice_num --; - - - /* 复制结果到hash_result里 */ - unsigned long long old_len = strlen(tmp_next_node->hash_result); - if(old_len == 1) - { - free(tmp_next_node->hash_result); - tmp_next_node->hash_result = (char *)malloc(sizeof(char) * (fnv_index + 1)); - memcpy(tmp_next_node->hash_result, FNV_hash, fnv_index); - (tmp_next_node->hash_result)[fnv_index] = '\0'; - } - else - { - unsigned long long new_len = old_len - 1 + fnv_index; - char tmp[old_len - 1]; - char * old_hash = (tmp_next_node->hash_result) + 1; - memcpy(tmp, old_hash, old_len - 1); - free(tmp_next_node->hash_result); - tmp_next_node->hash_result = (char *)malloc(sizeof(char) * (new_len + 1)); - memset(tmp_next_node->hash_result, '\0', (new_len + 1)); - memcpy(tmp_next_node->hash_result, FNV_hash, fnv_index); - strncat(tmp_next_node->hash_result, tmp, old_len - 1); - (tmp_next_node->hash_result)[new_len] = '\0'; - } - free(FNV_hash); - } - return; + zt_hash(&(p->s_state),data[i]); +// if((roll_hash_value & (blocksize-1)) == blocksize - 1) + if((roll_hash_value % (blocksize)) == blocksize - 1) + { + p->slice_num ++; + if(p->r_cnt==0) + { + p->ps.val=p->s_state.val; + } + else + { +#ifdef DEBUG_PRINT + printf("p->s_cnt:%u\n",p->s_cnt); + printf("p->s_size:%u\n",p->s_size); +#endif + write_uint_array(_handle,(unsigned int**)(&(p->s_array)), &(p->s_cnt),&(p->s_size),p->s_state.val); + state_inc_cnt++; + } +#ifdef DEBUG_PRINT + printf("p->r_cnt:%u\n",p->s_cnt); + printf("p->r_size:%u\n",p->s_size); +#endif + write_uint_array(_handle,&(p->r_array),&(p->r_cnt),&(p->r_size),roll_hash_value); + zt_hash_initial(&(p->s_state)); + } + } + assert(p->r_cnt>=p->s_cnt); + p->right_offset+=data_size; + return state_inc_cnt; } +int sfh_merge_seg(fuzzy_handle_inner_t * _handle, sfh_seg_t * p, sfh_seg_t * n,unsigned long long blocksize) +{ + unsigned int roll_hash_value = 0; + int i = 0,state_inc_cnt=0; + struct roll_state_t * rs = &(p->r_state); + for(i = 0; i < n->msize; i++) + { + roll_hash(rs, n->mbuf[i]); + roll_hash_value = roll_sum(rs); + zt_hash(&(p->s_state), n->mbuf[i]); +// if((roll_hash_value & (blocksize-1)) == blocksize - 1) + if(roll_hash_value % blocksize == blocksize - 1) + { + //printf("roll_value : %u\n",roll_hash_value); + p->slice_num ++; +// unsigned int * tmp = (unsigned int *)(p->s_array); + if(p->r_cnt == 0) + { + p->ps.val = p->s_state.val; + } + else + { + write_uint_array(_handle,(unsigned int **)(&(p->s_array)), &(p->s_cnt), &(p->s_size), p->s_state.val); + state_inc_cnt++; + } + write_uint_array(_handle,&(p->r_array),&(p->r_cnt), &(p->r_size), roll_hash_value); + zt_hash_initial(&(p->s_state)); + } + } + if(n->r_cnt==0) + { + zt_hash_arymul(&(p->s_state),&(n->ps)); + zt_hash_arymul(&(p->s_state), &(n->s_state)); + } + else + { + if(p->r_cnt==0) + { + zt_hash_arymul(&(p->s_state),&(n->ps)); + p->ps.val=p->s_state.val; + } + else + { + zt_hash_arymul(&(p->s_state), &(n->ps)); + write_uint_array(_handle,(unsigned int **)(&(p->s_array)), &(p->s_cnt), &(p->s_size), p->s_state.val); + state_inc_cnt++; + } + p->s_state.val=n->s_state.val; + } + for(i=0;ir_cnt;i++) + { + write_uint_array(_handle,&(p->r_array),&(p->r_cnt), &(p->r_size), n->r_array[i]); + } + for(i=0;is_cnt;i++) + { + write_uint_array(_handle, (unsigned int **)(&(p->s_array)), &(p->s_cnt), &(p->s_size), n->s_array[i].val); + } + memcpy(&(p->r_state),&(n->r_state),sizeof(p->r_state)); + assert(p->r_cnt>=p->s_cnt); + + return state_inc_cnt; +} /** * 取出区间链表里面的hash_result值,并进行拼接,形成最后的result输出,并且满足abc[1:100]def[200:300]这种格式 */ int fuzzy_digest(fuzzy_handle_t * handle, char * result, unsigned int size) { - final_result * temp = (final_result *)malloc(sizeof(final_result)); - temp->head = result; - temp->size = size; - temp->offset = 0; - temp->first_FNV_offset = 0; - temp->last_FNV_offset = 0; - //final_result * temp = (final_result *)malloc(sizeof(final_result)); - //temp->offset = 0; - IVI_traverse(((fuzzy_handle_inner_t *)handle)->ivi, fuzzy_hash_merge_new, (void *) temp); - result[size - 1] = '\0'; - //memcpy(result, temp->result, size); - free(temp); - return 0; + final_result * temp = (final_result *)malloc(sizeof(final_result)); + fuzzy_handle_inner_t* _handle=(fuzzy_handle_inner_t *)handle; + temp->data = result; + temp->size = size-1; + temp->offset = 0; + temp->first_ZTH_offset = 0; + temp->last_ZTH_offset = 0; + temp->offset+=snprintf(temp->data,temp->size,"%llu:",_handle->blocksize); + IVI_traverse(_handle->ivi, sfh_output_state, (void *) temp); + result[temp->offset] = '\0'; + free(temp); + temp = NULL; + return 0; } - -void fuzzy_hash_merge_new(IVI_seg_t * seg, void * user_para) +void sfh_output_state(IVI_seg_t * seg, void * user_para) { - IVI_seg_t * prev_seg; - IVI_seg_t * next_seg; - prev_seg = IVI_prev_continuous_seg(seg); - next_seg = IVI_next_continuous_seg(seg); - char buffer[MAXSIZE]; - final_result * tmp = (final_result *)user_para; - fuzzy_node * node = (fuzzy_node *)(seg->data); - if(node->slice_num != 0) - { - tmp->last_FNV_offset = seg->right - node->right_len; - } - - if(prev_seg == NULL && next_seg == NULL) //如果前分片和后分片都为空,则不用拼接 - { - tmp->first_FNV_offset = seg->left; - tmp->last_FNV_offset = seg->right - node->right_len; - sprintf(buffer, "%s[%llu:%llu]", node->hash_result, tmp->first_FNV_offset, seg->right); - } - if(prev_seg == NULL && next_seg != NULL) //如果前分片为空,后分片不为空,更新左值,将FNV值链接上去 - { - tmp->first_FNV_offset = seg->left; - - sprintf(buffer, "%s", node->hash_result); - } - if(prev_seg != NULL && next_seg == NULL) //如果前分片不为空,后分片为空,更新右值输出偏移 - { - - sprintf(buffer, "%s[%llu:%llu]", node->hash_result, tmp->first_FNV_offset, seg->right); - } - if(prev_seg != NULL && next_seg != NULL) //如果前分片不为空,后分片不为空,将链接FNV值上去 - { - sprintf(buffer, "%s", node->hash_result); - } - - unsigned int inner_size = strlen(buffer); - tmp->offset += inner_size; - if(tmp->offset <= tmp->size) - { - memcpy(tmp->head, buffer, inner_size); - tmp->head += inner_size; - } - else - { - unsigned int length = (tmp->size - (tmp->offset - inner_size)); - if(length != 0) - { - memcpy(tmp->head, buffer, length); - } - tmp->offset = tmp->size; - tmp->head += length; - } - return; + char buffer[2000]; + final_result * result = (final_result *)user_para; + sfh_seg_t * node = (sfh_seg_t *)(seg->data); + char hash_result[node->r_cnt + 1]; + hash_result[node->r_cnt] = '\0'; + int i = 0, j = 0, to_copy_len=0,this_len=0; + if(node->s_cnt==0&&!(seg->left==0&&node->s_cnt>0)) + { + return; + } + memset(hash_result,0,sizeof(hash_result)); + if(seg->left == 0) + { + hash_result[j] = b64[zt_hash_code(&(node->ps)) & 0x3F]; + j++; + } + for(i = 0; i < node->s_cnt; i++,j++) + { + hash_result[j] = b64[(node->s_array[i].val) & 0x3F]; + } + hash_result[j+1]='\0'; + if(0!=memcmp(&(node->s_state),ZT_INIT_VAL,sizeof(ZT_INIT_VAL))) + { + result->last_char=b64[zt_hash_code(&(node->s_state)) & 0x3F]; + } + else + { + result->last_char='\0'; + } + hash_result[j+1] = '\0'; + this_len=snprintf(buffer,sizeof(buffer), "[%llu:%llu]",seg->left, seg->right); + this_len+=j; +// this_len++; + to_copy_len=MIN(this_len,result->size-result->offset); + memcpy(result->data+result->offset,hash_result,j); + result->offset+=j; + memcpy(result->data+result->offset,buffer,to_copy_len-j); + result->offset += to_copy_len-j; + return; } - /** * 计算fuzzy_hash的各种长度 */ unsigned long long fuzzy_status(fuzzy_handle_t * handle, int type) { unsigned long long length; - final_length tmp_length; fuzzy_handle_inner_t * _handle = (fuzzy_handle_inner_t *)(handle); + final_length tmp_length; + char buffer[64]; switch(type) { - case TOTAL_LENGTH: //已经计算过hash值的全部长度 - length = IVI_seg_length(_handle->ivi); - break; + case TOTAL_LENGTH: //已经计算过hash值的全部长度 + length = IVI_seg_length(_handle->ivi); + break; case EFFECTIVE_LENGTH: //包含在计算hash值里面的有效长度 - length = _handle->effective_length; - break; + length = _handle->effective_length; + break; case HASH_LENGTH: //最后输出哈希结果的长度 - tmp_length.hash_length = 0; - tmp_length.first_FNV_offset = 0; - tmp_length.last_FNV_offset = 0; - IVI_traverse(_handle->ivi, fuzzy_hash_length, (void *)&tmp_length); - length = tmp_length.hash_length + 1; - break; + tmp_length.hash_length = 0; + tmp_length.first_ZTH_offset = 0; + tmp_length.last_ZTH_offset = 0; + tmp_length.hash_length+=snprintf(buffer,sizeof(buffer),"%llu:",_handle->blocksize); + IVI_traverse(_handle->ivi, fuzzy_hash_length, (void *)&tmp_length); + length = tmp_length.hash_length + 1; + break; + case MEMORY_OCCUPY: + length = _handle->fuzzy_node_memory + _handle->IVI_memory; + break; default: - return 0; + return 0; } return length; } - void fuzzy_hash_length(IVI_seg_t * seg, void * user_para) { + char buffer[100]; + final_length * tmp = (final_length *)user_para; + sfh_seg_t * node = (sfh_seg_t *)(seg->data); - IVI_seg_t * prev_seg; - IVI_seg_t * next_seg; - prev_seg = IVI_prev_continuous_seg(seg); - next_seg = IVI_next_continuous_seg(seg); - char buffer[MAXSIZE]; - final_length * tmp = (final_length *)user_para; - fuzzy_node * node = (fuzzy_node *)(seg->data); - if(node->slice_num != 0) - { - //printf("node->slice_num != 0\n"); - tmp->last_FNV_offset = seg->right - node->right_len; - //printf("%lu\n", tmp->last_FNV_offset); - } - - if(prev_seg == NULL && next_seg == NULL) //如果前分片和后分片都为空,则不用拼接 - { - tmp->first_FNV_offset = seg->left; - tmp->last_FNV_offset = seg->right - node->right_len; - sprintf(buffer, "%s[%llu:%llu]", node->hash_result, tmp->first_FNV_offset, seg->right); - } - if(prev_seg == NULL && next_seg != NULL) //如果前分片为空,后分片不为空,更新左值,将FNV值链接上去 - { - tmp->first_FNV_offset = seg->left; - - sprintf(buffer, "%s", node->hash_result); - } - if(prev_seg != NULL && next_seg == NULL) //如果前分片不为空,后分片为空,更新右值输出偏移 - { - - sprintf(buffer, "%s[%llu:%llu]", node->hash_result, tmp->first_FNV_offset, seg->right); - } - if(prev_seg != NULL && next_seg != NULL) //如果前分片不为空,后分片不为空,将链接FNV值上去 - { - sprintf(buffer, "%s", node->hash_result); - } - tmp->hash_length += strlen(buffer); - return; + sprintf(buffer, "[%llu:%llu]", seg->left, seg->right); + + tmp->hash_length += node->r_cnt*sizeof(char) + strlen(buffer); + return; } diff --git a/src/inc_internal/mesa_fuzzy.h b/src/entry/mesa_fuzzy.h similarity index 100% rename from src/inc_internal/mesa_fuzzy.h rename to src/entry/mesa_fuzzy.h diff --git a/src/entry/rbtree.c b/src/entry/rbtree.c new file mode 100644 index 0000000..4c68ad1 --- /dev/null +++ b/src/entry/rbtree.c @@ -0,0 +1,548 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + (C) 2002 David Woodhouse + (C) 2012 Michel Lespinasse + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/lib/rbtree.c +*/ + +#include "rbtree.h" +#include "rbtree_augmented.h" +/* + * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree + * + * 1) A node is either red or black + * 2) The root is black + * 3) All leaves (NULL) are black + * 4) Both children of every red node are black + * 5) Every simple path from root to leaves contains the same number + * of black nodes. + * + * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two + * consecutive red nodes in a path and every red node is therefore followed by + * a black. So if B is the number of black nodes on every simple path (as per + * 5), then the longest possible path due to 4 is 2B. + * + * We shall indicate color with case, where black nodes are uppercase and red + * nodes will be lowercase. Unknown color nodes shall be drawn as red within + * parentheses and have some accompanying text comment. + */ + +static inline void rb_set_black(struct rb_node *rb) +{ + rb->__rb_parent_color |= RB_BLACK; +} + +static inline struct rb_node *rb_red_parent(struct rb_node *red) +{ + return (struct rb_node *)red->__rb_parent_color; +} + +/* + * Helper function for rotations: + * - old's parent and color get assigned to new + * - old gets assigned new as a parent and 'color' as a color. + */ +static inline void +__rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, + struct rb_root *root, int color) +{ + struct rb_node *parent = rb_parent(old); + new->__rb_parent_color = old->__rb_parent_color; + rb_set_parent_color(old, new, color); + __rb_change_child(old, new, parent, root); +} + +static __always_inline void +__rb_insert(struct rb_node *node, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; + + while (1) { + /* + * Loop invariant: node is red + * + * If there is a black parent, we are done. + * Otherwise, take some corrective action as we don't + * want a red root or two consecutive red nodes. + */ + if (!parent) { + rb_set_parent_color(node, NULL, RB_BLACK); + break; + } else if (rb_is_black(parent)) + break; + + gparent = rb_red_parent(parent); + + tmp = gparent->rb_right; + if (parent != tmp) { /* parent == gparent->rb_left */ + if (tmp && rb_is_red(tmp)) { + /* + * Case 1 - color flips + * + * G g + * / \ / \ + * p u --> P U + * / / + * n n + * + * However, since g's parent might be red, and + * 4) does not allow this, we need to recurse + * at g. + */ + rb_set_parent_color(tmp, gparent, RB_BLACK); + rb_set_parent_color(parent, gparent, RB_BLACK); + node = gparent; + parent = rb_parent(node); + rb_set_parent_color(node, parent, RB_RED); + continue; + } + + tmp = parent->rb_right; + if (node == tmp) { + /* + * Case 2 - left rotate at parent + * + * G G + * / \ / \ + * p U --> n U + * \ / + * n p + * + * This still leaves us in violation of 4), the + * continuation into Case 3 will fix that. + */ + parent->rb_right = tmp = node->rb_left; + node->rb_left = parent; + if (tmp) + rb_set_parent_color(tmp, parent, + RB_BLACK); + rb_set_parent_color(parent, node, RB_RED); + augment_rotate(parent, node); + parent = node; + tmp = node->rb_right; + } + + /* + * Case 3 - right rotate at gparent + * + * G P + * / \ / \ + * p U --> n g + * / \ + * n U + */ + gparent->rb_left = tmp; /* == parent->rb_right */ + parent->rb_right = gparent; + if (tmp) + rb_set_parent_color(tmp, gparent, RB_BLACK); + __rb_rotate_set_parents(gparent, parent, root, RB_RED); + augment_rotate(gparent, parent); + break; + } else { + tmp = gparent->rb_left; + if (tmp && rb_is_red(tmp)) { + /* Case 1 - color flips */ + rb_set_parent_color(tmp, gparent, RB_BLACK); + rb_set_parent_color(parent, gparent, RB_BLACK); + node = gparent; + parent = rb_parent(node); + rb_set_parent_color(node, parent, RB_RED); + continue; + } + + tmp = parent->rb_left; + if (node == tmp) { + /* Case 2 - right rotate at parent */ + parent->rb_left = tmp = node->rb_right; + node->rb_right = parent; + if (tmp) + rb_set_parent_color(tmp, parent, + RB_BLACK); + rb_set_parent_color(parent, node, RB_RED); + augment_rotate(parent, node); + parent = node; + tmp = node->rb_left; + } + + /* Case 3 - left rotate at gparent */ + gparent->rb_right = tmp; /* == parent->rb_left */ + parent->rb_left = gparent; + if (tmp) + rb_set_parent_color(tmp, gparent, RB_BLACK); + __rb_rotate_set_parents(gparent, parent, root, RB_RED); + augment_rotate(gparent, parent); + break; + } + } +} + +/* + * Inline version for rb_erase() use - we want to be able to inline + * and eliminate the dummy_rotate callback there + */ +static __always_inline void +____rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; + + while (1) { + /* + * Loop invariants: + * - node is black (or NULL on first iteration) + * - node is not the root (parent is not NULL) + * - All leaf paths going through parent and node have a + * black node count that is 1 lower than other leaf paths. + */ + sibling = parent->rb_right; + if (node != sibling) { /* node == parent->rb_left */ + if (rb_is_red(sibling)) { + /* + * Case 1 - left rotate at parent + * + * P S + * / \ / \ + * N s --> p Sr + * / \ / \ + * Sl Sr N Sl + */ + parent->rb_right = tmp1 = sibling->rb_left; + sibling->rb_left = parent; + rb_set_parent_color(tmp1, parent, RB_BLACK); + __rb_rotate_set_parents(parent, sibling, root, + RB_RED); + augment_rotate(parent, sibling); + sibling = tmp1; + } + tmp1 = sibling->rb_right; + if (!tmp1 || rb_is_black(tmp1)) { + tmp2 = sibling->rb_left; + if (!tmp2 || rb_is_black(tmp2)) { + /* + * Case 2 - sibling color flip + * (p could be either color here) + * + * (p) (p) + * / \ / \ + * N S --> N s + * / \ / \ + * Sl Sr Sl Sr + * + * This leaves us violating 5) which + * can be fixed by flipping p to black + * if it was red, or by recursing at p. + * p is red when coming from Case 1. + */ + rb_set_parent_color(sibling, parent, + RB_RED); + if (rb_is_red(parent)) + rb_set_black(parent); + else { + node = parent; + parent = rb_parent(node); + if (parent) + continue; + } + break; + } + /* + * Case 3 - right rotate at sibling + * (p could be either color here) + * + * (p) (p) + * / \ / \ + * N S --> N Sl + * / \ \ + * sl Sr s + * \ + * Sr + */ + sibling->rb_left = tmp1 = tmp2->rb_right; + tmp2->rb_right = sibling; + parent->rb_right = tmp2; + if (tmp1) + rb_set_parent_color(tmp1, sibling, + RB_BLACK); + augment_rotate(sibling, tmp2); + tmp1 = sibling; + sibling = tmp2; + } + /* + * Case 4 - left rotate at parent + color flips + * (p and sl could be either color here. + * After rotation, p becomes black, s acquires + * p's color, and sl keeps its color) + * + * (p) (s) + * / \ / \ + * N S --> P Sr + * / \ / \ + * (sl) sr N (sl) + */ + parent->rb_right = tmp2 = sibling->rb_left; + sibling->rb_left = parent; + rb_set_parent_color(tmp1, sibling, RB_BLACK); + if (tmp2) + rb_set_parent(tmp2, parent); + __rb_rotate_set_parents(parent, sibling, root, + RB_BLACK); + augment_rotate(parent, sibling); + break; + } else { + sibling = parent->rb_left; + if (rb_is_red(sibling)) { + /* Case 1 - right rotate at parent */ + parent->rb_left = tmp1 = sibling->rb_right; + sibling->rb_right = parent; + rb_set_parent_color(tmp1, parent, RB_BLACK); + __rb_rotate_set_parents(parent, sibling, root, + RB_RED); + augment_rotate(parent, sibling); + sibling = tmp1; + } + tmp1 = sibling->rb_left; + if (!tmp1 || rb_is_black(tmp1)) { + tmp2 = sibling->rb_right; + if (!tmp2 || rb_is_black(tmp2)) { + /* Case 2 - sibling color flip */ + rb_set_parent_color(sibling, parent, + RB_RED); + if (rb_is_red(parent)) + rb_set_black(parent); + else { + node = parent; + parent = rb_parent(node); + if (parent) + continue; + } + break; + } + /* Case 3 - right rotate at sibling */ + sibling->rb_right = tmp1 = tmp2->rb_left; + tmp2->rb_left = sibling; + parent->rb_left = tmp2; + if (tmp1) + rb_set_parent_color(tmp1, sibling, + RB_BLACK); + augment_rotate(sibling, tmp2); + tmp1 = sibling; + sibling = tmp2; + } + /* Case 4 - left rotate at parent + color flips */ + parent->rb_left = tmp2 = sibling->rb_right; + sibling->rb_right = parent; + rb_set_parent_color(tmp1, sibling, RB_BLACK); + if (tmp2) + rb_set_parent(tmp2, parent); + __rb_rotate_set_parents(parent, sibling, root, + RB_BLACK); + augment_rotate(parent, sibling); + break; + } + } +} + +/* Non-inline version for rb_erase_augmented() use */ +void __rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + ____rb_erase_color(parent, root, augment_rotate); +} + +/* + * Non-augmented rbtree manipulation functions. + * + * We use dummy augmented callbacks here, and have the compiler optimize them + * out of the rb_insert_color() and rb_erase() function definitions. + */ + +static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} +static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} +static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} + +static const struct rb_augment_callbacks dummy_callbacks = { + dummy_propagate, dummy_copy, dummy_rotate +}; + +void rb_insert_color(struct rb_node *node, struct rb_root *root) +{ + __rb_insert(node, root, dummy_rotate); +} + +void rb_erase(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *rebalance; + rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); + if (rebalance) + ____rb_erase_color(rebalance, root, dummy_rotate); +} + +/* + * Augmented rbtree manipulation functions. + * + * This instantiates the same __always_inline functions as in the non-augmented + * case, but this time with user-defined callbacks. + */ + +void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) +{ + __rb_insert(node, root, augment_rotate); +} + +/* + * This function returns the first node (in sort order) of the tree. + */ +struct rb_node *rb_first(const struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_left) + n = n->rb_left; + return n; +} + +struct rb_node *rb_last(const struct rb_root *root) +{ + struct rb_node *n; + + n = root->rb_node; + if (!n) + return NULL; + while (n->rb_right) + n = n->rb_right; + return n; +} + +struct rb_node *rb_next(const struct rb_node *node) +{ + struct rb_node *parent; + + if (RB_EMPTY_NODE(node)) + return NULL; + + /* + * If we have a right-hand child, go down and then left as far + * as we can. + */ + if (node->rb_right) { + node = node->rb_right; + while (node->rb_left) + node=node->rb_left; + return (struct rb_node *)node; + } + + /* + * No right-hand children. Everything down and left is smaller than us, + * so any 'next' node must be in the general direction of our parent. + * Go up the tree; any time the ancestor is a right-hand child of its + * parent, keep going up. First time it's a left-hand child of its + * parent, said parent is our 'next' node. + */ + while ((parent = rb_parent(node)) && node == parent->rb_right) + node = parent; + + return parent; +} + +struct rb_node *rb_prev(const struct rb_node *node) +{ + struct rb_node *parent; + + if (RB_EMPTY_NODE(node)) + return NULL; + + /* + * If we have a left-hand child, go down and then right as far + * as we can. + */ + if (node->rb_left) { + node = node->rb_left; + while (node->rb_right) + node=node->rb_right; + return (struct rb_node *)node; + } + + /* + * No left-hand children. Go up till we find an ancestor which + * is a right-hand child of its parent. + */ + while ((parent = rb_parent(node)) && node == parent->rb_left) + node = parent; + + return parent; +} + +void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root) +{ + struct rb_node *parent = rb_parent(victim); + + /* Set the surrounding nodes to point to the replacement */ + __rb_change_child(victim, new, parent, root); + if (victim->rb_left) + rb_set_parent(victim->rb_left, new); + if (victim->rb_right) + rb_set_parent(victim->rb_right, new); + + /* Copy the pointers/colour from the victim to the replacement */ + *new = *victim; +} + +static struct rb_node *rb_left_deepest_node(const struct rb_node *node) +{ + for (;;) { + if (node->rb_left) + node = node->rb_left; + else if (node->rb_right) + node = node->rb_right; + else + return (struct rb_node *)node; + } +} + +struct rb_node *rb_next_postorder(const struct rb_node *node) +{ + const struct rb_node *parent; + if (!node) + return NULL; + parent = rb_parent(node); + + /* If we're sitting on node, we've already seen our children */ + if (parent && node == parent->rb_left && parent->rb_right) { + /* If we are the parent's left node, go to the parent's right + * node then all the way down to the left */ + return rb_left_deepest_node(parent->rb_right); + } else + /* Otherwise we are the parent's right node, and the parent + * should be next */ + return (struct rb_node *)parent; +} + +struct rb_node *rb_first_postorder(const struct rb_root *root) +{ + if (!root->rb_node) + return NULL; + + return rb_left_deepest_node(root->rb_node); +} diff --git a/src/entry/rbtree.h b/src/entry/rbtree.h new file mode 100644 index 0000000..adfad02 --- /dev/null +++ b/src/entry/rbtree.h @@ -0,0 +1,118 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/include/linux/rbtree.h + + To use rbtrees you'll have to implement your own insert and search cores. + This will avoid us to use callbacks and to drop drammatically performances. + I know it's not the cleaner way, but in C (not in C++) to get + performances and genericity... + + See Documentation/rbtree.txt for documentation and samples. +*/ + +#ifndef _LINUX_RBTREE_H +#define _LINUX_RBTREE_H + +#include + +struct rb_node { + unsigned long __rb_parent_color; + struct rb_node *rb_right; + struct rb_node *rb_left; +} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root { + struct rb_node *rb_node; +}; + + +#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) + +#define RB_ROOT (struct rb_root) { NULL, } + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type, member) );}) +#endif + +#define rb_entry(ptr, type, member) container_of(ptr, type, member) + +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) + +/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ +#define RB_EMPTY_NODE(node) \ + ((node)->__rb_parent_color == (unsigned long)(node)) +#define RB_CLEAR_NODE(node) \ + ((node)->__rb_parent_color = (unsigned long)(node)) + + +extern void rb_insert_color(struct rb_node *, struct rb_root *); +extern void rb_erase(struct rb_node *, struct rb_root *); + + +/* Find logical next and previous nodes in a tree */ +extern struct rb_node *rb_next(const struct rb_node *); +extern struct rb_node *rb_prev(const struct rb_node *); +extern struct rb_node *rb_first(const struct rb_root *); +extern struct rb_node *rb_last(const struct rb_root *); + +/* Postorder iteration - always visit the parent after its children */ +extern struct rb_node *rb_first_postorder(const struct rb_root *); +extern struct rb_node *rb_next_postorder(const struct rb_node *); + +/* Fast replacement of a single node without remove/rebalance/add/rebalance */ +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, + struct rb_root *root); + +static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, + struct rb_node ** rb_link) +{ + node->__rb_parent_color = (unsigned long)parent; + node->rb_left = node->rb_right = NULL; + + *rb_link = node; +} + +#define rb_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? rb_entry(____ptr, type, member) : NULL; \ + }) + +/** + * rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of + * given type safe against removal of rb_node entry + * + * @pos: the 'type *' to use as a loop cursor. + * @n: another 'type *' to use as temporary storage + * @root: 'rb_root *' of the rbtree. + * @field: the name of the rb_node field within 'type'. + */ +#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \ + for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \ + pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \ + typeof(*pos), field); 1; }); \ + pos = n) + +#endif /* _LINUX_RBTREE_H */ diff --git a/src/entry/rbtree_augmented.h b/src/entry/rbtree_augmented.h new file mode 100644 index 0000000..bf3b639 --- /dev/null +++ b/src/entry/rbtree_augmented.h @@ -0,0 +1,241 @@ +/* + Red Black Trees + (C) 1999 Andrea Arcangeli + (C) 2002 David Woodhouse + (C) 2012 Michel Lespinasse + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + linux/include/linux/rbtree_augmented.h +*/ + +#ifndef _LINUX_RBTREE_AUGMENTED_H +#define _LINUX_RBTREE_AUGMENTED_H + +#include "rbtree.h" + +/* + * Please note - only struct rb_augment_callbacks and the prototypes for + * rb_insert_augmented() and rb_erase_augmented() are intended to be public. + * The rest are implementation details you are not expected to depend on. + * + * See Documentation/rbtree.txt for documentation and samples. + */ + +struct rb_augment_callbacks { + void (*propagate)(struct rb_node *node, struct rb_node *stop); + void (*copy)(struct rb_node *old, struct rb_node *new); + void (*rotate)(struct rb_node *old, struct rb_node *new); +}; + +extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); +/* + * Fixup the rbtree and update the augmented information when rebalancing. + * + * On insertion, the user must update the augmented information on the path + * leading to the inserted node, then call rb_link_node() as usual and + * rb_augment_inserted() instead of the usual rb_insert_color() call. + * If rb_augment_inserted() rebalances the rbtree, it will callback into + * a user provided function to update the augmented information on the + * affected subtrees. + */ +static inline void +rb_insert_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + __rb_insert_augmented(node, root, augment->rotate); +} + +#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ + rbtype, rbaugmented, rbcompute) \ +static inline void \ +rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ +{ \ + while (rb != stop) { \ + rbstruct *node = rb_entry(rb, rbstruct, rbfield); \ + rbtype augmented = rbcompute(node); \ + if (node->rbaugmented == augmented) \ + break; \ + node->rbaugmented = augmented; \ + rb = rb_parent(&node->rbfield); \ + } \ +} \ +static inline void \ +rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ +{ \ + rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ + rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ + new->rbaugmented = old->rbaugmented; \ +} \ +static void \ +rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ +{ \ + rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ + rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ + new->rbaugmented = old->rbaugmented; \ + old->rbaugmented = rbcompute(old); \ +} \ +rbstatic const struct rb_augment_callbacks rbname = { \ + rbname ## _propagate, rbname ## _copy, rbname ## _rotate \ +}; + + +#define RB_RED 0 +#define RB_BLACK 1 + +#define __rb_parent(pc) ((struct rb_node *)(pc & ~3)) + +#define __rb_color(pc) ((pc) & 1) +#define __rb_is_black(pc) __rb_color(pc) +#define __rb_is_red(pc) (!__rb_color(pc)) +#define rb_color(rb) __rb_color((rb)->__rb_parent_color) +#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color) +#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color) + +static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->__rb_parent_color = rb_color(rb) | (unsigned long)p; +} + +static inline void rb_set_parent_color(struct rb_node *rb, + struct rb_node *p, int color) +{ + rb->__rb_parent_color = (unsigned long)p | color; +} + +static inline void +__rb_change_child(struct rb_node *old, struct rb_node *new, + struct rb_node *parent, struct rb_root *root) +{ + if (parent) { + if (parent->rb_left == old) + parent->rb_left = new; + else + parent->rb_right = new; + } else + root->rb_node = new; +} + +extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, + void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); + +static __always_inline struct rb_node * +__rb_erase_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + struct rb_node *child = node->rb_right, *tmp = node->rb_left; + struct rb_node *parent, *rebalance; + unsigned long pc; + + if (!tmp) { + /* + * Case 1: node to erase has no more than 1 child (easy!) + * + * Note that if there is one child it must be red due to 5) + * and node must be black due to 4). We adjust colors locally + * so as to bypass __rb_erase_color() later on. + */ + pc = node->__rb_parent_color; + parent = __rb_parent(pc); + __rb_change_child(node, child, parent, root); + if (child) { + child->__rb_parent_color = pc; + rebalance = NULL; + } else + rebalance = __rb_is_black(pc) ? parent : NULL; + tmp = parent; + } else if (!child) { + /* Still case 1, but this time the child is node->rb_left */ + tmp->__rb_parent_color = pc = node->__rb_parent_color; + parent = __rb_parent(pc); + __rb_change_child(node, tmp, parent, root); + rebalance = NULL; + tmp = parent; + } else { + struct rb_node *successor = child, *child2; + tmp = child->rb_left; + if (!tmp) { + /* + * Case 2: node's successor is its right child + * + * (n) (s) + * / \ / \ + * (x) (s) -> (x) (c) + * \ + * (c) + */ + parent = successor; + child2 = successor->rb_right; + augment->copy(node, successor); + } else { + /* + * Case 3: node's successor is leftmost under + * node's right child subtree + * + * (n) (s) + * / \ / \ + * (x) (y) -> (x) (y) + * / / + * (p) (p) + * / / + * (s) (c) + * \ + * (c) + */ + do { + parent = successor; + successor = tmp; + tmp = tmp->rb_left; + } while (tmp); + parent->rb_left = child2 = successor->rb_right; + successor->rb_right = child; + rb_set_parent(child, successor); + augment->copy(node, successor); + augment->propagate(parent, successor); + } + + successor->rb_left = tmp = node->rb_left; + rb_set_parent(tmp, successor); + + pc = node->__rb_parent_color; + tmp = __rb_parent(pc); + __rb_change_child(node, successor, tmp, root); + if (child2) { + successor->__rb_parent_color = pc; + rb_set_parent_color(child2, parent, RB_BLACK); + rebalance = NULL; + } else { + unsigned long pc2 = successor->__rb_parent_color; + successor->__rb_parent_color = pc; + rebalance = __rb_is_black(pc2) ? parent : NULL; + } + tmp = successor; + } + + augment->propagate(tmp, NULL); + return rebalance; +} + +static __always_inline void +rb_erase_augmented(struct rb_node *node, struct rb_root *root, + const struct rb_augment_callbacks *augment) +{ + struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); + if (rebalance) + __rb_erase_color(rebalance, root, augment->rotate); +} + +#endif /* _LINUX_RBTREE_AUGMENTED_H */ diff --git a/src/entry/sfh_internal.h b/src/entry/sfh_internal.h new file mode 100644 index 0000000..ddfeddc --- /dev/null +++ b/src/entry/sfh_internal.h @@ -0,0 +1,106 @@ +#include +#include +#include + +#ifndef __SFH_INTERNAL_H_INCLUDE_ +#define __SFH_INTERNAL_H_INCLUDE_ + +#define ROLLING_WINDOW 7 +#define BLOCKSIZE_MIN 3 +#define HASH_PRIME 0x01000193 +#define HASH_INIT 0x28021967 +#define CALCULATE 0 +#define MODIFY 1 +#define EXPECT_SIGNATURE_LEN 64 +#define MEMORY_OCCUPY 3 + +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define DEBUG (0) + +int hash_length; +//int count = 0; +struct roll_state_t +{ + unsigned char window[ROLLING_WINDOW]; + unsigned char pad[1]; + unsigned int h1, h2, h3; + unsigned int n; +}; + + +typedef struct +{ + char mbuf[ROLLING_WINDOW-1]; + char pad[8-ROLLING_WINDOW+1]; + int slice_num; + unsigned int msize; + struct zt_state_t ps; //partial strong hash value + struct zt_state_t s_state;//strong hash state + unsigned long long left_offset; + unsigned long long right_offset; + struct roll_state_t r_state; + unsigned int * r_array; //array to store rolling hash value + unsigned int r_cnt; + unsigned int r_size; + struct zt_state_t * s_array; //array to store strong(Tillichi-Zemor) hash value + unsigned int s_cnt; //always point to the next available position + unsigned int s_size; +}sfh_seg_t; + + +typedef struct +{ + unsigned long long orilen; + IVI_t * ivi; //每一个handle里面保存一个IVI指针,一个IVI里面保存的是一个文件里的片 + unsigned long long effective_length; + unsigned long long blocksize; + unsigned long long fuzzy_node_memory; + unsigned long long IVI_memory; + unsigned long long length_increase; + int s_state_cnt; + unsigned int sim_tuned_rs_cnt;//rolling state count after a tune simulation + int do_tune; +}fuzzy_handle_inner_t; + + +typedef struct +{ + char * data; //最后输出结果的char数组 + unsigned int size; + unsigned int offset; //数组长度 + unsigned long long first_ZTH_offset; + unsigned long long last_ZTH_offset; + char last_char; +}final_result; + + +typedef struct +{ + unsigned long long first_ZTH_offset; + unsigned long long last_ZTH_offset; + unsigned long long hash_length; +}final_length; + +sfh_seg_t* create_sfh_seg(fuzzy_handle_inner_t * _handle); +int destroy_sfh_seg(sfh_seg_t*p); +unsigned long long get_blocksize(unsigned long long orilen); +int sfh_merge_seg(fuzzy_handle_inner_t * _handle,sfh_seg_t * seg, sfh_seg_t * next_seg, unsigned long long blocksize); +int sfh_update_seg(fuzzy_handle_inner_t * _handle,sfh_seg_t * p, const char * data, unsigned long data_size, unsigned long long blocksize); +unsigned int segment_overlap(fuzzy_handle_inner_t * handle, unsigned int size, unsigned long long offset, const char * data); +void sfh_tune_seg(IVI_seg_t * seg, void * user_para); +void sfh_output_state(IVI_seg_t * seg, void * user_para); +void fuzzy_hash_length(IVI_seg_t * seg, void * user_para); +unsigned long long fuzzy_status(fuzzy_handle_t * handle, int type); +#endif diff --git a/src/entry/zt_hash.h b/src/entry/zt_hash.h new file mode 100644 index 0000000..8acf0be --- /dev/null +++ b/src/entry/zt_hash.h @@ -0,0 +1,234 @@ +#include +#include + +struct zt_state_t +{ + union + { + unsigned char matrix[4]; //strong hash state + unsigned int val; + }; +}; + +const unsigned char table[256][4] = +{ + {76,28,128,81},{76,204,128,209},{204,128,209,81},{204,76,209,128},{238,209,196,115},{238,63,196,183},{63,209,183,115},{63,238,183,196},{230,196,193,123},{230,34,193,186},{34,196,186,123},{34,230,186,193},{0,183,175,76},{0,183,175,227},{183,183,227,76},{183,0,227,175},{228,193,192,121},{228,37,192,185},{37,193,185,121},{37,228,185,192},{18,186,164,75},{18,168,164,239},{168,186,239,75},{168,18,239,164},{15,175,169,67},{15,160,169,234},{160,175,234,67},{160,15,234,169},{151,227,247,108},{151,116,247,155},{116,227,155,108},{116,151,155,247},{228,192,193,121},{228,36,193,184},{36,192,184,121},{36,228,184,193},{22,185,167,74},{22,175,167,237},{175,185,237,74},{175,22,237,167},{30,164,162,71},{30,186,162,229},{186,164,229,71},{186,30,229,162},{136,239,250,107},{136,103,250,145},{103,239,145,107},{103,136,145,250},{12,169,169,64},{12,165,169,233},{165,169,233,64},{165,12,233,169},{138,234,251,105},{138,96,251,146},{96,234,146,105},{96,138,146,251},{159,247,243,100},{159,104,243,151},{104,247,151,100},{104,159,151,243},{71,155,133,95},{71,220,133,218},{220,155,218,95},{220,71,218,133},{230,193,196,123},{230,39,196,191},{39,193,191,123},{39,230,191,196},{20,184,160,73},{20,172,160,233},{172,184,233,73},{172,20,233,160},{25,167,167,69},{25,190,167,226},{190,167,226,69},{190,25,226,167},{141,237,253,104},{141,96,253,149},{96,237,149,104},{96,141,149,253},{30,162,164,71},{30,188,164,227},{188,162,227,71},{188,30,227,164},{144,229,240,109},{144,117,240,157},{117,229,157,109},{117,144,157,240},{130,250,251,97},{130,120,251,154},{120,250,154,97},{120,130,154,251},{84,145,137,88},{84,197,137,209},{197,145,209,88},{197,84,209,137},{15,169,175,67},{15,166,175,236},{166,169,236,67},{166,15,236,175},{143,233,253,106},{143,102,253,151},{102,233,151,106},{102,143,151,253},{130,251,250,97},{130,121,250,155},{121,251,155,97},{121,130,155,250},{80,146,138,89},{80,194,138,211},{194,146,211,89},{194,80,211,138},{159,243,247,100},{159,108,247,147},{108,243,147,100},{108,159,147,247},{87,151,137,91},{87,192,137,210},{192,151,210,91},{192,87,210,137},{72,133,133,80},{72,205,133,213},{205,133,213,80},{205,72,213,133},{246,218,207,117},{246,44,207,186},{44,218,186,117},{44,246,186,207},{238,196,209,115},{238,42,209,162},{42,196,162,115},{42,238,162,209},{24,191,191,68},{24,167,191,251},{167,191,251,68},{167,24,251,191},{20,160,184,73},{20,180,184,241},{180,160,241,73},{180,20,241,184},{134,233,236,99},{134,111,236,143},{111,233,143,99},{111,134,143,236},{22,167,185,74},{22,177,185,243},{177,167,243,74},{177,22,243,185},{156,226,227,103},{156,126,227,132},{126,226,132,103},{126,156,132,227},{143,253,233,106},{143,114,233,131},{114,253,131,106},{114,143,131,233},{95,149,147,87},{95,202,147,196},{202,149,196,87},{202,95,196,147},{18,164,186,75},{18,182,186,241},{182,164,241,75},{182,18,241,186},{156,227,226,103},{156,127,226,133},{127,227,133,103},{127,156,133,226},{144,240,229,109},{144,96,229,136},{96,240,136,109},{96,144,136,229},{74,157,155,82},{74,215,155,201},{215,157,201,82},{215,74,201,155},{138,251,234,105},{138,113,234,131},{113,251,131,105},{113,138,131,234},{72,154,154,81},{72,210,154,203},{210,154,203,81},{210,72,203,154},{87,137,151,91},{87,222,151,204},{222,137,204,91},{222,87,204,151},{231,209,213,122},{231,54,213,175},{54,209,175,122},{54,231,175,213},{0,175,183,76},{0,175,183,251},{175,175,251,76},{175,0,251,183},{134,236,233,99},{134,106,233,138},{106,236,138,99},{106,134,138,233},{141,253,237,104},{141,112,237,133},{112,253,133,104},{112,141,133,237},{89,151,151,85},{89,206,151,194},{206,151,194,85},{206,89,194,151},{136,250,239,107},{136,114,239,132},{114,250,132,107},{114,136,132,239},{74,155,157,82},{74,209,157,207},{209,155,207,82},{209,74,207,157},{80,138,146,89},{80,218,146,203},{218,138,203,89},{218,80,203,146},{226,211,210,121},{226,49,210,171},{49,211,171,121},{49,226,171,210},{151,247,227,108},{151,96,227,143},{96,247,143,108},{96,151,143,227},{95,147,149,87},{95,204,149,194},{204,147,194,87},{204,95,194,149},{84,137,145,88},{84,221,145,201},{221,137,201,88},{221,84,201,145},{226,210,211,121},{226,48,211,170},{48,210,170,121},{48,226,170,211},{71,133,155,95},{71,194,155,196},{194,133,196,95},{194,71,196,155},{231,213,209,122},{231,50,209,171},{50,213,171,122},{50,231,171,209},{246,207,218,117},{246,57,218,175},{57,207,175,117},{57,246,175,218},{28,186,186,69},{28,166,186,255},{166,186,255,69},{166,28,255,186} +}; + +const static unsigned char galois_mult_8_table[65536] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,29,31,25,27,21,23,17,19,13,15,9,11,5,7,1,3,61,63,57,59,53,55,49,51,45,47,41,43,37,39,33,35,93,95,89,91,85,87,81,83,77,79,73,75,69,71,65,67,125,127,121,123,117,119,113,115,109,111,105,107,101,103,97,99,157,159,153,155,149,151,145,147,141,143,137,139,133,135,129,131,189,191,185,187,181,183,177,179,173,175,169,171,165,167,161,163,221,223,217,219,213,215,209,211,205,207,201,203,197,199,193,195,253,255,249,251,245,247,241,243,237,239,233,235,229,231,225,227,0,3,6,5,12,15,10,9,24,27,30,29,20,23,18,17,48,51,54,53,60,63,58,57,40,43,46,45,36,39,34,33,96,99,102,101,108,111,106,105,120,123,126,125,116,119,114,113,80,83,86,85,92,95,90,89,72,75,78,77,68,71,66,65,192,195,198,197,204,207,202,201,216,219,222,221,212,215,210,209,240,243,246,245,252,255,250,249,232,235,238,237,228,231,226,225,160,163,166,165,172,175,170,169,184,187,190,189,180,183,178,177,144,147,150,149,156,159,154,153,136,139,142,141,132,135,130,129,157,158,155,152,145,146,151,148,133,134,131,128,137,138,143,140,173,174,171,168,161,162,167,164,181,182,179,176,185,186,191,188,253,254,251,248,241,242,247,244,229,230,227,224,233,234,239,236,205,206,203,200,193,194,199,196,213,214,211,208,217,218,223,220,93,94,91,88,81,82,87,84,69,70,67,64,73,74,79,76,109,110,107,104,97,98,103,100,117,118,115,112,121,122,127,124,61,62,59,56,49,50,55,52,37,38,35,32,41,42,47,44,13,14,11,8,1,2,7,4,21,22,19,16,25,26,31,28,0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,29,25,21,17,13,9,5,1,61,57,53,49,45,41,37,33,93,89,85,81,77,73,69,65,125,121,117,113,109,105,101,97,157,153,149,145,141,137,133,129,189,185,181,177,173,169,165,161,221,217,213,209,205,201,197,193,253,249,245,241,237,233,229,225,58,62,50,54,42,46,34,38,26,30,18,22,10,14,2,6,122,126,114,118,106,110,98,102,90,94,82,86,74,78,66,70,186,190,178,182,170,174,162,166,154,158,146,150,138,142,130,134,250,254,242,246,234,238,226,230,218,222,210,214,202,206,194,198,39,35,47,43,55,51,63,59,7,3,15,11,23,19,31,27,103,99,111,107,119,115,127,123,71,67,79,75,87,83,95,91,167,163,175,171,183,179,191,187,135,131,143,139,151,147,159,155,231,227,239,235,247,243,255,251,199,195,207,203,215,211,223,219,0,5,10,15,20,17,30,27,40,45,34,39,60,57,54,51,80,85,90,95,68,65,78,75,120,125,114,119,108,105,102,99,160,165,170,175,180,177,190,187,136,141,130,135,156,153,150,147,240,245,250,255,228,225,238,235,216,221,210,215,204,201,198,195,93,88,87,82,73,76,67,70,117,112,127,122,97,100,107,110,13,8,7,2,25,28,19,22,37,32,47,42,49,52,59,62,253,248,247,242,233,236,227,230,213,208,223,218,193,196,203,206,173,168,167,162,185,188,179,182,133,128,143,138,145,148,155,158,186,191,176,181,174,171,164,161,146,151,152,157,134,131,140,137,234,239,224,229,254,251,244,241,194,199,200,205,214,211,220,217,26,31,16,21,14,11,4,1,50,55,56,61,38,35,44,41,74,79,64,69,94,91,84,81,98,103,104,109,118,115,124,121,231,226,237,232,243,246,249,252,207,202,197,192,219,222,209,212,183,178,189,184,163,166,169,172,159,154,149,144,139,142,129,132,71,66,77,72,83,86,89,92,111,106,101,96,123,126,113,116,23,18,29,24,3,6,9,12,63,58,53,48,43,46,33,36,0,6,12,10,24,30,20,18,48,54,60,58,40,46,36,34,96,102,108,106,120,126,116,114,80,86,92,90,72,78,68,66,192,198,204,202,216,222,212,210,240,246,252,250,232,238,228,226,160,166,172,170,184,190,180,178,144,150,156,154,136,142,132,130,157,155,145,151,133,131,137,143,173,171,161,167,181,179,185,191,253,251,241,247,229,227,233,239,205,203,193,199,213,211,217,223,93,91,81,87,69,67,73,79,109,107,97,103,117,115,121,127,61,59,49,55,37,35,41,47,13,11,1,7,21,19,25,31,39,33,43,45,63,57,51,53,23,17,27,29,15,9,3,5,71,65,75,77,95,89,83,85,119,113,123,125,111,105,99,101,231,225,235,237,255,249,243,245,215,209,219,221,207,201,195,197,135,129,139,141,159,153,147,149,183,177,187,189,175,169,163,165,186,188,182,176,162,164,174,168,138,140,134,128,146,148,158,152,218,220,214,208,194,196,206,200,234,236,230,224,242,244,254,248,122,124,118,112,98,100,110,104,74,76,70,64,82,84,94,88,26,28,22,16,2,4,14,8,42,44,38,32,50,52,62,56,0,7,14,9,28,27,18,21,56,63,54,49,36,35,42,45,112,119,126,121,108,107,98,101,72,79,70,65,84,83,90,93,224,231,238,233,252,251,242,245,216,223,214,209,196,195,202,205,144,151,158,153,140,139,130,133,168,175,166,161,180,179,186,189,221,218,211,212,193,198,207,200,229,226,235,236,249,254,247,240,173,170,163,164,177,182,191,184,149,146,155,156,137,142,135,128,61,58,51,52,33,38,47,40,5,2,11,12,25,30,23,16,77,74,67,68,81,86,95,88,117,114,123,124,105,110,103,96,167,160,169,174,187,188,181,178,159,152,145,150,131,132,141,138,215,208,217,222,203,204,197,194,239,232,225,230,243,244,253,250,71,64,73,78,91,92,85,82,127,120,113,118,99,100,109,106,55,48,57,62,43,44,37,34,15,8,1,6,19,20,29,26,122,125,116,115,102,97,104,111,66,69,76,75,94,89,80,87,10,13,4,3,22,17,24,31,50,53,60,59,46,41,32,39,154,157,148,147,134,129,136,143,162,165,172,171,190,185,176,183,234,237,228,227,246,241,248,255,210,213,220,219,206,201,192,199,0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,29,21,13,5,61,53,45,37,93,85,77,69,125,117,109,101,157,149,141,133,189,181,173,165,221,213,205,197,253,245,237,229,58,50,42,34,26,18,10,2,122,114,106,98,90,82,74,66,186,178,170,162,154,146,138,130,250,242,234,226,218,210,202,194,39,47,55,63,7,15,23,31,103,111,119,127,71,79,87,95,167,175,183,191,135,143,151,159,231,239,247,255,199,207,215,223,116,124,100,108,84,92,68,76,52,60,36,44,20,28,4,12,244,252,228,236,212,220,196,204,180,188,164,172,148,156,132,140,105,97,121,113,73,65,89,81,41,33,57,49,9,1,25,17,233,225,249,241,201,193,217,209,169,161,185,177,137,129,153,145,78,70,94,86,110,102,126,118,14,6,30,22,46,38,62,54,206,198,222,214,238,230,254,246,142,134,158,150,174,166,190,182,83,91,67,75,115,123,99,107,19,27,3,11,51,59,35,43,211,219,195,203,243,251,227,235,147,155,131,139,179,187,163,171,0,9,18,27,36,45,54,63,72,65,90,83,108,101,126,119,144,153,130,139,180,189,166,175,216,209,202,195,252,245,238,231,61,52,47,38,25,16,11,2,117,124,103,110,81,88,67,74,173,164,191,182,137,128,155,146,229,236,247,254,193,200,211,218,122,115,104,97,94,87,76,69,50,59,32,41,22,31,4,13,234,227,248,241,206,199,220,213,162,171,176,185,134,143,148,157,71,78,85,92,99,106,113,120,15,6,29,20,43,34,57,48,215,222,197,204,243,250,225,232,159,150,141,132,187,178,169,160,244,253,230,239,208,217,194,203,188,181,174,167,152,145,138,131,100,109,118,127,64,73,82,91,44,37,62,55,8,1,26,19,201,192,219,210,237,228,255,246,129,136,147,154,165,172,183,190,89,80,75,66,125,116,111,102,17,24,3,10,53,60,39,46,142,135,156,149,170,163,184,177,198,207,212,221,226,235,240,249,30,23,12,5,58,51,40,33,86,95,68,77,114,123,96,105,179,186,161,168,151,158,133,140,251,242,233,224,223,214,205,196,35,42,49,56,7,14,21,28,107,98,121,112,79,70,93,84,0,10,20,30,40,34,60,54,80,90,68,78,120,114,108,102,160,170,180,190,136,130,156,150,240,250,228,238,216,210,204,198,93,87,73,67,117,127,97,107,13,7,25,19,37,47,49,59,253,247,233,227,213,223,193,203,173,167,185,179,133,143,145,155,186,176,174,164,146,152,134,140,234,224,254,244,194,200,214,220,26,16,14,4,50,56,38,44,74,64,94,84,98,104,118,124,231,237,243,249,207,197,219,209,183,189,163,169,159,149,139,129,71,77,83,89,111,101,123,113,23,29,3,9,63,53,43,33,105,99,125,119,65,75,85,95,57,51,45,39,17,27,5,15,201,195,221,215,225,235,245,255,153,147,141,135,177,187,165,175,52,62,32,42,28,22,8,2,100,110,112,122,76,70,88,82,148,158,128,138,188,182,168,162,196,206,208,218,236,230,248,242,211,217,199,205,251,241,239,229,131,137,151,157,171,161,191,181,115,121,103,109,91,81,79,69,35,41,55,61,11,1,31,21,142,132,154,144,166,172,178,184,222,212,202,192,246,252,226,232,46,36,58,48,6,12,18,24,126,116,106,96,86,92,66,72,0,11,22,29,44,39,58,49,88,83,78,69,116,127,98,105,176,187,166,173,156,151,138,129,232,227,254,245,196,207,210,217,125,118,107,96,81,90,71,76,37,46,51,56,9,2,31,20,205,198,219,208,225,234,247,252,149,158,131,136,185,178,175,164,250,241,236,231,214,221,192,203,162,169,180,191,142,133,152,147,74,65,92,87,102,109,112,123,18,25,4,15,62,53,40,35,135,140,145,154,171,160,189,182,223,212,201,194,243,248,229,238,55,60,33,42,27,16,13,6,111,100,121,114,67,72,85,94,233,226,255,244,197,206,211,216,177,186,167,172,157,150,139,128,89,82,79,68,117,126,99,104,1,10,23,28,45,38,59,48,148,159,130,137,184,179,174,165,204,199,218,209,224,235,246,253,36,47,50,57,8,3,30,21,124,119,106,97,80,91,70,77,19,24,5,14,63,52,41,34,75,64,93,86,103,108,113,122,163,168,181,190,143,132,153,146,251,240,237,230,215,220,193,202,110,101,120,115,66,73,84,95,54,61,32,43,26,17,12,7,222,213,200,195,242,249,228,239,134,141,144,155,170,161,188,183,0,12,24,20,48,60,40,36,96,108,120,116,80,92,72,68,192,204,216,212,240,252,232,228,160,172,184,180,144,156,136,132,157,145,133,137,173,161,181,185,253,241,229,233,205,193,213,217,93,81,69,73,109,97,117,121,61,49,37,41,13,1,21,25,39,43,63,51,23,27,15,3,71,75,95,83,119,123,111,99,231,235,255,243,215,219,207,195,135,139,159,147,183,187,175,163,186,182,162,174,138,134,146,158,218,214,194,206,234,230,242,254,122,118,98,110,74,70,82,94,26,22,2,14,42,38,50,62,78,66,86,90,126,114,102,106,46,34,54,58,30,18,6,10,142,130,150,154,190,178,166,170,238,226,246,250,222,210,198,202,211,223,203,199,227,239,251,247,179,191,171,167,131,143,155,151,19,31,11,7,35,47,59,55,115,127,107,103,67,79,91,87,105,101,113,125,89,85,65,77,9,5,17,29,57,53,33,45,169,165,177,189,153,149,129,141,201,197,209,221,249,245,225,237,244,248,236,224,196,200,220,208,148,152,140,128,164,168,188,176,52,56,44,32,4,8,28,16,84,88,76,64,100,104,124,112,0,13,26,23,52,57,46,35,104,101,114,127,92,81,70,75,208,221,202,199,228,233,254,243,184,181,162,175,140,129,150,155,189,176,167,170,137,132,147,158,213,216,207,194,225,236,251,246,109,96,119,122,89,84,67,78,5,8,31,18,49,60,43,38,103,106,125,112,83,94,73,68,15,2,21,24,59,54,33,44,183,186,173,160,131,142,153,148,223,210,197,200,235,230,241,252,218,215,192,205,238,227,244,249,178,191,168,165,134,139,156,145,10,7,16,29,62,51,36,41,98,111,120,117,86,91,76,65,206,195,212,217,250,247,224,237,166,171,188,177,146,159,136,133,30,19,4,9,42,39,48,61,118,123,108,97,66,79,88,85,115,126,105,100,71,74,93,80,27,22,1,12,47,34,53,56,163,174,185,180,151,154,141,128,203,198,209,220,255,242,229,232,169,164,179,190,157,144,135,138,193,204,219,214,245,248,239,226,121,116,99,110,77,64,87,90,17,28,11,6,37,40,63,50,20,25,14,3,32,45,58,55,124,113,102,107,72,69,82,95,196,201,222,211,240,253,234,231,172,161,182,187,152,149,130,143,0,14,28,18,56,54,36,42,112,126,108,98,72,70,84,90,224,238,252,242,216,214,196,202,144,158,140,130,168,166,180,186,221,211,193,207,229,235,249,247,173,163,177,191,149,155,137,135,61,51,33,47,5,11,25,23,77,67,81,95,117,123,105,103,167,169,187,181,159,145,131,141,215,217,203,197,239,225,243,253,71,73,91,85,127,113,99,109,55,57,43,37,15,1,19,29,122,116,102,104,66,76,94,80,10,4,22,24,50,60,46,32,154,148,134,136,162,172,190,176,234,228,246,248,210,220,206,192,83,93,79,65,107,101,119,121,35,45,63,49,27,21,7,9,179,189,175,161,139,133,151,153,195,205,223,209,251,245,231,233,142,128,146,156,182,184,170,164,254,240,226,236,198,200,218,212,110,96,114,124,86,88,74,68,30,16,2,12,38,40,58,52,244,250,232,230,204,194,208,222,132,138,152,150,188,178,160,174,20,26,8,6,44,34,48,62,100,106,120,118,92,82,64,78,41,39,53,59,17,31,13,3,89,87,69,75,97,111,125,115,201,199,213,219,241,255,237,227,185,183,165,171,129,143,157,147,0,15,30,17,60,51,34,45,120,119,102,105,68,75,90,85,240,255,238,225,204,195,210,221,136,135,150,153,180,187,170,165,253,242,227,236,193,206,223,208,133,138,155,148,185,182,167,168,13,2,19,28,49,62,47,32,117,122,107,100,73,70,87,88,231,232,249,246,219,212,197,202,159,144,129,142,163,172,189,178,23,24,9,6,43,36,53,58,111,96,113,126,83,92,77,66,26,21,4,11,38,41,56,55,98,109,124,115,94,81,64,79,234,229,244,251,214,217,200,199,146,157,140,131,174,161,176,191,211,220,205,194,239,224,241,254,171,164,181,186,151,152,137,134,35,44,61,50,31,16,1,14,91,84,69,74,103,104,121,118,46,33,48,63,18,29,12,3,86,89,72,71,106,101,116,123,222,209,192,207,226,237,252,243,166,169,184,183,154,149,132,139,52,59,42,37,8,7,22,25,76,67,82,93,112,127,110,97,196,203,218,213,248,247,230,233,188,179,162,173,128,143,158,145,201,198,215,216,245,250,235,228,177,190,175,160,141,130,147,156,57,54,39,40,5,10,27,20,65,78,95,80,125,114,99,108,0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240,29,13,61,45,93,77,125,109,157,141,189,173,221,205,253,237,58,42,26,10,122,106,90,74,186,170,154,138,250,234,218,202,39,55,7,23,103,119,71,87,167,183,135,151,231,247,199,215,116,100,84,68,52,36,20,4,244,228,212,196,180,164,148,132,105,121,73,89,41,57,9,25,233,249,201,217,169,185,137,153,78,94,110,126,14,30,46,62,206,222,238,254,142,158,174,190,83,67,115,99,19,3,51,35,211,195,243,227,147,131,179,163,232,248,200,216,168,184,136,152,104,120,72,88,40,56,8,24,245,229,213,197,181,165,149,133,117,101,85,69,53,37,21,5,210,194,242,226,146,130,178,162,82,66,114,98,18,2,50,34,207,223,239,255,143,159,175,191,79,95,111,127,15,31,47,63,156,140,188,172,220,204,252,236,28,12,60,44,92,76,124,108,129,145,161,177,193,209,225,241,1,17,33,49,65,81,97,113,166,182,134,150,230,246,198,214,38,54,6,22,102,118,70,86,187,171,155,139,251,235,219,203,59,43,27,11,123,107,91,75,0,17,34,51,68,85,102,119,136,153,170,187,204,221,238,255,13,28,47,62,73,88,107,122,133,148,167,182,193,208,227,242,26,11,56,41,94,79,124,109,146,131,176,161,214,199,244,229,23,6,53,36,83,66,113,96,159,142,189,172,219,202,249,232,52,37,22,7,112,97,82,67,188,173,158,143,248,233,218,203,57,40,27,10,125,108,95,78,177,160,147,130,245,228,215,198,46,63,12,29,106,123,72,89,166,183,132,149,226,243,192,209,35,50,1,16,103,118,69,84,171,186,137,152,239,254,205,220,104,121,74,91,44,61,14,31,224,241,194,211,164,181,134,151,101,116,71,86,33,48,3,18,237,252,207,222,169,184,139,154,114,99,80,65,54,39,20,5,250,235,216,201,190,175,156,141,127,110,93,76,59,42,25,8,247,230,213,196,179,162,145,128,92,77,126,111,24,9,58,43,212,197,246,231,144,129,178,163,81,64,115,98,21,4,55,38,217,200,251,234,157,140,191,174,70,87,100,117,2,19,32,49,206,223,236,253,138,155,168,185,75,90,105,120,15,30,45,60,195,210,225,240,135,150,165,180,0,18,36,54,72,90,108,126,144,130,180,166,216,202,252,238,61,47,25,11,117,103,81,67,173,191,137,155,229,247,193,211,122,104,94,76,50,32,22,4,234,248,206,220,162,176,134,148,71,85,99,113,15,29,43,57,215,197,243,225,159,141,187,169,244,230,208,194,188,174,152,138,100,118,64,82,44,62,8,26,201,219,237,255,129,147,165,183,89,75,125,111,17,3,53,39,142,156,170,184,198,212,226,240,30,12,58,40,86,68,114,96,179,161,151,133,251,233,223,205,35,49,7,21,107,121,79,93,245,231,209,195,189,175,153,139,101,119,65,83,45,63,9,27,200,218,236,254,128,146,164,182,88,74,124,110,16,2,52,38,143,157,171,185,199,213,227,241,31,13,59,41,87,69,115,97,178,160,150,132,250,232,222,204,34,48,6,20,106,120,78,92,1,19,37,55,73,91,109,127,145,131,181,167,217,203,253,239,60,46,24,10,116,102,80,66,172,190,136,154,228,246,192,210,123,105,95,77,51,33,23,5,235,249,207,221,163,177,135,149,70,84,98,112,14,28,42,56,214,196,242,224,158,140,186,168,0,19,38,53,76,95,106,121,152,139,190,173,212,199,242,225,45,62,11,24,97,114,71,84,181,166,147,128,249,234,223,204,90,73,124,111,22,5,48,35,194,209,228,247,142,157,168,187,119,100,81,66,59,40,29,14,239,252,201,218,163,176,133,150,180,167,146,129,248,235,222,205,44,63,10,25,96,115,70,85,153,138,191,172,213,198,243,224,1,18,39,52,77,94,107,120,238,253,200,219,162,177,132,151,118,101,80,67,58,41,28,15,195,208,229,246,143,156,169,186,91,72,125,110,23,4,49,34,117,102,83,64,57,42,31,12,237,254,203,216,161,178,135,148,88,75,126,109,20,7,50,33,192,211,230,245,140,159,170,185,47,60,9,26,99,112,69,86,183,164,145,130,251,232,221,206,2,17,36,55,78,93,104,123,154,137,188,175,214,197,240,227,193,210,231,244,141,158,171,184,89,74,127,108,21,6,51,32,236,255,202,217,160,179,134,149,116,103,82,65,56,43,30,13,155,136,189,174,215,196,241,226,3,16,37,54,79,92,105,122,182,165,144,131,250,233,220,207,46,61,8,27,98,113,68,87,0,20,40,60,80,68,120,108,160,180,136,156,240,228,216,204,93,73,117,97,13,25,37,49,253,233,213,193,173,185,133,145,186,174,146,134,234,254,194,214,26,14,50,38,74,94,98,118,231,243,207,219,183,163,159,139,71,83,111,123,23,3,63,43,105,125,65,85,57,45,17,5,201,221,225,245,153,141,177,165,52,32,28,8,100,112,76,88,148,128,188,168,196,208,236,248,211,199,251,239,131,151,171,191,115,103,91,79,35,55,11,31,142,154,166,178,222,202,246,226,46,58,6,18,126,106,86,66,210,198,250,238,130,150,170,190,114,102,90,78,34,54,10,30,143,155,167,179,223,203,247,227,47,59,7,19,127,107,87,67,104,124,64,84,56,44,16,4,200,220,224,244,152,140,176,164,53,33,29,9,101,113,77,89,149,129,189,169,197,209,237,249,187,175,147,135,235,255,195,215,27,15,51,39,75,95,99,119,230,242,206,218,182,162,158,138,70,82,110,122,22,2,62,42,1,21,41,61,81,69,121,109,161,181,137,157,241,229,217,205,92,72,116,96,12,24,36,48,252,232,212,192,172,184,132,144,0,21,42,63,84,65,126,107,168,189,130,151,252,233,214,195,77,88,103,114,25,12,51,38,229,240,207,218,177,164,155,142,154,143,176,165,206,219,228,241,50,39,24,13,102,115,76,89,215,194,253,232,131,150,169,188,127,106,85,64,43,62,1,20,41,60,3,22,125,104,87,66,129,148,171,190,213,192,255,234,100,113,78,91,48,37,26,15,204,217,230,243,152,141,178,167,179,166,153,140,231,242,205,216,27,14,49,36,79,90,101,112,254,235,212,193,170,191,128,149,86,67,124,105,2,23,40,61,82,71,120,109,6,19,44,57,250,239,208,197,174,187,132,145,31,10,53,32,75,94,97,116,183,162,157,136,227,246,201,220,200,221,226,247,156,137,182,163,96,117,74,95,52,33,30,11,133,144,175,186,209,196,251,238,45,56,7,18,121,108,83,70,123,110,81,68,47,58,5,16,211,198,249,236,135,146,173,184,54,35,28,9,98,119,72,93,158,139,180,161,202,223,224,245,225,244,203,222,181,160,159,138,73,92,99,118,29,8,55,34,172,185,134,147,248,237,210,199,4,17,46,59,80,69,122,111,0,22,44,58,88,78,116,98,176,166,156,138,232,254,196,210,125,107,81,71,37,51,9,31,205,219,225,247,149,131,185,175,250,236,214,192,162,180,142,152,74,92,102,112,18,4,62,40,135,145,171,189,223,201,243,229,55,33,27,13,111,121,67,85,233,255,197,211,177,167,157,139,89,79,117,99,1,23,45,59,148,130,184,174,204,218,224,246,36,50,8,30,124,106,80,70,19,5,63,41,75,93,103,113,163,181,143,153,251,237,215,193,110,120,66,84,54,32,26,12,222,200,242,228,134,144,170,188,207,217,227,245,151,129,187,173,127,105,83,69,39,49,11,29,178,164,158,136,234,252,198,208,2,20,46,56,90,76,118,96,53,35,25,15,109,123,65,87,133,147,169,191,221,203,241,231,72,94,100,114,16,6,60,42,248,238,212,194,160,182,140,154,38,48,10,28,126,104,82,68,150,128,186,172,206,216,226,244,91,77,119,97,3,21,47,57,235,253,199,209,179,165,159,137,220,202,240,230,132,146,168,190,108,122,64,86,52,34,24,14,161,183,141,155,249,239,213,195,17,7,61,43,73,95,101,115,0,23,46,57,92,75,114,101,184,175,150,129,228,243,202,221,109,122,67,84,49,38,31,8,213,194,251,236,137,158,167,176,218,205,244,227,134,145,168,191,98,117,76,91,62,41,16,7,183,160,153,142,235,252,197,210,15,24,33,54,83,68,125,106,169,190,135,144,245,226,219,204,17,6,63,40,77,90,99,116,196,211,234,253,152,143,182,161,124,107,82,69,32,55,14,25,115,100,93,74,47,56,1,22,203,220,229,242,151,128,185,174,30,9,48,39,66,85,108,123,166,177,136,159,250,237,212,195,79,88,97,118,19,4,61,42,247,224,217,206,171,188,133,146,34,53,12,27,126,105,80,71,154,141,180,163,198,209,232,255,149,130,187,172,201,222,231,240,45,58,3,20,113,102,95,72,248,239,214,193,164,179,138,157,64,87,110,121,28,11,50,37,230,241,200,223,186,173,148,131,94,73,112,103,2,21,44,59,139,156,165,178,215,192,249,238,51,36,29,10,111,120,65,86,60,43,18,5,96,119,78,89,132,147,170,189,216,207,246,225,81,70,127,104,13,26,35,52,233,254,199,208,181,162,155,140,0,24,48,40,96,120,80,72,192,216,240,232,160,184,144,136,157,133,173,181,253,229,205,213,93,69,109,117,61,37,13,21,39,63,23,15,71,95,119,111,231,255,215,207,135,159,183,175,186,162,138,146,218,194,234,242,122,98,74,82,26,2,42,50,78,86,126,102,46,54,30,6,142,150,190,166,238,246,222,198,211,203,227,251,179,171,131,155,19,11,35,59,115,107,67,91,105,113,89,65,9,17,57,33,169,177,153,129,201,209,249,225,244,236,196,220,148,140,164,188,52,44,4,28,84,76,100,124,156,132,172,180,252,228,204,212,92,68,108,116,60,36,12,20,1,25,49,41,97,121,81,73,193,217,241,233,161,185,145,137,187,163,139,147,219,195,235,243,123,99,75,83,27,3,43,51,38,62,22,14,70,94,118,110,230,254,214,206,134,158,182,174,210,202,226,250,178,170,130,154,18,10,34,58,114,106,66,90,79,87,127,103,47,55,31,7,143,151,191,167,239,247,223,199,245,237,197,221,149,141,165,189,53,45,5,29,85,77,101,125,104,112,88,64,8,16,56,32,168,176,152,128,200,208,248,224,0,25,50,43,100,125,86,79,200,209,250,227,172,181,158,135,141,148,191,166,233,240,219,194,69,92,119,110,33,56,19,10,7,30,53,44,99,122,81,72,207,214,253,228,171,178,153,128,138,147,184,161,238,247,220,197,66,91,112,105,38,63,20,13,14,23,60,37,106,115,88,65,198,223,244,237,162,187,144,137,131,154,177,168,231,254,213,204,75,82,121,96,47,54,29,4,9,16,59,34,109,116,95,70,193,216,243,234,165,188,151,142,132,157,182,175,224,249,210,203,76,85,126,103,40,49,26,3,28,5,46,55,120,97,74,83,212,205,230,255,176,169,130,155,145,136,163,186,245,236,199,222,89,64,107,114,61,36,15,22,27,2,41,48,127,102,77,84,211,202,225,248,183,174,133,156,150,143,164,189,242,235,192,217,94,71,108,117,58,35,8,17,18,11,32,57,118,111,68,93,218,195,232,241,190,167,140,149,159,134,173,180,251,226,201,208,87,78,101,124,51,42,1,24,21,12,39,62,113,104,67,90,221,196,239,246,185,160,139,146,152,129,170,179,252,229,206,215,80,73,98,123,52,45,6,31,0,26,52,46,104,114,92,70,208,202,228,254,184,162,140,150,189,167,137,147,213,207,225,251,109,119,89,67,5,31,49,43,103,125,83,73,15,21,59,33,183,173,131,153,223,197,235,241,218,192,238,244,178,168,134,156,10,16,62,36,98,120,86,76,206,212,250,224,166,188,146,136,30,4,42,48,118,108,66,88,115,105,71,93,27,1,47,53,163,185,151,141,203,209,255,229,169,179,157,135,193,219,245,239,121,99,77,87,17,11,37,63,20,14,32,58,124,102,72,82,196,222,240,234,172,182,152,130,129,155,181,175,233,243,221,199,81,75,101,127,57,35,13,23,60,38,8,18,84,78,96,122,236,246,216,194,132,158,176,170,230,252,210,200,142,148,186,160,54,44,2,24,94,68,106,112,91,65,111,117,51,41,7,29,139,145,191,165,227,249,215,205,79,85,123,97,39,61,19,9,159,133,171,177,247,237,195,217,242,232,198,220,154,128,174,180,34,56,22,12,74,80,126,100,40,50,28,6,64,90,116,110,248,226,204,214,144,138,164,190,149,143,161,187,253,231,201,211,69,95,113,107,45,55,25,3,0,27,54,45,108,119,90,65,216,195,238,245,180,175,130,153,173,182,155,128,193,218,247,236,117,110,67,88,25,2,47,52,71,92,113,106,43,48,29,6,159,132,169,178,243,232,197,222,234,241,220,199,134,157,176,171,50,41,4,31,94,69,104,115,142,149,184,163,226,249,212,207,86,77,96,123,58,33,12,23,35,56,21,14,79,84,121,98,251,224,205,214,151,140,161,186,201,210,255,228,165,190,147,136,17,10,39,60,125,102,75,80,100,127,82,73,8,19,62,37,188,167,138,145,208,203,230,253,1,26,55,44,109,118,91,64,217,194,239,244,181,174,131,152,172,183,154,129,192,219,246,237,116,111,66,89,24,3,46,53,70,93,112,107,42,49,28,7,158,133,168,179,242,233,196,223,235,240,221,198,135,156,177,170,51,40,5,30,95,68,105,114,143,148,185,162,227,248,213,206,87,76,97,122,59,32,13,22,34,57,20,15,78,85,120,99,250,225,204,215,150,141,160,187,200,211,254,229,164,191,146,137,16,11,38,61,124,103,74,81,101,126,83,72,9,18,63,36,189,166,139,144,209,202,231,252,0,28,56,36,112,108,72,84,224,252,216,196,144,140,168,180,221,193,229,249,173,177,149,137,61,33,5,25,77,81,117,105,167,187,159,131,215,203,239,243,71,91,127,99,55,43,15,19,122,102,66,94,10,22,50,46,154,134,162,190,234,246,210,206,83,79,107,119,35,63,27,7,179,175,139,151,195,223,251,231,142,146,182,170,254,226,198,218,110,114,86,74,30,2,38,58,244,232,204,208,132,152,188,160,20,8,44,48,100,120,92,64,41,53,17,13,89,69,97,125,201,213,241,237,185,165,129,157,166,186,158,130,214,202,238,242,70,90,126,98,54,42,14,18,123,103,67,95,11,23,51,47,155,135,163,191,235,247,211,207,1,29,57,37,113,109,73,85,225,253,217,197,145,141,169,181,220,192,228,248,172,176,148,136,60,32,4,24,76,80,116,104,245,233,205,209,133,153,189,161,21,9,45,49,101,121,93,65,40,52,16,12,88,68,96,124,200,212,240,236,184,164,128,156,82,78,106,118,34,62,26,6,178,174,138,150,194,222,250,230,143,147,183,171,255,227,199,219,111,115,87,75,31,3,39,59,0,29,58,39,116,105,78,83,232,245,210,207,156,129,166,187,205,208,247,234,185,164,131,158,37,56,31,2,81,76,107,118,135,154,189,160,243,238,201,212,111,114,85,72,27,6,33,60,74,87,112,109,62,35,4,25,162,191,152,133,214,203,236,241,19,14,41,52,103,122,93,64,251,230,193,220,143,146,181,168,222,195,228,249,170,183,144,141,54,43,12,17,66,95,120,101,148,137,174,179,224,253,218,199,124,97,70,91,8,21,50,47,89,68,99,126,45,48,23,10,177,172,139,150,197,216,255,226,38,59,28,1,82,79,104,117,206,211,244,233,186,167,128,157,235,246,209,204,159,130,165,184,3,30,57,36,119,106,77,80,161,188,155,134,213,200,239,242,73,84,115,110,61,32,7,26,108,113,86,75,24,5,34,63,132,153,190,163,240,237,202,215,53,40,15,18,65,92,123,102,221,192,231,250,169,180,147,142,248,229,194,223,140,145,182,171,16,13,42,55,100,121,94,67,178,175,136,149,198,219,252,225,90,71,96,125,46,51,20,9,127,98,69,88,11,22,49,44,151,138,173,176,227,254,217,196,0,30,60,34,120,102,68,90,240,238,204,210,136,150,180,170,253,227,193,223,133,155,185,167,13,19,49,47,117,107,73,87,231,249,219,197,159,129,163,189,23,9,43,53,111,113,83,77,26,4,38,56,98,124,94,64,234,244,214,200,146,140,174,176,211,205,239,241,171,181,151,137,35,61,31,1,91,69,103,121,46,48,18,12,86,72,106,116,222,192,226,252,166,184,154,132,52,42,8,22,76,82,112,110,196,218,248,230,188,162,128,158,201,215,245,235,177,175,141,147,57,39,5,27,65,95,125,99,187,165,135,153,195,221,255,225,75,85,119,105,51,45,15,17,70,88,122,100,62,32,2,28,182,168,138,148,206,208,242,236,92,66,96,126,36,58,24,6,172,178,144,142,212,202,232,246,161,191,157,131,217,199,229,251,81,79,109,115,41,55,21,11,104,118,84,74,16,14,44,50,152,134,164,186,224,254,220,194,149,139,169,183,237,243,209,207,101,123,89,71,29,3,33,63,143,145,179,173,247,233,203,213,127,97,67,93,7,25,59,37,114,108,78,80,10,20,54,40,130,156,190,160,250,228,198,216,0,31,62,33,124,99,66,93,248,231,198,217,132,155,186,165,237,242,211,204,145,142,175,176,21,10,43,52,105,118,87,72,199,216,249,230,187,164,133,154,63,32,1,30,67,92,125,98,42,53,20,11,86,73,104,119,210,205,236,243,174,177,144,143,147,140,173,178,239,240,209,206,107,116,85,74,23,8,41,54,126,97,64,95,2,29,60,35,134,153,184,167,250,229,196,219,84,75,106,117,40,55,22,9,172,179,146,141,208,207,238,241,185,166,135,152,197,218,251,228,65,94,127,96,61,34,3,28,59,36,5,26,71,88,121,102,195,220,253,226,191,160,129,158,214,201,232,247,170,181,148,139,46,49,16,15,82,77,108,115,252,227,194,221,128,159,190,161,4,27,58,37,120,103,70,89,17,14,47,48,109,114,83,76,233,246,215,200,149,138,171,180,168,183,150,137,212,203,234,245,80,79,110,113,44,51,18,13,69,90,123,100,57,38,7,24,189,162,131,156,193,222,255,224,111,112,81,78,19,12,45,50,151,136,169,182,235,244,213,202,130,157,188,163,254,225,192,223,122,101,68,91,6,25,56,39,0,32,64,96,128,160,192,224,29,61,93,125,157,189,221,253,58,26,122,90,186,154,250,218,39,7,103,71,167,135,231,199,116,84,52,20,244,212,180,148,105,73,41,9,233,201,169,137,78,110,14,46,206,238,142,174,83,115,19,51,211,243,147,179,232,200,168,136,104,72,40,8,245,213,181,149,117,85,53,21,210,242,146,178,82,114,18,50,207,239,143,175,79,111,15,47,156,188,220,252,28,60,92,124,129,161,193,225,1,33,65,97,166,134,230,198,38,6,102,70,187,155,251,219,59,27,123,91,205,237,141,173,77,109,13,45,208,240,144,176,80,112,16,48,247,215,183,151,119,87,55,23,234,202,170,138,106,74,42,10,185,153,249,217,57,25,121,89,164,132,228,196,36,4,100,68,131,163,195,227,3,35,67,99,158,190,222,254,30,62,94,126,37,5,101,69,165,133,229,197,56,24,120,88,184,152,248,216,31,63,95,127,159,191,223,255,2,34,66,98,130,162,194,226,81,113,17,49,209,241,145,177,76,108,12,44,204,236,140,172,107,75,43,11,235,203,171,139,118,86,54,22,246,214,182,150,0,33,66,99,132,165,198,231,21,52,87,118,145,176,211,242,42,11,104,73,174,143,236,205,63,30,125,92,187,154,249,216,84,117,22,55,208,241,146,179,65,96,3,34,197,228,135,166,126,95,60,29,250,219,184,153,107,74,41,8,239,206,173,140,168,137,234,203,44,13,110,79,189,156,255,222,57,24,123,90,130,163,192,225,6,39,68,101,151,182,213,244,19,50,81,112,252,221,190,159,120,89,58,27,233,200,171,138,109,76,47,14,214,247,148,181,82,115,16,49,195,226,129,160,71,102,5,36,77,108,15,46,201,232,139,170,88,121,26,59,220,253,158,191,103,70,37,4,227,194,161,128,114,83,48,17,246,215,180,149,25,56,91,122,157,188,223,254,12,45,78,111,136,169,202,235,51,18,113,80,183,150,245,212,38,7,100,69,162,131,224,193,229,196,167,134,97,64,35,2,240,209,178,147,116,85,54,23,207,238,141,172,75,106,9,40,218,251,152,185,94,127,28,61,177,144,243,210,53,20,119,86,164,133,230,199,32,1,98,67,155,186,217,248,31,62,93,124,142,175,204,237,10,43,72,105,0,34,68,102,136,170,204,238,13,47,73,107,133,167,193,227,26,56,94,124,146,176,214,244,23,53,83,113,159,189,219,249,52,22,112,82,188,158,248,218,57,27,125,95,177,147,245,215,46,12,106,72,166,132,226,192,35,1,103,69,171,137,239,205,104,74,44,14,224,194,164,134,101,71,33,3,237,207,169,139,114,80,54,20,250,216,190,156,127,93,59,25,247,213,179,145,92,126,24,58,212,246,144,178,81,115,21,55,217,251,157,191,70,100,2,32,206,236,138,168,75,105,15,45,195,225,135,165,208,242,148,182,88,122,28,62,221,255,153,187,85,119,17,51,202,232,142,172,66,96,6,36,199,229,131,161,79,109,11,41,228,198,160,130,108,78,40,10,233,203,173,143,97,67,37,7,254,220,186,152,118,84,50,16,243,209,183,149,123,89,63,29,184,154,252,222,48,18,116,86,181,151,241,211,61,31,121,91,162,128,230,196,42,8,110,76,175,141,235,201,39,5,99,65,140,174,200,234,4,38,64,98,129,163,197,231,9,43,77,111,150,180,210,240,30,60,90,120,155,185,223,253,19,49,87,117,0,35,70,101,140,175,202,233,5,38,67,96,137,170,207,236,10,41,76,111,134,165,192,227,15,44,73,106,131,160,197,230,20,55,82,113,152,187,222,253,17,50,87,116,157,190,219,248,30,61,88,123,146,177,212,247,27,56,93,126,151,180,209,242,40,11,110,77,164,135,226,193,45,14,107,72,161,130,231,196,34,1,100,71,174,141,232,203,39,4,97,66,171,136,237,206,60,31,122,89,176,147,246,213,57,26,127,92,181,150,243,208,54,21,112,83,186,153,252,223,51,16,117,86,191,156,249,218,80,115,22,53,220,255,154,185,85,118,19,48,217,250,159,188,90,121,28,63,214,245,144,179,95,124,25,58,211,240,149,182,68,103,2,33,200,235,142,173,65,98,7,36,205,238,139,168,78,109,8,43,194,225,132,167,75,104,13,46,199,228,129,162,120,91,62,29,244,215,178,145,125,94,59,24,241,210,183,148,114,81,52,23,254,221,184,155,119,84,49,18,251,216,189,158,108,79,42,9,224,195,166,133,105,74,47,12,229,198,163,128,102,69,32,3,234,201,172,143,99,64,37,6,239,204,169,138,0,36,72,108,144,180,216,252,61,25,117,81,173,137,229,193,122,94,50,22,234,206,162,134,71,99,15,43,215,243,159,187,244,208,188,152,100,64,44,8,201,237,129,165,89,125,17,53,142,170,198,226,30,58,86,114,179,151,251,223,35,7,107,79,245,209,189,153,101,65,45,9,200,236,128,164,88,124,16,52,143,171,199,227,31,59,87,115,178,150,250,222,34,6,106,78,1,37,73,109,145,181,217,253,60,24,116,80,172,136,228,192,123,95,51,23,235,207,163,135,70,98,14,42,214,242,158,186,247,211,191,155,103,67,47,11,202,238,130,166,90,126,18,54,141,169,197,225,29,57,85,113,176,148,248,220,32,4,104,76,3,39,75,111,147,183,219,255,62,26,118,82,174,138,230,194,121,93,49,21,233,205,161,133,68,96,12,40,212,240,156,184,2,38,74,110,146,182,218,254,63,27,119,83,175,139,231,195,120,92,48,20,232,204,160,132,69,97,13,41,213,241,157,185,246,210,190,154,102,66,46,10,203,239,131,167,91,127,19,55,140,168,196,224,28,56,84,112,177,149,249,221,33,5,105,77,0,37,74,111,148,177,222,251,53,16,127,90,161,132,235,206,106,79,32,5,254,219,180,145,95,122,21,48,203,238,129,164,212,241,158,187,64,101,10,47,225,196,171,142,117,80,63,26,190,155,244,209,42,15,96,69,139,174,193,228,31,58,85,112,181,144,255,218,33,4,107,78,128,165,202,239,20,49,94,123,223,250,149,176,75,110,1,36,234,207,160,133,126,91,52,17,97,68,43,14,245,208,191,154,84,113,30,59,192,229,138,175,11,46,65,100,159,186,213,240,62,27,116,81,170,143,224,197,119,82,61,24,227,198,169,140,66,103,8,45,214,243,156,185,29,56,87,114,137,172,195,230,40,13,98,71,188,153,246,211,163,134,233,204,55,18,125,88,150,179,220,249,2,39,72,109,201,236,131,166,93,120,23,50,252,217,182,147,104,77,34,7,194,231,136,173,86,115,28,57,247,210,189,152,99,70,41,12,168,141,226,199,60,25,118,83,157,184,215,242,9,44,67,102,22,51,92,121,130,167,200,237,35,6,105,76,183,146,253,216,124,89,54,19,232,205,162,135,73,108,3,38,221,248,151,178,0,38,76,106,152,190,212,242,45,11,97,71,181,147,249,223,90,124,22,48,194,228,142,168,119,81,59,29,239,201,163,133,180,146,248,222,44,10,96,70,153,191,213,243,1,39,77,107,238,200,162,132,118,80,58,28,195,229,143,169,91,125,23,49,117,83,57,31,237,203,161,135,88,126,20,50,192,230,140,170,47,9,99,69,183,145,251,221,2,36,78,104,154,188,214,240,193,231,141,171,89,127,21,51,236,202,160,134,116,82,56,30,155,189,215,241,3,37,79,105,182,144,250,220,46,8,98,68,234,204,166,128,114,84,62,24,199,225,139,173,95,121,19,53,176,150,252,218,40,14,100,66,157,187,209,247,5,35,73,111,94,120,18,52,198,224,138,172,115,85,63,25,235,205,167,129,4,34,72,110,156,186,208,246,41,15,101,67,177,151,253,219,159,185,211,245,7,33,75,109,178,148,254,216,42,12,102,64,197,227,137,175,93,123,17,55,232,206,164,130,112,86,60,26,43,13,103,65,179,149,255,217,6,32,74,108,158,184,210,244,113,87,61,27,233,207,165,131,92,122,16,54,196,226,136,174,0,39,78,105,156,187,210,245,37,2,107,76,185,158,247,208,74,109,4,35,214,241,152,191,111,72,33,6,243,212,189,154,148,179,218,253,8,47,70,97,177,150,255,216,45,10,99,68,222,249,144,183,66,101,12,43,251,220,181,146,103,64,41,14,53,18,123,92,169,142,231,192,16,55,94,121,140,171,194,229,127,88,49,22,227,196,173,138,90,125,20,51,198,225,136,175,161,134,239,200,61,26,115,84,132,163,202,237,24,63,86,113,235,204,165,130,119,80,57,30,206,233,128,167,82,117,28,59,106,77,36,3,246,209,184,159,79,104,1,38,211,244,157,186,32,7,110,73,188,155,242,213,5,34,75,108,153,190,215,240,254,217,176,151,98,69,44,11,219,252,149,178,71,96,9,46,180,147,250,221,40,15,102,65,145,182,223,248,13,42,67,100,95,120,17,54,195,228,141,170,122,93,52,19,230,193,168,143,21,50,91,124,137,174,199,224,48,23,126,89,172,139,226,197,203,236,133,162,87,112,25,62,238,201,160,135,114,85,60,27,129,166,207,232,29,58,83,116,164,131,234,205,56,31,118,81,0,40,80,120,160,136,240,216,93,117,13,37,253,213,173,133,186,146,234,194,26,50,74,98,231,207,183,159,71,111,23,63,105,65,57,17,201,225,153,177,52,28,100,76,148,188,196,236,211,251,131,171,115,91,35,11,142,166,222,246,46,6,126,86,210,250,130,170,114,90,34,10,143,167,223,247,47,7,127,87,104,64,56,16,200,224,152,176,53,29,101,77,149,189,197,237,187,147,235,195,27,51,75,99,230,206,182,158,70,110,22,62,1,41,81,121,161,137,241,217,92,116,12,36,252,212,172,132,185,145,233,193,25,49,73,97,228,204,180,156,68,108,20,60,3,43,83,123,163,139,243,219,94,118,14,38,254,214,174,134,208,248,128,168,112,88,32,8,141,165,221,245,45,5,125,85,106,66,58,18,202,226,154,178,55,31,103,79,151,191,199,239,107,67,59,19,203,227,155,179,54,30,102,78,150,190,198,238,209,249,129,169,113,89,33,9,140,164,220,244,44,4,124,84,2,42,82,122,162,138,242,218,95,119,15,39,255,215,175,135,184,144,232,192,24,48,72,96,229,205,181,157,69,109,21,61,0,41,82,123,164,141,246,223,85,124,7,46,241,216,163,138,170,131,248,209,14,39,92,117,255,214,173,132,91,114,9,32,73,96,27,50,237,196,191,150,28,53,78,103,184,145,234,195,227,202,177,152,71,110,21,60,182,159,228,205,18,59,64,105,146,187,192,233,54,31,100,77,199,238,149,188,99,74,49,24,56,17,106,67,156,181,206,231,109,68,63,22,201,224,155,178,219,242,137,160,127,86,45,4,142,167,220,245,42,3,120,81,113,88,35,10,213,252,135,174,36,13,118,95,128,169,210,251,57,16,107,66,157,180,207,230,108,69,62,23,200,225,154,179,147,186,193,232,55,30,101,76,198,239,148,189,98,75,48,25,112,89,34,11,212,253,134,175,37,12,119,94,129,168,211,250,218,243,136,161,126,87,44,5,143,166,221,244,43,2,121,80,171,130,249,208,15,38,93,116,254,215,172,133,90,115,8,33,1,40,83,122,165,140,247,222,84,125,6,47,240,217,162,139,226,203,176,153,70,111,20,61,183,158,229,204,19,58,65,104,72,97,26,51,236,197,190,151,29,52,79,102,185,144,235,194,0,42,84,126,168,130,252,214,77,103,25,51,229,207,177,155,154,176,206,228,50,24,102,76,215,253,131,169,127,85,43,1,41,3,125,87,129,171,213,255,100,78,48,26,204,230,152,178,179,153,231,205,27,49,79,101,254,212,170,128,86,124,2,40,82,120,6,44,250,208,174,132,31,53,75,97,183,157,227,201,200,226,156,182,96,74,52,30,133,175,209,251,45,7,121,83,123,81,47,5,211,249,135,173,54,28,98,72,158,180,202,224,225,203,181,159,73,99,29,55,172,134,248,210,4,46,80,122,164,142,240,218,12,38,88,114,233,195,189,151,65,107,21,63,62,20,106,64,150,188,194,232,115,89,39,13,219,241,143,165,141,167,217,243,37,15,113,91,192,234,148,190,104,66,60,22,23,61,67,105,191,149,235,193,90,112,14,36,242,216,166,140,246,220,162,136,94,116,10,32,187,145,239,197,19,57,71,109,108,70,56,18,196,238,144,186,33,11,117,95,137,163,221,247,223,245,139,161,119,93,35,9,146,184,198,236,58,16,110,68,69,111,17,59,237,199,185,147,8,34,92,118,160,138,244,222,0,43,86,125,172,135,250,209,69,110,19,56,233,194,191,148,138,161,220,247,38,13,112,91,207,228,153,178,99,72,53,30,9,34,95,116,165,142,243,216,76,103,26,49,224,203,182,157,131,168,213,254,47,4,121,82,198,237,144,187,106,65,60,23,18,57,68,111,190,149,232,195,87,124,1,42,251,208,173,134,152,179,206,229,52,31,98,73,221,246,139,160,113,90,39,12,27,48,77,102,183,156,225,202,94,117,8,35,242,217,164,143,145,186,199,236,61,22,107,64,212,255,130,169,120,83,46,5,36,15,114,89,136,163,222,245,97,74,55,28,205,230,155,176,174,133,248,211,2,41,84,127,235,192,189,150,71,108,17,58,45,6,123,80,129,170,215,252,104,67,62,21,196,239,146,185,167,140,241,218,11,32,93,118,226,201,180,159,78,101,24,51,54,29,96,75,154,177,204,231,115,88,37,14,223,244,137,162,188,151,234,193,16,59,70,109,249,210,175,132,85,126,3,40,63,20,105,66,147,184,197,238,122,81,44,7,214,253,128,171,181,158,227,200,25,50,79,100,240,219,166,141,92,119,10,33,0,44,88,116,176,156,232,196,125,81,37,9,205,225,149,185,250,214,162,142,74,102,18,62,135,171,223,243,55,27,111,67,233,197,177,157,89,117,1,45,148,184,204,224,36,8,124,80,19,63,75,103,163,143,251,215,110,66,54,26,222,242,134,170,207,227,151,187,127,83,39,11,178,158,234,198,2,46,90,118,53,25,109,65,133,169,221,241,72,100,16,60,248,212,160,140,38,10,126,82,150,186,206,226,91,119,3,47,235,199,179,159,220,240,132,168,108,64,52,24,161,141,249,213,17,61,73,101,131,175,219,247,51,31,107,71,254,210,166,138,78,98,22,58,121,85,33,13,201,229,145,189,4,40,92,112,180,152,236,192,106,70,50,30,218,246,130,174,23,59,79,99,167,139,255,211,144,188,200,228,32,12,120,84,237,193,181,153,93,113,5,41,76,96,20,56,252,208,164,136,49,29,105,69,129,173,217,245,182,154,238,194,6,42,94,114,203,231,147,191,123,87,35,15,165,137,253,209,21,57,77,97,216,244,128,172,104,68,48,28,95,115,7,43,239,195,183,155,34,14,122,86,146,190,202,230,0,45,90,119,180,153,238,195,117,88,47,2,193,236,155,182,234,199,176,157,94,115,4,41,159,178,197,232,43,6,113,92,201,228,147,190,125,80,39,10,188,145,230,203,8,37,82,127,35,14,121,84,151,186,205,224,86,123,12,33,226,207,184,149,143,162,213,248,59,22,97,76,250,215,160,141,78,99,20,57,101,72,63,18,209,252,139,166,16,61,74,103,164,137,254,211,70,107,28,49,242,223,168,133,51,30,105,68,135,170,221,240,172,129,246,219,24,53,66,111,217,244,131,174,109,64,55,26,3,46,89,116,183,154,237,192,118,91,44,1,194,239,152,181,233,196,179,158,93,112,7,42,156,177,198,235,40,5,114,95,202,231,144,189,126,83,36,9,191,146,229,200,11,38,81,124,32,13,122,87,148,185,206,227,85,120,15,34,225,204,187,150,140,161,214,251,56,21,98,79,249,212,163,142,77,96,23,58,102,75,60,17,210,255,136,165,19,62,73,100,167,138,253,208,69,104,31,50,241,220,171,134,48,29,106,71,132,169,222,243,175,130,245,216,27,54,65,108,218,247,128,173,110,67,52,25,0,46,92,114,184,150,228,202,109,67,49,31,213,251,137,167,218,244,134,168,98,76,62,16,183,153,235,197,15,33,83,125,169,135,245,219,17,63,77,99,196,234,152,182,124,82,32,14,115,93,47,1,203,229,151,185,30,48,66,108,166,136,250,212,79,97,19,61,247,217,171,133,34,12,126,80,154,180,198,232,149,187,201,231,45,3,113,95,248,214,164,138,64,110,28,50,230,200,186,148,94,112,2,44,139,165,215,249,51,29,111,65,60,18,96,78,132,170,216,246,81,127,13,35,233,199,181,155,158,176,194,236,38,8,122,84,243,221,175,129,75,101,23,57,68,106,24,54,252,210,160,142,41,7,117,91,145,191,205,227,55,25,107,69,143,161,211,253,90,116,6,40,226,204,190,144,237,195,177,159,85,123,9,39,128,174,220,242,56,22,100,74,209,255,141,163,105,71,53,27,188,146,224,206,4,42,88,118,11,37,87,121,179,157,239,193,102,72,58,20,222,240,130,172,120,86,36,10,192,238,156,178,21,59,73,103,173,131,241,223,162,140,254,208,26,52,70,104,207,225,147,189,119,89,43,5,0,47,94,113,188,147,226,205,101,74,59,20,217,246,135,168,202,229,148,187,118,89,40,7,175,128,241,222,19,60,77,98,137,166,215,248,53,26,107,68,236,195,178,157,80,127,14,33,67,108,29,50,255,208,161,142,38,9,120,87,154,181,196,235,15,32,81,126,179,156,237,194,106,69,52,27,214,249,136,167,197,234,155,180,121,86,39,8,160,143,254,209,28,51,66,109,134,169,216,247,58,21,100,75,227,204,189,146,95,112,1,46,76,99,18,61,240,223,174,129,41,6,119,88,149,186,203,228,30,49,64,111,162,141,252,211,123,84,37,10,199,232,153,182,212,251,138,165,104,71,54,25,177,158,239,192,13,34,83,124,151,184,201,230,43,4,117,90,242,221,172,131,78,97,16,63,93,114,3,44,225,206,191,144,56,23,102,73,132,171,218,245,17,62,79,96,173,130,243,220,116,91,42,5,200,231,150,185,219,244,133,170,103,72,57,22,190,145,224,207,2,45,92,115,152,183,198,233,36,11,122,85,253,210,163,140,65,110,31,48,82,125,12,35,238,193,176,159,55,24,105,70,139,164,213,250,0,48,96,80,192,240,160,144,157,173,253,205,93,109,61,13,39,23,71,119,231,215,135,183,186,138,218,234,122,74,26,42,78,126,46,30,142,190,238,222,211,227,179,131,19,35,115,67,105,89,9,57,169,153,201,249,244,196,148,164,52,4,84,100,156,172,252,204,92,108,60,12,1,49,97,81,193,241,161,145,187,139,219,235,123,75,27,43,38,22,70,118,230,214,134,182,210,226,178,130,18,34,114,66,79,127,47,31,143,191,239,223,245,197,149,165,53,5,85,101,104,88,8,56,168,152,200,248,37,21,69,117,229,213,133,181,184,136,216,232,120,72,24,40,2,50,98,82,194,242,162,146,159,175,255,207,95,111,63,15,107,91,11,59,171,155,203,251,246,198,150,166,54,6,86,102,76,124,44,28,140,188,236,220,209,225,177,129,17,33,113,65,185,137,217,233,121,73,25,41,36,20,68,116,228,212,132,180,158,174,254,206,94,110,62,14,3,51,99,83,195,243,163,147,247,199,151,167,55,7,87,103,106,90,10,58,170,154,202,250,208,224,176,128,16,32,112,64,77,125,45,29,141,189,237,221,0,49,98,83,196,245,166,151,149,164,247,198,81,96,51,2,55,6,85,100,243,194,145,160,162,147,192,241,102,87,4,53,110,95,12,61,170,155,200,249,251,202,153,168,63,14,93,108,89,104,59,10,157,172,255,206,204,253,174,159,8,57,106,91,220,237,190,143,24,41,122,75,73,120,43,26,141,188,239,222,235,218,137,184,47,30,77,124,126,79,28,45,186,139,216,233,178,131,208,225,118,71,20,37,39,22,69,116,227,210,129,176,133,180,231,214,65,112,35,18,16,33,114,67,212,229,182,135,165,148,199,246,97,80,3,50,48,1,82,99,244,197,150,167,146,163,240,193,86,103,52,5,7,54,101,84,195,242,161,144,203,250,169,152,15,62,109,92,94,111,60,13,154,171,248,201,252,205,158,175,56,9,90,107,105,88,11,58,173,156,207,254,121,72,27,42,189,140,223,238,236,221,142,191,40,25,74,123,78,127,44,29,138,187,232,217,219,234,185,136,31,46,125,76,23,38,117,68,211,226,177,128,130,179,224,209,70,119,36,21,32,17,66,115,228,213,134,183,181,132,215,230,113,64,19,34,0,50,100,86,200,250,172,158,141,191,233,219,69,119,33,19,7,53,99,81,207,253,171,153,138,184,238,220,66,112,38,20,14,60,106,88,198,244,162,144,131,177,231,213,75,121,47,29,9,59,109,95,193,243,165,151,132,182,224,210,76,126,40,26,28,46,120,74,212,230,176,130,145,163,245,199,89,107,61,15,27,41,127,77,211,225,183,133,150,164,242,192,94,108,58,8,18,32,118,68,218,232,190,140,159,173,251,201,87,101,51,1,21,39,113,67,221,239,185,139,152,170,252,206,80,98,52,6,56,10,92,110,240,194,148,166,181,135,209,227,125,79,25,43,63,13,91,105,247,197,147,161,178,128,214,228,122,72,30,44,54,4,82,96,254,204,154,168,187,137,223,237,115,65,23,37,49,3,85,103,249,203,157,175,188,142,216,234,116,70,16,34,36,22,64,114,236,222,136,186,169,155,205,255,97,83,5,55,35,17,71,117,235,217,143,189,174,156,202,248,102,84,2,48,42,24,78,124,226,208,134,180,167,149,195,241,111,93,11,57,45,31,73,123,229,215,129,179,160,146,196,246,104,90,12,62,0,51,102,85,204,255,170,153,133,182,227,208,73,122,47,28,23,36,113,66,219,232,189,142,146,161,244,199,94,109,56,11,46,29,72,123,226,209,132,183,171,152,205,254,103,84,1,50,57,10,95,108,245,198,147,160,188,143,218,233,112,67,22,37,92,111,58,9,144,163,246,197,217,234,191,140,21,38,115,64,75,120,45,30,135,180,225,210,206,253,168,155,2,49,100,87,114,65,20,39,190,141,216,235,247,196,145,162,59,8,93,110,101,86,3,48,169,154,207,252,224,211,134,181,44,31,74,121,184,139,222,237,116,71,18,33,61,14,91,104,241,194,151,164,175,156,201,250,99,80,5,54,42,25,76,127,230,213,128,179,150,165,240,195,90,105,60,15,19,32,117,70,223,236,185,138,129,178,231,212,77,126,43,24,4,55,98,81,200,251,174,157,228,215,130,177,40,27,78,125,97,82,7,52,173,158,203,248,243,192,149,166,63,12,89,106,118,69,16,35,186,137,220,239,202,249,172,159,6,53,96,83,79,124,41,26,131,176,229,214,221,238,187,136,17,34,119,68,88,107,62,13,148,167,242,193,0,52,104,92,208,228,184,140,189,137,213,225,109,89,5,49,103,83,15,59,183,131,223,235,218,238,178,134,10,62,98,86,206,250,166,146,30,42,118,66,115,71,27,47,163,151,203,255,169,157,193,245,121,77,17,37,20,32,124,72,196,240,172,152,129,181,233,221,81,101,57,13,60,8,84,96,236,216,132,176,230,210,142,186,54,2,94,106,91,111,51,7,139,191,227,215,79,123,39,19,159,171,247,195,242,198,154,174,34,22,74,126,40,28,64,116,248,204,144,164,149,161,253,201,69,113,45,25,31,43,119,67,207,251,167,147,162,150,202,254,114,70,26,46,120,76,16,36,168,156,192,244,197,241,173,153,21,33,125,73,209,229,185,141,1,53,105,93,108,88,4,48,188,136,212,224,182,130,222,234,102,82,14,58,11,63,99,87,219,239,179,135,158,170,246,194,78,122,38,18,35,23,75,127,243,199,155,175,249,205,145,165,41,29,65,117,68,112,44,24,148,160,252,200,80,100,56,12,128,180,232,220,237,217,133,177,61,9,85,97,55,3,95,107,231,211,143,187,138,190,226,214,90,110,50,6,0,53,106,95,212,225,190,139,181,128,223,234,97,84,11,62,119,66,29,40,163,150,201,252,194,247,168,157,22,35,124,73,238,219,132,177,58,15,80,101,91,110,49,4,143,186,229,208,153,172,243,198,77,120,39,18,44,25,70,115,248,205,146,167,193,244,171,158,21,32,127,74,116,65,30,43,160,149,202,255,182,131,220,233,98,87,8,61,3,54,105,92,215,226,189,136,47,26,69,112,251,206,145,164,154,175,240,197,78,123,36,17,88,109,50,7,140,185,230,211,237,216,135,178,57,12,83,102,159,170,245,192,75,126,33,20,42,31,64,117,254,203,148,161,232,221,130,183,60,9,86,99,93,104,55,2,137,188,227,214,113,68,27,46,165,144,207,250,196,241,174,155,16,37,122,79,6,51,108,89,210,231,184,141,179,134,217,236,103,82,13,56,94,107,52,1,138,191,224,213,235,222,129,180,63,10,85,96,41,28,67,118,253,200,151,162,156,169,246,195,72,125,34,23,176,133,218,239,100,81,14,59,5,48,111,90,209,228,187,142,199,242,173,152,19,38,121,76,114,71,24,45,166,147,204,249,0,54,108,90,216,238,180,130,173,155,193,247,117,67,25,47,71,113,43,29,159,169,243,197,234,220,134,176,50,4,94,104,142,184,226,212,86,96,58,12,35,21,79,121,251,205,151,161,201,255,165,147,17,39,125,75,100,82,8,62,188,138,208,230,1,55,109,91,217,239,181,131,172,154,192,246,116,66,24,46,70,112,42,28,158,168,242,196,235,221,135,177,51,5,95,105,143,185,227,213,87,97,59,13,34,20,78,120,250,204,150,160,200,254,164,146,16,38,124,74,101,83,9,63,189,139,209,231,2,52,110,88,218,236,182,128,175,153,195,245,119,65,27,45,69,115,41,31,157,171,241,199,232,222,132,178,48,6,92,106,140,186,224,214,84,98,56,14,33,23,77,123,249,207,149,163,203,253,167,145,19,37,127,73,102,80,10,60,190,136,210,228,3,53,111,89,219,237,183,129,174,152,194,244,118,64,26,44,68,114,40,30,156,170,240,198,233,223,133,179,49,7,93,107,141,187,225,215,85,99,57,15,32,22,76,122,248,206,148,162,202,252,166,144,18,36,126,72,103,81,11,61,191,137,211,229,0,55,110,89,220,235,178,133,165,146,203,252,121,78,23,32,87,96,57,14,139,188,229,210,242,197,156,171,46,25,64,119,174,153,192,247,114,69,28,43,11,60,101,82,215,224,185,142,249,206,151,160,37,18,75,124,92,107,50,5,128,183,238,217,65,118,47,24,157,170,243,196,228,211,138,189,56,15,86,97,22,33,120,79,202,253,164,147,179,132,221,234,111,88,1,54,239,216,129,182,51,4,93,106,74,125,36,19,150,161,248,207,184,143,214,225,100,83,10,61,29,42,115,68,193,246,175,152,130,181,236,219,94,105,48,7,39,16,73,126,251,204,149,162,213,226,187,140,9,62,103,80,112,71,30,41,172,155,194,245,44,27,66,117,240,199,158,169,137,190,231,208,85,98,59,12,123,76,21,34,167,144,201,254,222,233,176,135,2,53,108,91,195,244,173,154,31,40,113,70,102,81,8,63,186,141,212,227,148,163,250,205,72,127,38,17,49,6,95,104,237,218,131,180,109,90,3,52,177,134,223,232,200,255,166,145,20,35,122,77,58,13,84,99,230,209,136,191,159,168,241,198,67,116,45,26,0,56,112,72,224,216,144,168,221,229,173,149,61,5,77,117,167,159,215,239,71,127,55,15,122,66,10,50,154,162,234,210,83,107,35,27,179,139,195,251,142,182,254,198,110,86,30,38,244,204,132,188,20,44,100,92,41,17,89,97,201,241,185,129,166,158,214,238,70,126,54,14,123,67,11,51,155,163,235,211,1,57,113,73,225,217,145,169,220,228,172,148,60,4,76,116,245,205,133,189,21,45,101,93,40,16,88,96,200,240,184,128,82,106,34,26,178,138,194,250,143,183,255,199,111,87,31,39,81,105,33,25,177,137,193,249,140,180,252,196,108,84,28,36,246,206,134,190,22,46,102,94,43,19,91,99,203,243,187,131,2,58,114,74,226,218,146,170,223,231,175,151,63,7,79,119,165,157,213,237,69,125,53,13,120,64,8,48,152,160,232,208,247,207,135,191,23,47,103,95,42,18,90,98,202,242,186,130,80,104,32,24,176,136,192,248,141,181,253,197,109,85,29,37,164,156,212,236,68,124,52,12,121,65,9,49,153,161,233,209,3,59,115,75,227,219,147,171,222,230,174,150,62,6,78,118,0,57,114,75,228,221,150,175,213,236,167,158,49,8,67,122,183,142,197,252,83,106,33,24,98,91,16,41,134,191,244,205,115,74,1,56,151,174,229,220,166,159,212,237,66,123,48,9,196,253,182,143,32,25,82,107,17,40,99,90,245,204,135,190,230,223,148,173,2,59,112,73,51,10,65,120,215,238,165,156,81,104,35,26,181,140,199,254,132,189,246,207,96,89,18,43,149,172,231,222,113,72,3,58,64,121,50,11,164,157,214,239,34,27,80,105,198,255,180,141,247,206,133,188,19,42,97,88,209,232,163,154,53,12,71,126,4,61,118,79,224,217,146,171,102,95,20,45,130,187,240,201,179,138,193,248,87,110,37,28,162,155,208,233,70,127,52,13,119,78,5,60,147,170,225,216,21,44,103,94,241,200,131,186,192,249,178,139,36,29,86,111,55,14,69,124,211,234,161,152,226,219,144,169,6,63,116,77,128,185,242,203,100,93,22,47,85,108,39,30,177,136,195,250,68,125,54,15,160,153,210,235,145,168,227,218,117,76,7,62,243,202,129,184,23,46,101,92,38,31,84,109,194,251,176,137,0,58,116,78,232,210,156,166,205,247,185,131,37,31,81,107,135,189,243,201,111,85,27,33,74,112,62,4,162,152,214,236,19,41,103,93,251,193,143,181,222,228,170,144,54,12,66,120,148,174,224,218,124,70,8,50,89,99,45,23,177,139,197,255,38,28,82,104,206,244,186,128,235,209,159,165,3,57,119,77,161,155,213,239,73,115,61,7,108,86,24,34,132,190,240,202,53,15,65,123,221,231,169,147,248,194,140,182,16,42,100,94,178,136,198,252,90,96,46,20,127,69,11,49,151,173,227,217,76,118,56,2,164,158,208,234,129,187,245,207,105,83,29,39,203,241,191,133,35,25,87,109,6,60,114,72,238,212,154,160,95,101,43,17,183,141,195,249,146,168,230,220,122,64,14,52,216,226,172,150,48,10,68,126,21,47,97,91,253,199,137,179,106,80,30,36,130,184,246,204,167,157,211,233,79,117,59,1,237,215,153,163,5,63,113,75,32,26,84,110,200,242,188,134,121,67,13,55,145,171,229,223,180,142,192,250,92,102,40,18,254,196,138,176,22,44,98,88,51,9,71,125,219,225,175,149,0,59,118,77,236,215,154,161,197,254,179,136,41,18,95,100,151,172,225,218,123,64,13,54,82,105,36,31,190,133,200,243,51,8,69,126,223,228,169,146,246,205,128,187,26,33,108,87,164,159,210,233,72,115,62,5,97,90,23,44,141,182,251,192,102,93,16,43,138,177,252,199,163,152,213,238,79,116,57,2,241,202,135,188,29,38,107,80,52,15,66,121,216,227,174,149,85,110,35,24,185,130,207,244,144,171,230,221,124,71,10,49,194,249,180,143,46,21,88,99,7,60,113,74,235,208,157,166,204,247,186,129,32,27,86,109,9,50,127,68,229,222,147,168,91,96,45,22,183,140,193,250,158,165,232,211,114,73,4,63,255,196,137,178,19,40,101,94,58,1,76,119,214,237,160,155,104,83,30,37,132,191,242,201,173,150,219,224,65,122,55,12,170,145,220,231,70,125,48,11,111,84,25,34,131,184,245,206,61,6,75,112,209,234,167,156,248,195,142,181,20,47,98,89,153,162,239,212,117,78,3,56,92,103,42,17,176,139,198,253,14,53,120,67,226,217,148,175,203,240,189,134,39,28,81,106,0,60,120,68,240,204,136,180,253,193,133,185,13,49,117,73,231,219,159,163,23,43,111,83,26,38,98,94,234,214,146,174,211,239,171,151,35,31,91,103,46,18,86,106,222,226,166,154,52,8,76,112,196,248,188,128,201,245,177,141,57,5,65,125,187,135,195,255,75,119,51,15,70,122,62,2,182,138,206,242,92,96,36,24,172,144,212,232,161,157,217,229,81,109,41,21,104,84,16,44,152,164,224,220,149,169,237,209,101,89,29,33,143,179,247,203,127,67,7,59,114,78,10,54,130,190,250,198,107,87,19,47,155,167,227,223,150,170,238,210,102,90,30,34,140,176,244,200,124,64,4,56,113,77,9,53,129,189,249,197,184,132,192,252,72,116,48,12,69,121,61,1,181,137,205,241,95,99,39,27,175,147,215,235,162,158,218,230,82,110,42,22,208,236,168,148,32,28,88,100,45,17,85,105,221,225,165,153,55,11,79,115,199,251,191,131,202,246,178,142,58,6,66,126,3,63,123,71,243,207,139,183,254,194,134,186,14,50,118,74,228,216,156,160,20,40,108,80,25,37,97,93,233,213,145,173,0,61,122,71,244,201,142,179,245,200,143,178,1,60,123,70,247,202,141,176,3,62,121,68,2,63,120,69,246,203,140,177,243,206,137,180,7,58,125,64,6,59,124,65,242,207,136,181,4,57,126,67,240,205,138,183,241,204,139,182,5,56,127,66,251,198,129,188,15,50,117,72,14,51,116,73,250,199,128,189,12,49,118,75,248,197,130,191,249,196,131,190,13,48,119,74,8,53,114,79,252,193,134,187,253,192,135,186,9,52,115,78,255,194,133,184,11,54,113,76,10,55,112,77,254,195,132,185,235,214,145,172,31,34,101,88,30,35,100,89,234,215,144,173,28,33,102,91,232,213,146,175,233,212,147,174,29,32,103,90,24,37,98,95,236,209,150,171,237,208,151,170,25,36,99,94,239,210,149,168,27,38,97,92,26,39,96,93,238,211,148,169,16,45,106,87,228,217,158,163,229,216,159,162,17,44,107,86,231,218,157,160,19,46,105,84,18,47,104,85,230,219,156,161,227,222,153,164,23,42,109,80,22,43,108,81,226,223,152,165,20,41,110,83,224,221,154,167,225,220,155,166,21,40,111,82,0,62,124,66,248,198,132,186,237,211,145,175,21,43,105,87,199,249,187,133,63,1,67,125,42,20,86,104,210,236,174,144,147,173,239,209,107,85,23,41,126,64,2,60,134,184,250,196,84,106,40,22,172,146,208,238,185,135,197,251,65,127,61,3,59,5,71,121,195,253,191,129,214,232,170,148,46,16,82,108,252,194,128,190,4,58,120,70,17,47,109,83,233,215,149,171,168,150,212,234,80,110,44,18,69,123,57,7,189,131,193,255,111,81,19,45,151,169,235,213,130,188,254,192,122,68,6,56,118,72,10,52,142,176,242,204,155,165,231,217,99,93,31,33,177,143,205,243,73,119,53,11,92,98,32,30,164,154,216,230,229,219,153,167,29,35,97,95,8,54,116,74,240,206,140,178,34,28,94,96,218,228,166,152,207,241,179,141,55,9,75,117,77,115,49,15,181,139,201,247,160,158,220,226,88,102,36,26,138,180,246,200,114,76,14,48,103,89,27,37,159,161,227,221,222,224,162,156,38,24,90,100,51,13,79,113,203,245,183,137,25,39,101,91,225,223,157,163,244,202,136,182,12,50,112,78,0,63,126,65,252,195,130,189,229,218,155,164,25,38,103,88,215,232,169,150,43,20,85,106,50,13,76,115,206,241,176,143,179,140,205,242,79,112,49,14,86,105,40,23,170,149,212,235,100,91,26,37,152,167,230,217,129,190,255,192,125,66,3,60,123,68,5,58,135,184,249,198,158,161,224,223,98,93,28,35,172,147,210,237,80,111,46,17,73,118,55,8,181,138,203,244,200,247,182,137,52,11,74,117,45,18,83,108,209,238,175,144,31,32,97,94,227,220,157,162,250,197,132,187,6,57,120,71,246,201,136,183,10,53,116,75,19,44,109,82,239,208,145,174,33,30,95,96,221,226,163,156,196,251,186,133,56,7,70,121,69,122,59,4,185,134,199,248,160,159,222,225,92,99,34,29,146,173,236,211,110,81,16,47,119,72,9,54,139,180,245,202,141,178,243,204,113,78,15,48,104,87,22,41,148,171,234,213,90,101,36,27,166,153,216,231,191,128,193,254,67,124,61,2,62,1,64,127,194,253,188,131,219,228,165,154,39,24,89,102,233,214,151,168,21,42,107,84,12,51,114,77,240,207,142,177,0,64,128,192,29,93,157,221,58,122,186,250,39,103,167,231,116,52,244,180,105,41,233,169,78,14,206,142,83,19,211,147,232,168,104,40,245,181,117,53,210,146,82,18,207,143,79,15,156,220,28,92,129,193,1,65,166,230,38,102,187,251,59,123,205,141,77,13,208,144,80,16,247,183,119,55,234,170,106,42,185,249,57,121,164,228,36,100,131,195,3,67,158,222,30,94,37,101,165,229,56,120,184,248,31,95,159,223,2,66,130,194,81,17,209,145,76,12,204,140,107,43,235,171,118,54,246,182,135,199,7,71,154,218,26,90,189,253,61,125,160,224,32,96,243,179,115,51,238,174,110,46,201,137,73,9,212,148,84,20,111,47,239,175,114,50,242,178,85,21,213,149,72,8,200,136,27,91,155,219,6,70,134,198,33,97,161,225,60,124,188,252,74,10,202,138,87,23,215,151,112,48,240,176,109,45,237,173,62,126,190,254,35,99,163,227,4,68,132,196,25,89,153,217,162,226,34,98,191,255,63,127,152,216,24,88,133,197,5,69,214,150,86,22,203,139,75,11,236,172,108,44,241,177,113,49,0,65,130,195,25,88,155,218,50,115,176,241,43,106,169,232,100,37,230,167,125,60,255,190,86,23,212,149,79,14,205,140,200,137,74,11,209,144,83,18,250,187,120,57,227,162,97,32,172,237,46,111,181,244,55,118,158,223,28,93,135,198,5,68,141,204,15,78,148,213,22,87,191,254,61,124,166,231,36,101,233,168,107,42,240,177,114,51,219,154,89,24,194,131,64,1,69,4,199,134,92,29,222,159,119,54,245,180,110,47,236,173,33,96,163,226,56,121,186,251,19,82,145,208,10,75,136,201,7,70,133,196,30,95,156,221,53,116,183,246,44,109,174,239,99,34,225,160,122,59,248,185,81,16,211,146,72,9,202,139,207,142,77,12,214,151,84,21,253,188,127,62,228,165,102,39,171,234,41,104,178,243,48,113,153,216,27,90,128,193,2,67,138,203,8,73,147,210,17,80,184,249,58,123,161,224,35,98,238,175,108,45,247,182,117,52,220,157,94,31,197,132,71,6,66,3,192,129,91,26,217,152,112,49,242,179,105,40,235,170,38,103,164,229,63,126,189,252,20,85,150,215,13,76,143,206,0,66,132,198,21,87,145,211,42,104,174,236,63,125,187,249,84,22,208,146,65,3,197,135,126,60,250,184,107,41,239,173,168,234,44,110,189,255,57,123,130,192,6,68,151,213,19,81,252,190,120,58,233,171,109,47,214,148,82,16,195,129,71,5,77,15,201,139,88,26,220,158,103,37,227,161,114,48,246,180,25,91,157,223,12,78,136,202,51,113,183,245,38,100,162,224,229,167,97,35,240,178,116,54,207,141,75,9,218,152,94,28,177,243,53,119,164,230,32,98,155,217,31,93,142,204,10,72,154,216,30,92,143,205,11,73,176,242,52,118,165,231,33,99,206,140,74,8,219,153,95,29,228,166,96,34,241,179,117,55,50,112,182,244,39,101,163,225,24,90,156,222,13,79,137,203,102,36,226,160,115,49,247,181,76,14,200,138,89,27,221,159,215,149,83,17,194,128,70,4,253,191,121,59,232,170,108,46,131,193,7,69,150,212,18,80,169,235,45,111,188,254,56,122,127,61,251,185,106,40,238,172,85,23,209,147,64,2,196,134,43,105,175,237,62,124,186,248,1,67,133,199,20,86,144,210,0,67,134,197,17,82,151,212,34,97,164,231,51,112,181,246,68,7,194,129,85,22,211,144,102,37,224,163,119,52,241,178,136,203,14,77,153,218,31,92,170,233,44,111,187,248,61,126,204,143,74,9,221,158,91,24,238,173,104,43,255,188,121,58,13,78,139,200,28,95,154,217,47,108,169,234,62,125,184,251,73,10,207,140,88,27,222,157,107,40,237,174,122,57,252,191,133,198,3,64,148,215,18,81,167,228,33,98,182,245,48,115,193,130,71,4,208,147,86,21,227,160,101,38,242,177,116,55,26,89,156,223,11,72,141,206,56,123,190,253,41,106,175,236,94,29,216,155,79,12,201,138,124,63,250,185,109,46,235,168,146,209,20,87,131,192,5,70,176,243,54,117,161,226,39,100,214,149,80,19,199,132,65,2,244,183,114,49,229,166,99,32,23,84,145,210,6,69,128,195,53,118,179,240,36,103,162,225,83,16,213,150,66,1,196,135,113,50,247,180,96,35,230,165,159,220,25,90,142,205,8,75,189,254,59,120,172,239,42,105,219,152,93,30,202,137,76,15,249,186,127,60,232,171,110,45,0,68,136,204,13,73,133,193,26,94,146,214,23,83,159,219,52,112,188,248,57,125,177,245,46,106,166,226,35,103,171,239,104,44,224,164,101,33,237,169,114,54,250,190,127,59,247,179,92,24,212,144,81,21,217,157,70,2,206,138,75,15,195,135,208,148,88,28,221,153,85,17,202,142,66,6,199,131,79,11,228,160,108,40,233,173,97,37,254,186,118,50,243,183,123,63,184,252,48,116,181,241,61,121,162,230,42,110,175,235,39,99,140,200,4,64,129,197,9,77,150,210,30,90,155,223,19,87,189,249,53,113,176,244,56,124,167,227,47,107,170,238,34,102,137,205,1,69,132,192,12,72,147,215,27,95,158,218,22,82,213,145,93,25,216,156,80,20,207,139,71,3,194,134,74,14,225,165,105,45,236,168,100,32,251,191,115,55,246,178,126,58,109,41,229,161,96,36,232,172,119,51,255,187,122,62,242,182,89,29,209,149,84,16,220,152,67,7,203,143,78,10,198,130,5,65,141,201,8,76,128,196,31,91,151,211,18,86,154,222,49,117,185,253,60,120,180,240,43,111,163,231,38,98,174,234,0,69,138,207,9,76,131,198,18,87,152,221,27,94,145,212,36,97,174,235,45,104,167,226,54,115,188,249,63,122,181,240,72,13,194,135,65,4,203,142,90,31,208,149,83,22,217,156,108,41,230,163,101,32,239,170,126,59,244,177,119,50,253,184,144,213,26,95,153,220,19,86,130,199,8,77,139,206,1,68,180,241,62,123,189,248,55,114,166,227,44,105,175,234,37,96,216,157,82,23,209,148,91,30,202,143,64,5,195,134,73,12,252,185,118,51,245,176,127,58,238,171,100,33,231,162,109,40,61,120,183,242,52,113,190,251,47,106,165,224,38,99,172,233,25,92,147,214,16,85,154,223,11,78,129,196,2,71,136,205,117,48,255,186,124,57,246,179,103,34,237,168,110,43,228,161,81,20,219,158,88,29,210,151,67,6,201,140,74,15,192,133,173,232,39,98,164,225,46,107,191,250,53,112,182,243,60,121,137,204,3,70,128,197,10,79,155,222,17,84,146,215,24,93,229,160,111,42,236,169,102,35,247,178,125,56,254,187,116,49,193,132,75,14,200,141,66,7,211,150,89,28,218,159,80,21,0,70,140,202,5,67,137,207,10,76,134,192,15,73,131,197,20,82,152,222,17,87,157,219,30,88,146,212,27,93,151,209,40,110,164,226,45,107,161,231,34,100,174,232,39,97,171,237,60,122,176,246,57,127,181,243,54,112,186,252,51,117,191,249,80,22,220,154,85,19,217,159,90,28,214,144,95,25,211,149,68,2,200,142,65,7,205,139,78,8,194,132,75,13,199,129,120,62,244,178,125,59,241,183,114,52,254,184,119,49,251,189,108,42,224,166,105,47,229,163,102,32,234,172,99,37,239,169,160,230,44,106,165,227,41,111,170,236,38,96,175,233,35,101,180,242,56,126,177,247,61,123,190,248,50,116,187,253,55,113,136,206,4,66,141,203,1,71,130,196,14,72,135,193,11,77,156,218,16,86,153,223,21,83,150,208,26,92,147,213,31,89,240,182,124,58,245,179,121,63,250,188,118,48,255,185,115,53,228,162,104,46,225,167,109,43,238,168,98,36,235,173,103,33,216,158,84,18,221,155,81,23,210,148,94,24,215,145,91,29,204,138,64,6,201,143,69,3,198,128,74,12,195,133,79,9,0,71,142,201,1,70,143,200,2,69,140,203,3,68,141,202,4,67,138,205,5,66,139,204,6,65,136,207,7,64,137,206,8,79,134,193,9,78,135,192,10,77,132,195,11,76,133,194,12,75,130,197,13,74,131,196,14,73,128,199,15,72,129,198,16,87,158,217,17,86,159,216,18,85,156,219,19,84,157,218,20,83,154,221,21,82,155,220,22,81,152,223,23,80,153,222,24,95,150,209,25,94,151,208,26,93,148,211,27,92,149,210,28,91,146,213,29,90,147,212,30,89,144,215,31,88,145,214,32,103,174,233,33,102,175,232,34,101,172,235,35,100,173,234,36,99,170,237,37,98,171,236,38,97,168,239,39,96,169,238,40,111,166,225,41,110,167,224,42,109,164,227,43,108,165,226,44,107,162,229,45,106,163,228,46,105,160,231,47,104,161,230,48,119,190,249,49,118,191,248,50,117,188,251,51,116,189,250,52,115,186,253,53,114,187,252,54,113,184,255,55,112,185,254,56,127,182,241,57,126,183,240,58,125,180,243,59,124,181,242,60,123,178,245,61,122,179,244,62,121,176,247,63,120,177,246,0,72,144,216,61,117,173,229,122,50,234,162,71,15,215,159,244,188,100,44,201,129,89,17,142,198,30,86,179,251,35,107,245,189,101,45,200,128,88,16,143,199,31,87,178,250,34,106,1,73,145,217,60,116,172,228,123,51,235,163,70,14,214,158,247,191,103,47,202,130,90,18,141,197,29,85,176,248,32,104,3,75,147,219,62,118,174,230,121,49,233,161,68,12,212,156,2,74,146,218,63,119,175,231,120,48,232,160,69,13,213,157,246,190,102,46,203,131,91,19,140,196,28,84,177,249,33,105,243,187,99,43,206,134,94,22,137,193,25,81,180,252,36,108,7,79,151,223,58,114,170,226,125,53,237,165,64,8,208,152,6,78,150,222,59,115,171,227,124,52,236,164,65,9,209,153,242,186,98,42,207,135,95,23,136,192,24,80,181,253,37,109,4,76,148,220,57,113,169,225,126,54,238,166,67,11,211,155,240,184,96,40,205,133,93,21,138,194,26,82,183,255,39,111,241,185,97,41,204,132,92,20,139,195,27,83,182,254,38,110,5,77,149,221,56,112,168,224,127,55,239,167,66,10,210,154,0,73,146,219,57,112,171,226,114,59,224,169,75,2,217,144,228,173,118,63,221,148,79,6,150,223,4,77,175,230,61,116,213,156,71,14,236,165,126,55,167,238,53,124,158,215,12,69,49,120,163,234,8,65,154,211,67,10,209,152,122,51,232,161,183,254,37,108,142,199,28,85,197,140,87,30,252,181,110,39,83,26,193,136,106,35,248,177,33,104,179,250,24,81,138,195,98,43,240,185,91,18,201,128,16,89,130,203,41,96,187,242,134,207,20,93,191,246,45,100,244,189,102,47,205,132,95,22,115,58,225,168,74,3,216,145,1,72,147,218,56,113,170,227,151,222,5,76,174,231,60,117,229,172,119,62,220,149,78,7,166,239,52,125,159,214,13,68,212,157,70,15,237,164,127,54,66,11,208,153,123,50,233,160,48,121,162,235,9,64,155,210,196,141,86,31,253,180,111,38,182,255,36,109,143,198,29,84,32,105,178,251,25,80,139,194,82,27,192,137,107,34,249,176,17,88,131,202,40,97,186,243,99,42,241,184,90,19,200,129,245,188,103,46,204,133,94,23,135,206,21,92,190,247,44,101,0,74,148,222,53,127,161,235,106,32,254,180,95,21,203,129,212,158,64,10,225,171,117,63,190,244,42,96,139,193,31,85,181,255,33,107,128,202,20,94,223,149,75,1,234,160,126,52,97,43,245,191,84,30,192,138,11,65,159,213,62,116,170,224,119,61,227,169,66,8,214,156,29,87,137,195,40,98,188,246,163,233,55,125,150,220,2,72,201,131,93,23,252,182,104,34,194,136,86,28,247,189,99,41,168,226,60,118,157,215,9,67,22,92,130,200,35,105,183,253,124,54,232,162,73,3,221,151,238,164,122,48,219,145,79,5,132,206,16,90,177,251,37,111,58,112,174,228,15,69,155,209,80,26,196,142,101,47,241,187,91,17,207,133,110,36,250,176,49,123,165,239,4,78,144,218,143,197,27,81,186,240,46,100,229,175,113,59,208,154,68,14,153,211,13,71,172,230,56,114,243,185,103,45,198,140,82,24,77,7,217,147,120,50,236,166,39,109,179,249,18,88,134,204,44,102,184,242,25,83,141,199,70,12,210,152,115,57,231,173,248,178,108,38,205,135,89,19,146,216,6,76,167,237,51,121,0,75,150,221,49,122,167,236,98,41,244,191,83,24,197,142,196,143,82,25,245,190,99,40,166,237,48,123,151,220,1,74,149,222,3,72,164,239,50,121,247,188,97,42,198,141,80,27,81,26,199,140,96,43,246,189,51,120,165,238,2,73,148,223,55,124,161,234,6,77,144,219,85,30,195,136,100,47,242,185,243,184,101,46,194,137,84,31,145,218,7,76,160,235,54,125,162,233,52,127,147,216,5,78,192,139,86,29,241,186,103,44,102,45,240,187,87,28,193,138,4,79,146,217,53,126,163,232,110,37,248,179,95,20,201,130,12,71,154,209,61,118,171,224,170,225,60,119,155,208,13,70,200,131,94,21,249,178,111,36,251,176,109,38,202,129,92,23,153,210,15,68,168,227,62,117,63,116,169,226,14,69,152,211,93,22,203,128,108,39,250,177,89,18,207,132,104,35,254,181,59,112,173,230,10,65,156,215,157,214,11,64,172,231,58,113,255,180,105,34,206,133,88,19,204,135,90,17,253,182,107,32,174,229,56,115,159,212,9,66,8,67,158,213,57,114,175,228,106,33,252,183,91,16,205,134,0,76,152,212,45,97,181,249,90,22,194,142,119,59,239,163,180,248,44,96,153,213,1,77,238,162,118,58,195,143,91,23,117,57,237,161,88,20,192,140,47,99,183,251,2,78,154,214,193,141,89,21,236,160,116,56,155,215,3,79,182,250,46,98,234,166,114,62,199,139,95,19,176,252,40,100,157,209,5,73,94,18,198,138,115,63,235,167,4,72,156,208,41,101,177,253,159,211,7,75,178,254,42,102,197,137,93,17,232,164,112,60,43,103,179,255,6,74,158,210,113,61,233,165,92,16,196,136,201,133,81,29,228,168,124,48,147,223,11,71,190,242,38,106,125,49,229,169,80,28,200,132,39,107,191,243,10,70,146,222,188,240,36,104,145,221,9,69,230,170,126,50,203,135,83,31,8,68,144,220,37,105,189,241,82,30,202,134,127,51,231,171,35,111,187,247,14,66,150,218,121,53,225,173,84,24,204,128,151,219,15,67,186,246,34,110,205,129,85,25,224,172,120,52,86,26,206,130,123,55,227,175,12,64,148,216,33,109,185,245,226,174,122,54,207,131,87,27,184,244,32,108,149,217,13,65,0,77,154,215,41,100,179,254,82,31,200,133,123,54,225,172,164,233,62,115,141,192,23,90,246,187,108,33,223,146,69,8,85,24,207,130,124,49,230,171,7,74,157,208,46,99,180,249,241,188,107,38,216,149,66,15,163,238,57,116,138,199,16,93,170,231,48,125,131,206,25,84,248,181,98,47,209,156,75,6,14,67,148,217,39,106,189,240,92,17,198,139,117,56,239,162,255,178,101,40,214,155,76,1,173,224,55,122,132,201,30,83,91,22,193,140,114,63,232,165,9,68,147,222,32,109,186,247,73,4,211,158,96,45,250,183,27,86,129,204,50,127,168,229,237,160,119,58,196,137,94,19,191,242,37,104,150,219,12,65,28,81,134,203,53,120,175,226,78,3,212,153,103,42,253,176,184,245,34,111,145,220,11,70,234,167,112,61,195,142,89,20,227,174,121,52,202,135,80,29,177,252,43,102,152,213,2,79,71,10,221,144,110,35,244,185,21,88,143,194,60,113,166,235,182,251,44,97,159,210,5,72,228,169,126,51,205,128,87,26,18,95,136,197,59,118,161,236,64,13,218,151,105,36,243,190,0,78,156,210,37,107,185,247,74,4,214,152,111,33,243,189,148,218,8,70,177,255,45,99,222,144,66,12,251,181,103,41,53,123,169,231,16,94,140,194,127,49,227,173,90,20,198,136,161,239,61,115,132,202,24,86,235,165,119,57,206,128,82,28,106,36,246,184,79,1,211,157,32,110,188,242,5,75,153,215,254,176,98,44,219,149,71,9,180,250,40,102,145,223,13,67,95,17,195,141,122,52,230,168,21,91,137,199,48,126,172,226,203,133,87,25,238,160,114,60,129,207,29,83,164,234,56,118,212,154,72,6,241,191,109,35,158,208,2,76,187,245,39,105,64,14,220,146,101,43,249,183,10,68,150,216,47,97,179,253,225,175,125,51,196,138,88,22,171,229,55,121,142,192,18,92,117,59,233,167,80,30,204,130,63,113,163,237,26,84,134,200,190,240,34,108,155,213,7,73,244,186,104,38,209,159,77,3,42,100,182,248,15,65,147,221,96,46,252,178,69,11,217,151,139,197,23,89,174,224,50,124,193,143,93,19,228,170,120,54,31,81,131,205,58,116,166,232,85,27,201,135,112,62,236,162,0,79,158,209,33,110,191,240,66,13,220,147,99,44,253,178,132,203,26,85,165,234,59,116,198,137,88,23,231,168,121,54,21,90,139,196,52,123,170,229,87,24,201,134,118,57,232,167,145,222,15,64,176,255,46,97,211,156,77,2,242,189,108,35,42,101,180,251,11,68,149,218,104,39,246,185,73,6,215,152,174,225,48,127,143,192,17,94,236,163,114,61,205,130,83,28,63,112,161,238,30,81,128,207,125,50,227,172,92,19,194,141,187,244,37,106,154,213,4,75,249,182,103,40,216,151,70,9,84,27,202,133,117,58,235,164,22,89,136,199,55,120,169,230,208,159,78,1,241,190,111,32,146,221,12,67,179,252,45,98,65,14,223,144,96,47,254,177,3,76,157,210,34,109,188,243,197,138,91,20,228,171,122,53,135,200,25,86,166,233,56,119,126,49,224,175,95,16,193,142,60,115,162,237,29,82,131,204,250,181,100,43,219,148,69,10,184,247,38,105,153,214,7,72,107,36,245,186,74,5,212,155,41,102,183,248,8,71,150,217,239,160,113,62,206,129,80,31,173,226,51,124,140,195,18,93,0,80,160,240,93,13,253,173,186,234,26,74,231,183,71,23,105,57,201,153,52,100,148,196,211,131,115,35,142,222,46,126,210,130,114,34,143,223,47,127,104,56,200,152,53,101,149,197,187,235,27,75,230,182,70,22,1,81,161,241,92,12,252,172,185,233,25,73,228,180,68,20,3,83,163,243,94,14,254,174,208,128,112,32,141,221,45,125,106,58,202,154,55,103,151,199,107,59,203,155,54,102,150,198,209,129,113,33,140,220,44,124,2,82,162,242,95,15,255,175,184,232,24,72,229,181,69,21,111,63,207,159,50,98,146,194,213,133,117,37,136,216,40,120,6,86,166,246,91,11,251,171,188,236,28,76,225,177,65,17,189,237,29,77,224,176,64,16,7,87,167,247,90,10,250,170,212,132,116,36,137,217,41,121,110,62,206,158,51,99,147,195,214,134,118,38,139,219,43,123,108,60,204,156,49,97,145,193,191,239,31,79,226,178,66,18,5,85,165,245,88,8,248,168,4,84,164,244,89,9,249,169,190,238,30,78,227,179,67,19,109,61,205,157,48,96,144,192,215,135,119,39,138,218,42,122,0,81,162,243,89,8,251,170,178,227,16,65,235,186,73,24,121,40,219,138,32,113,130,211,203,154,105,56,146,195,48,97,242,163,80,1,171,250,9,88,64,17,226,179,25,72,187,234,139,218,41,120,210,131,112,33,57,104,155,202,96,49,194,147,249,168,91,10,160,241,2,83,75,26,233,184,18,67,176,225,128,209,34,115,217,136,123,42,50,99,144,193,107,58,201,152,11,90,169,248,82,3,240,161,185,232,27,74,224,177,66,19,114,35,208,129,43,122,137,216,192,145,98,51,153,200,59,106,239,190,77,28,182,231,20,69,93,12,255,174,4,85,166,247,150,199,52,101,207,158,109,60,36,117,134,215,125,44,223,142,29,76,191,238,68,21,230,183,175,254,13,92,246,167,84,5,100,53,198,151,61,108,159,206,214,135,116,37,143,222,45,124,22,71,180,229,79,30,237,188,164,245,6,87,253,172,95,14,111,62,205,156,54,103,148,197,221,140,127,46,132,213,38,119,228,181,70,23,189,236,31,78,86,7,244,165,15,94,173,252,157,204,63,110,196,149,102,55,47,126,141,220,118,39,212,133,0,82,164,246,85,7,241,163,170,248,14,92,255,173,91,9,73,27,237,191,28,78,184,234,227,177,71,21,182,228,18,64,146,192,54,100,199,149,99,49,56,106,156,206,109,63,201,155,219,137,127,45,142,220,42,120,113,35,213,135,36,118,128,210,57,107,157,207,108,62,200,154,147,193,55,101,198,148,98,48,112,34,212,134,37,119,129,211,218,136,126,44,143,221,43,121,171,249,15,93,254,172,90,8,1,83,165,247,84,6,240,162,226,176,70,20,183,229,19,65,72,26,236,190,29,79,185,235,114,32,214,132,39,117,131,209,216,138,124,46,141,223,41,123,59,105,159,205,110,60,202,152,145,195,53,103,196,150,96,50,224,178,68,22,181,231,17,67,74,24,238,188,31,77,187,233,169,251,13,95,252,174,88,10,3,81,167,245,86,4,242,160,75,25,239,189,30,76,186,232,225,179,69,23,180,230,16,66,2,80,166,244,87,5,243,161,168,250,12,94,253,175,89,11,217,139,125,47,140,222,40,122,115,33,215,133,38,116,130,208,144,194,52,102,197,151,97,51,58,104,158,204,111,61,203,153,0,83,166,245,81,2,247,164,162,241,4,87,243,160,85,6,89,10,255,172,8,91,174,253,251,168,93,14,170,249,12,95,178,225,20,71,227,176,69,22,16,67,182,229,65,18,231,180,235,184,77,30,186,233,28,79,73,26,239,188,24,75,190,237,121,42,223,140,40,123,142,221,219,136,125,46,138,217,44,127,32,115,134,213,113,34,215,132,130,209,36,119,211,128,117,38,203,152,109,62,154,201,60,111,105,58,207,156,56,107,158,205,146,193,52,103,195,144,101,54,48,99,150,197,97,50,199,148,242,161,84,7,163,240,5,86,80,3,246,165,1,82,167,244,171,248,13,94,250,169,92,15,9,90,175,252,88,11,254,173,64,19,230,181,17,66,183,228,226,177,68,23,179,224,21,70,25,74,191,236,72,27,238,189,187,232,29,78,234,185,76,31,139,216,45,126,218,137,124,47,41,122,143,220,120,43,222,141,210,129,116,39,131,208,37,118,112,35,214,133,33,114,135,212,57,106,159,204,104,59,206,157,155,200,61,110,202,153,108,63,96,51,198,149,49,98,151,196,194,145,100,55,147,192,53,102,0,84,168,252,77,25,229,177,154,206,50,102,215,131,127,43,41,125,129,213,100,48,204,152,179,231,27,79,254,170,86,2,82,6,250,174,31,75,183,227,200,156,96,52,133,209,45,121,123,47,211,135,54,98,158,202,225,181,73,29,172,248,4,80,164,240,12,88,233,189,65,21,62,106,150,194,115,39,219,143,141,217,37,113,192,148,104,60,23,67,191,235,90,14,242,166,246,162,94,10,187,239,19,71,108,56,196,144,33,117,137,221,223,139,119,35,146,198,58,110,69,17,237,185,8,92,160,244,85,1,253,169,24,76,176,228,207,155,103,51,130,214,42,126,124,40,212,128,49,101,153,205,230,178,78,26,171,255,3,87,7,83,175,251,74,30,226,182,157,201,53,97,208,132,120,44,46,122,134,210,99,55,203,159,180,224,28,72,249,173,81,5,241,165,89,13,188,232,20,64,107,63,195,151,38,114,142,218,216,140,112,36,149,193,61,105,66,22,234,190,15,91,167,243,163,247,11,95,238,186,70,18,57,109,145,197,116,32,220,136,138,222,34,118,199,147,111,59,16,68,184,236,93,9,245,161,0,85,170,255,73,28,227,182,146,199,56,109,219,142,113,36,57,108,147,198,112,37,218,143,171,254,1,84,226,183,72,29,114,39,216,141,59,110,145,196,224,181,74,31,169,252,3,86,75,30,225,180,2,87,168,253,217,140,115,38,144,197,58,111,228,177,78,27,173,248,7,82,118,35,220,137,63,106,149,192,221,136,119,34,148,193,62,107,79,26,229,176,6,83,172,249,150,195,60,105,223,138,117,32,4,81,174,251,77,24,231,178,175,250,5,80,230,179,76,25,61,104,151,194,116,33,222,139,213,128,127,42,156,201,54,99,71,18,237,184,14,91,164,241,236,185,70,19,165,240,15,90,126,43,212,129,55,98,157,200,167,242,13,88,238,187,68,17,53,96,159,202,124,41,214,131,158,203,52,97,215,130,125,40,12,89,166,243,69,16,239,186,49,100,155,206,120,45,210,135,163,246,9,92,234,191,64,21,8,93,162,247,65,20,235,190,154,207,48,101,211,134,121,44,67,22,233,188,10,95,160,245,209,132,123,46,152,205,50,103,122,47,208,133,51,102,153,204,232,189,66,23,161,244,11,94,0,86,172,250,69,19,233,191,138,220,38,112,207,153,99,53,9,95,165,243,76,26,224,182,131,213,47,121,198,144,106,60,18,68,190,232,87,1,251,173,152,206,52,98,221,139,113,39,27,77,183,225,94,8,242,164,145,199,61,107,212,130,120,46,36,114,136,222,97,55,205,155,174,248,2,84,235,189,71,17,45,123,129,215,104,62,196,146,167,241,11,93,226,180,78,24,54,96,154,204,115,37,223,137,188,234,16,70,249,175,85,3,63,105,147,197,122,44,214,128,181,227,25,79,240,166,92,10,72,30,228,178,13,91,161,247,194,148,110,56,135,209,43,125,65,23,237,187,4,82,168,254,203,157,103,49,142,216,34,116,90,12,246,160,31,73,179,229,208,134,124,42,149,195,57,111,83,5,255,169,22,64,186,236,217,143,117,35,156,202,48,102,108,58,192,150,41,127,133,211,230,176,74,28,163,245,15,89,101,51,201,159,32,118,140,218,239,185,67,21,170,252,6,80,126,40,210,132,59,109,151,193,244,162,88,14,177,231,29,75,119,33,219,141,50,100,158,200,253,171,81,7,184,238,20,66,0,87,174,249,65,22,239,184,130,213,44,123,195,148,109,58,25,78,183,224,88,15,246,161,155,204,53,98,218,141,116,35,50,101,156,203,115,36,221,138,176,231,30,73,241,166,95,8,43,124,133,210,106,61,196,147,169,254,7,80,232,191,70,17,100,51,202,157,37,114,139,220,230,177,72,31,167,240,9,94,125,42,211,132,60,107,146,197,255,168,81,6,190,233,16,71,86,1,248,175,23,64,185,238,212,131,122,45,149,194,59,108,79,24,225,182,14,89,160,247,205,154,99,52,140,219,34,117,200,159,102,49,137,222,39,112,74,29,228,179,11,92,165,242,209,134,127,40,144,199,62,105,83,4,253,170,18,69,188,235,250,173,84,3,187,236,21,66,120,47,214,129,57,110,151,192,227,180,77,26,162,245,12,91,97,54,207,152,32,119,142,217,172,251,2,85,237,186,67,20,46,121,128,215,111,56,193,150,181,226,27,76,244,163,90,13,55,96,153,206,118,33,216,143,158,201,48,103,223,136,113,38,28,75,178,229,93,10,243,164,135,208,41,126,198,145,104,63,5,82,171,252,68,19,234,189,0,88,176,232,125,37,205,149,250,162,74,18,135,223,55,111,233,177,89,1,148,204,36,124,19,75,163,251,110,54,222,134,207,151,127,39,178,234,2,90,53,109,133,221,72,16,248,160,38,126,150,206,91,3,235,179,220,132,108,52,161,249,17,73,131,219,51,107,254,166,78,22,121,33,201,145,4,92,180,236,106,50,218,130,23,79,167,255,144,200,32,120,237,181,93,5,76,20,252,164,49,105,129,217,182,238,6,94,203,147,123,35,165,253,21,77,216,128,104,48,95,7,239,183,34,122,146,202,27,67,171,243,102,62,214,142,225,185,81,9,156,196,44,116,242,170,66,26,143,215,63,103,8,80,184,224,117,45,197,157,212,140,100,60,169,241,25,65,46,118,158,198,83,11,227,187,61,101,141,213,64,24,240,168,199,159,119,47,186,226,10,82,152,192,40,112,229,189,85,13,98,58,210,138,31,71,175,247,113,41,193,153,12,84,188,228,139,211,59,99,246,174,70,30,87,15,231,191,42,114,154,194,173,245,29,69,208,136,96,56,190,230,14,86,195,155,115,43,68,28,244,172,57,97,137,209,0,89,178,235,121,32,203,146,242,171,64,25,139,210,57,96,249,160,75,18,128,217,50,107,11,82,185,224,114,43,192,153,239,182,93,4,150,207,36,125,29,68,175,246,100,61,214,143,22,79,164,253,111,54,221,132,228,189,86,15,157,196,47,118,195,154,113,40,186,227,8,81,49,104,131,218,72,17,250,163,58,99,136,209,67,26,241,168,200,145,122,35,177,232,3,90,44,117,158,199,85,12,231,190,222,135,108,53,167,254,21,76,213,140,103,62,172,245,30,71,39,126,149,204,94,7,236,181,155,194,41,112,226,187,80,9,105,48,219,130,16,73,162,251,98,59,208,137,27,66,169,240,144,201,34,123,233,176,91,2,116,45,198,159,13,84,191,230,134,223,52,109,255,166,77,20,141,212,63,102,244,173,70,31,127,38,205,148,6,95,180,237,88,1,234,179,33,120,147,202,170,243,24,65,211,138,97,56,161,248,19,74,216,129,106,51,83,10,225,184,42,115,152,193,183,238,5,92,206,151,124,37,69,28,247,174,60,101,142,215,78,23,252,165,55,110,133,220,188,229,14,87,197,156,119,46,0,90,180,238,117,47,193,155,234,176,94,4,159,197,43,113,201,147,125,39,188,230,8,82,35,121,151,205,86,12,226,184,143,213,59,97,250,160,78,20,101,63,209,139,16,74,164,254,70,28,242,168,51,105,135,221,172,246,24,66,217,131,109,55,3,89,183,237,118,44,194,152,233,179,93,7,156,198,40,114,202,144,126,36,191,229,11,81,32,122,148,206,85,15,225,187,140,214,56,98,249,163,77,23,102,60,210,136,19,73,167,253,69,31,241,171,48,106,132,222,175,245,27,65,218,128,110,52,6,92,178,232,115,41,199,157,236,182,88,2,153,195,45,119,207,149,123,33,186,224,14,84,37,127,145,203,80,10,228,190,137,211,61,103,252,166,72,18,99,57,215,141,22,76,162,248,64,26,244,174,53,111,129,219,170,240,30,68,223,133,107,49,5,95,177,235,112,42,196,158,239,181,91,1,154,192,46,116,204,150,120,34,185,227,13,87,38,124,146,200,83,9,231,189,138,208,62,100,255,165,75,17,96,58,212,142,21,79,161,251,67,25,247,173,54,108,130,216,169,243,29,71,220,134,104,50,0,91,182,237,113,42,199,156,226,185,84,15,147,200,37,126,217,130,111,52,168,243,30,69,59,96,141,214,74,17,252,167,175,244,25,66,222,133,104,51,77,22,251,160,60,103,138,209,118,45,192,155,7,92,177,234,148,207,34,121,229,190,83,8,67,24,245,174,50,105,132,223,161,250,23,76,208,139,102,61,154,193,44,119,235,176,93,6,120,35,206,149,9,82,191,228,236,183,90,1,157,198,43,112,14,85,184,227,127,36,201,146,53,110,131,216,68,31,242,169,215,140,97,58,166,253,16,75,134,221,48,107,247,172,65,26,100,63,210,137,21,78,163,248,95,4,233,178,46,117,152,195,189,230,11,80,204,151,122,33,41,114,159,196,88,3,238,181,203,144,125,38,186,225,12,87,240,171,70,29,129,218,55,108,18,73,164,255,99,56,213,142,197,158,115,40,180,239,2,89,39,124,145,202,86,13,224,187,28,71,170,241,109,54,219,128,254,165,72,19,143,212,57,98,106,49,220,135,27,64,173,246,136,211,62,101,249,162,79,20,179,232,5,94,194,153,116,47,81,10,231,188,32,123,150,205,0,92,184,228,109,49,213,137,218,134,98,62,183,235,15,83,169,245,17,77,196,152,124,32,115,47,203,151,30,66,166,250,79,19,247,171,34,126,154,198,149,201,45,113,248,164,64,28,230,186,94,2,139,215,51,111,60,96,132,216,81,13,233,181,158,194,38,122,243,175,75,23,68,24,252,160,41,117,145,205,55,107,143,211,90,6,226,190,237,177,85,9,128,220,56,100,209,141,105,53,188,224,4,88,11,87,179,239,102,58,222,130,120,36,192,156,21,73,173,241,162,254,26,70,207,147,119,43,33,125,153,197,76,16,244,168,251,167,67,31,150,202,46,114,136,212,48,108,229,185,93,1,82,14,234,182,63,99,135,219,110,50,214,138,3,95,187,231,180,232,12,80,217,133,97,61,199,155,127,35,170,246,18,78,29,65,165,249,112,44,200,148,191,227,7,91,210,142,106,54,101,57,221,129,8,84,176,236,22,74,174,242,123,39,195,159,204,144,116,40,161,253,25,69,240,172,72,20,157,193,37,121,42,118,146,206,71,27,255,163,89,5,225,189,52,104,140,208,131,223,59,103,238,178,86,10,0,93,186,231,105,52,211,142,210,143,104,53,187,230,1,92,185,228,3,94,208,141,106,55,107,54,209,140,2,95,184,229,111,50,213,136,6,91,188,225,189,224,7,90,212,137,110,51,214,139,108,49,191,226,5,88,4,89,190,227,109,48,215,138,222,131,100,57,183,234,13,80,12,81,182,235,101,56,223,130,103,58,221,128,14,83,180,233,181,232,15,82,220,129,102,59,177,236,11,86,216,133,98,63,99,62,217,132,10,87,176,237,8,85,178,239,97,60,219,134,218,135,96,61,179,238,9,84,161,252,27,70,200,149,114,47,115,46,201,148,26,71,160,253,24,69,162,255,113,44,203,150,202,151,112,45,163,254,25,68,206,147,116,41,167,250,29,64,28,65,166,251,117,40,207,146,119,42,205,144,30,67,164,249,165,248,31,66,204,145,118,43,127,34,197,152,22,75,172,241,173,240,23,74,196,153,126,35,198,155,124,33,175,242,21,72,20,73,174,243,125,32,199,154,16,77,170,247,121,36,195,158,194,159,120,37,171,246,17,76,169,244,19,78,192,157,122,39,123,38,193,156,18,79,168,245,0,94,188,226,101,59,217,135,202,148,118,40,175,241,19,77,137,215,53,107,236,178,80,14,67,29,255,161,38,120,154,196,15,81,179,237,106,52,214,136,197,155,121,39,160,254,28,66,134,216,58,100,227,189,95,1,76,18,240,174,41,119,149,203,30,64,162,252,123,37,199,153,212,138,104,54,177,239,13,83,151,201,43,117,242,172,78,16,93,3,225,191,56,102,132,218,17,79,173,243,116,42,200,150,219,133,103,57,190,224,2,92,152,198,36,122,253,163,65,31,82,12,238,176,55,105,139,213,60,98,128,222,89,7,229,187,246,168,74,20,147,205,47,113,181,235,9,87,208,142,108,50,127,33,195,157,26,68,166,248,51,109,143,209,86,8,234,180,249,167,69,27,156,194,32,126,186,228,6,88,223,129,99,61,112,46,204,146,21,75,169,247,34,124,158,192,71,25,251,165,232,182,84,10,141,211,49,111,171,245,23,73,206,144,114,44,97,63,221,131,4,90,184,230,45,115,145,207,72,22,244,170,231,185,91,5,130,220,62,96,164,250,24,70,193,159,125,35,110,48,210,140,11,85,183,233,0,95,190,225,97,62,223,128,194,157,124,35,163,252,29,66,153,198,39,120,248,167,70,25,91,4,229,186,58,101,132,219,47,112,145,206,78,17,240,175,237,178,83,12,140,211,50,109,182,233,8,87,215,136,105,54,116,43,202,149,21,74,171,244,94,1,224,191,63,96,129,222,156,195,34,125,253,162,67,28,199,152,121,38,166,249,24,71,5,90,187,228,100,59,218,133,113,46,207,144,16,79,174,241,179,236,13,82,210,141,108,51,232,183,86,9,137,214,55,104,42,117,148,203,75,20,245,170,188,227,2,93,221,130,99,60,126,33,192,159,31,64,161,254,37,122,155,196,68,27,250,165,231,184,89,6,134,217,56,103,147,204,45,114,242,173,76,19,81,14,239,176,48,111,142,209,10,85,180,235,107,52,213,138,200,151,118,41,169,246,23,72,226,189,92,3,131,220,61,98,32,127,158,193,65,30,255,160,123,36,197,154,26,69,164,251,185,230,7,88,216,135,102,57,205,146,115,44,172,243,18,77,15,80,177,238,110,49,208,143,84,11,234,181,53,106,139,212,150,201,40,119,247,168,73,22,0,96,192,160,157,253,93,61,39,71,231,135,186,218,122,26,78,46,142,238,211,179,19,115,105,9,169,201,244,148,52,84,156,252,92,60,1,97,193,161,187,219,123,27,38,70,230,134,210,178,18,114,79,47,143,239,245,149,53,85,104,8,168,200,37,69,229,133,184,216,120,24,2,98,194,162,159,255,95,63,107,11,171,203,246,150,54,86,76,44,140,236,209,177,17,113,185,217,121,25,36,68,228,132,158,254,94,62,3,99,195,163,247,151,55,87,106,10,170,202,208,176,16,112,77,45,141,237,74,42,138,234,215,183,23,119,109,13,173,205,240,144,48,80,4,100,196,164,153,249,89,57,35,67,227,131,190,222,126,30,214,182,22,118,75,43,139,235,241,145,49,81,108,12,172,204,152,248,88,56,5,101,197,165,191,223,127,31,34,66,226,130,111,15,175,207,242,146,50,82,72,40,136,232,213,181,21,117,33,65,225,129,188,220,124,28,6,102,198,166,155,251,91,59,243,147,51,83,110,14,174,206,212,180,20,116,73,41,137,233,189,221,125,29,32,64,224,128,154,250,90,58,7,103,199,167,0,97,194,163,153,248,91,58,47,78,237,140,182,215,116,21,94,63,156,253,199,166,5,100,113,16,179,210,232,137,42,75,188,221,126,31,37,68,231,134,147,242,81,48,10,107,200,169,226,131,32,65,123,26,185,216,205,172,15,110,84,53,150,247,101,4,167,198,252,157,62,95,74,43,136,233,211,178,17,112,59,90,249,152,162,195,96,1,20,117,214,183,141,236,79,46,217,184,27,122,64,33,130,227,246,151,52,85,111,14,173,204,135,230,69,36,30,127,220,189,168,201,106,11,49,80,243,146,202,171,8,105,83,50,145,240,229,132,39,70,124,29,190,223,148,245,86,55,13,108,207,174,187,218,121,24,34,67,224,129,118,23,180,213,239,142,45,76,89,56,155,250,192,161,2,99,40,73,234,139,177,208,115,18,7,102,197,164,158,255,92,61,175,206,109,12,54,87,244,149,128,225,66,35,25,120,219,186,241,144,51,82,104,9,170,203,222,191,28,125,71,38,133,228,19,114,209,176,138,235,72,41,60,93,254,159,165,196,103,6,77,44,143,238,212,181,22,119,98,3,160,193,251,154,57,88,0,98,196,166,149,247,81,51,55,85,243,145,162,192,102,4,110,12,170,200,251,153,63,93,89,59,157,255,204,174,8,106,220,190,24,122,73,43,141,239,235,137,47,77,126,28,186,216,178,208,118,20,39,69,227,129,133,231,65,35,16,114,212,182,165,199,97,3,48,82,244,150,146,240,86,52,7,101,195,161,203,169,15,109,94,60,154,248,252,158,56,90,105,11,173,207,121,27,189,223,236,142,40,74,78,44,138,232,219,185,31,125,23,117,211,177,130,224,70,36,32,66,228,134,181,215,113,19,87,53,147,241,194,160,6,100,96,2,164,198,245,151,49,83,57,91,253,159,172,206,104,10,14,108,202,168,155,249,95,61,139,233,79,45,30,124,218,184,188,222,120,26,41,75,237,143,229,135,33,67,112,18,180,214,210,176,22,116,71,37,131,225,242,144,54,84,103,5,163,193,197,167,1,99,80,50,148,246,156,254,88,58,9,107,205,175,171,201,111,13,62,92,250,152,46,76,234,136,187,217,127,29,25,123,221,191,140,238,72,42,64,34,132,230,213,183,17,115,119,21,179,209,226,128,38,68,0,99,198,165,145,242,87,52,63,92,249,154,174,205,104,11,126,29,184,219,239,140,41,74,65,34,135,228,208,179,22,117,252,159,58,89,109,14,171,200,195,160,5,102,82,49,148,247,130,225,68,39,19,112,213,182,189,222,123,24,44,79,234,137,229,134,35,64,116,23,178,209,218,185,28,127,75,40,141,238,155,248,93,62,10,105,204,175,164,199,98,1,53,86,243,144,25,122,223,188,136,235,78,45,38,69,224,131,183,212,113,18,103,4,161,194,246,149,48,83,88,59,158,253,201,170,15,108,215,180,17,114,70,37,128,227,232,139,46,77,121,26,191,220,169,202,111,12,56,91,254,157,150,245,80,51,7,100,193,162,43,72,237,142,186,217,124,31,20,119,210,177,133,230,67,32,85,54,147,240,196,167,2,97,106,9,172,207,251,152,61,94,50,81,244,151,163,192,101,6,13,110,203,168,156,255,90,57,76,47,138,233,221,190,27,120,115,16,181,214,226,129,36,71,206,173,8,107,95,60,153,250,241,146,55,84,96,3,166,197,176,211,118,21,33,66,231,132,143,236,73,42,30,125,216,187,0,100,200,172,141,233,69,33,7,99,207,171,138,238,66,38,14,106,198,162,131,231,75,47,9,109,193,165,132,224,76,40,28,120,212,176,145,245,89,61,27,127,211,183,150,242,94,58,18,118,218,190,159,251,87,51,21,113,221,185,152,252,80,52,56,92,240,148,181,209,125,25,63,91,247,147,178,214,122,30,54,82,254,154,187,223,115,23,49,85,249,157,188,216,116,16,36,64,236,136,169,205,97,5,35,71,235,143,174,202,102,2,42,78,226,134,167,195,111,11,45,73,229,129,160,196,104,12,112,20,184,220,253,153,53,81,119,19,191,219,250,158,50,86,126,26,182,210,243,151,59,95,121,29,177,213,244,144,60,88,108,8,164,192,225,133,41,77,107,15,163,199,230,130,46,74,98,6,170,206,239,139,39,67,101,1,173,201,232,140,32,68,72,44,128,228,197,161,13,105,79,43,135,227,194,166,10,110,70,34,142,234,203,175,3,103,65,37,137,237,204,168,4,96,84,48,156,248,217,189,17,117,83,55,155,255,222,186,22,114,90,62,146,246,215,179,31,123,93,57,149,241,208,180,24,124,0,101,202,175,137,236,67,38,15,106,197,160,134,227,76,41,30,123,212,177,151,242,93,56,17,116,219,190,152,253,82,55,60,89,246,147,181,208,127,26,51,86,249,156,186,223,112,21,34,71,232,141,171,206,97,4,45,72,231,130,164,193,110,11,120,29,178,215,241,148,59,94,119,18,189,216,254,155,52,81,102,3,172,201,239,138,37,64,105,12,163,198,224,133,42,79,68,33,142,235,205,168,7,98,75,46,129,228,194,167,8,109,90,63,144,245,211,182,25,124,85,48,159,250,220,185,22,115,240,149,58,95,121,28,179,214,255,154,53,80,118,19,188,217,238,139,36,65,103,2,173,200,225,132,43,78,104,13,162,199,204,169,6,99,69,32,143,234,195,166,9,108,74,47,128,229,210,183,24,125,91,62,145,244,221,184,23,114,84,49,158,251,136,237,66,39,1,100,203,174,135,226,77,40,14,107,196,161,150,243,92,57,31,122,213,176,153,252,83,54,16,117,218,191,180,209,126,27,61,88,247,146,187,222,113,20,50,87,248,157,170,207,96,5,35,70,233,140,165,192,111,10,44,73,230,131,0,102,204,170,133,227,73,47,23,113,219,189,146,244,94,56,46,72,226,132,171,205,103,1,57,95,245,147,188,218,112,22,92,58,144,246,217,191,21,115,75,45,135,225,206,168,2,100,114,20,190,216,247,145,59,93,101,3,169,207,224,134,44,74,184,222,116,18,61,91,241,151,175,201,99,5,42,76,230,128,150,240,90,60,19,117,223,185,129,231,77,43,4,98,200,174,228,130,40,78,97,7,173,203,243,149,63,89,118,16,186,220,202,172,6,96,79,41,131,229,221,187,17,119,88,62,148,242,109,11,161,199,232,142,36,66,122,28,182,208,255,153,51,85,67,37,143,233,198,160,10,108,84,50,152,254,209,183,29,123,49,87,253,155,180,210,120,30,38,64,234,140,163,197,111,9,31,121,211,181,154,252,86,48,8,110,196,162,141,235,65,39,213,179,25,127,80,54,156,250,194,164,14,104,71,33,139,237,251,157,55,81,126,24,178,212,236,138,32,70,105,15,165,195,137,239,69,35,12,106,192,166,158,248,82,52,27,125,215,177,167,193,107,13,34,68,238,136,176,214,124,26,53,83,249,159,0,103,206,169,129,230,79,40,31,120,209,182,158,249,80,55,62,89,240,151,191,216,113,22,33,70,239,136,160,199,110,9,124,27,178,213,253,154,51,84,99,4,173,202,226,133,44,75,66,37,140,235,195,164,13,106,93,58,147,244,220,187,18,117,248,159,54,81,121,30,183,208,231,128,41,78,102,1,168,207,198,161,8,111,71,32,137,238,217,190,23,112,88,63,150,241,132,227,74,45,5,98,203,172,155,252,85,50,26,125,212,179,186,221,116,19,59,92,245,146,165,194,107,12,36,67,234,141,237,138,35,68,108,11,162,197,242,149,60,91,115,20,189,218,211,180,29,122,82,53,156,251,204,171,2,101,77,42,131,228,145,246,95,56,16,119,222,185,142,233,64,39,15,104,193,166,175,200,97,6,46,73,224,135,176,215,126,25,49,86,255,152,21,114,219,188,148,243,90,61,10,109,196,163,139,236,69,34,43,76,229,130,170,205,100,3,52,83,250,157,181,210,123,28,105,14,167,192,232,143,38,65,118,17,184,223,247,144,57,94,87,48,153,254,214,177,24,127,72,47,134,225,201,174,7,96,0,104,208,184,189,213,109,5,103,15,183,223,218,178,10,98,206,166,30,118,115,27,163,203,169,193,121,17,20,124,196,172,129,233,81,57,60,84,236,132,230,142,54,94,91,51,139,227,79,39,159,247,242,154,34,74,40,64,248,144,149,253,69,45,31,119,207,167,162,202,114,26,120,16,168,192,197,173,21,125,209,185,1,105,108,4,188,212,182,222,102,14,11,99,219,179,158,246,78,38,35,75,243,155,249,145,41,65,68,44,148,252,80,56,128,232,237,133,61,85,55,95,231,143,138,226,90,50,62,86,238,134,131,235,83,59,89,49,137,225,228,140,52,92,240,152,32,72,77,37,157,245,151,255,71,47,42,66,250,146,191,215,111,7,2,106,210,186,216,176,8,96,101,13,181,221,113,25,161,201,204,164,28,116,22,126,198,174,171,195,123,19,33,73,241,153,156,244,76,36,70,46,150,254,251,147,43,67,239,135,63,87,82,58,130,234,136,224,88,48,53,93,229,141,160,200,112,24,29,117,205,165,199,175,23,127,122,18,170,194,110,6,190,214,211,187,3,107,9,97,217,177,180,220,100,12,0,105,210,187,185,208,107,2,111,6,189,212,214,191,4,109,222,183,12,101,103,14,181,220,177,216,99,10,8,97,218,179,161,200,115,26,24,113,202,163,206,167,28,117,119,30,165,204,127,22,173,196,198,175,20,125,16,121,194,171,169,192,123,18,95,54,141,228,230,143,52,93,48,89,226,139,137,224,91,50,129,232,83,58,56,81,234,131,238,135,60,85,87,62,133,236,254,151,44,69,71,46,149,252,145,248,67,42,40,65,250,147,32,73,242,155,153,240,75,34,79,38,157,244,246,159,36,77,190,215,108,5,7,110,213,188,209,184,3,106,104,1,186,211,96,9,178,219,217,176,11,98,15,102,221,180,182,223,100,13,31,118,205,164,166,207,116,29,112,25,162,203,201,160,27,114,193,168,19,122,120,17,170,195,174,199,124,21,23,126,197,172,225,136,51,90,88,49,138,227,142,231,92,53,55,94,229,140,63,86,237,132,134,239,84,61,80,57,130,235,233,128,59,82,64,41,146,251,249,144,43,66,47,70,253,148,150,255,68,45,158,247,76,37,39,78,245,156,241,152,35,74,72,33,154,243,0,106,212,190,181,223,97,11,119,29,163,201,194,168,22,124,238,132,58,80,91,49,143,229,153,243,77,39,44,70,248,146,193,171,21,127,116,30,160,202,182,220,98,8,3,105,215,189,47,69,251,145,154,240,78,36,88,50,140,230,237,135,57,83,159,245,75,33,42,64,254,148,232,130,60,86,93,55,137,227,113,27,165,207,196,174,16,122,6,108,210,184,179,217,103,13,94,52,138,224,235,129,63,85,41,67,253,151,156,246,72,34,176,218,100,14,5,111,209,187,199,173,19,121,114,24,166,204,35,73,247,157,150,252,66,40,84,62,128,234,225,139,53,95,205,167,25,115,120,18,172,198,186,208,110,4,15,101,219,177,226,136,54,92,87,61,131,233,149,255,65,43,32,74,244,158,12,102,216,178,185,211,109,7,123,17,175,197,206,164,26,112,188,214,104,2,9,99,221,183,203,161,31,117,126,20,170,192,82,56,134,236,231,141,51,89,37,79,241,155,144,250,68,46,125,23,169,195,200,162,28,118,10,96,222,180,191,213,107,1,147,249,71,45,38,76,242,152,228,142,48,90,81,59,133,239,0,107,214,189,177,218,103,12,127,20,169,194,206,165,24,115,254,149,40,67,79,36,153,242,129,234,87,60,48,91,230,141,225,138,55,92,80,59,134,237,158,245,72,35,47,68,249,146,31,116,201,162,174,197,120,19,96,11,182,221,209,186,7,108,223,180,9,98,110,5,184,211,160,203,118,29,17,122,199,172,33,74,247,156,144,251,70,45,94,53,136,227,239,132,57,82,62,85,232,131,143,228,89,50,65,42,151,252,240,155,38,77,192,171,22,125,113,26,167,204,191,212,105,2,14,101,216,179,163,200,117,30,18,121,196,175,220,183,10,97,109,6,187,208,93,54,139,224,236,135,58,81,34,73,244,159,147,248,69,46,66,41,148,255,243,152,37,78,61,86,235,128,140,231,90,49,188,215,106,1,13,102,219,176,195,168,21,126,114,25,164,207,124,23,170,193,205,166,27,112,3,104,213,190,178,217,100,15,130,233,84,63,51,88,229,142,253,150,43,64,76,39,154,241,157,246,75,32,44,71,250,145,226,137,52,95,83,56,133,238,99,8,181,222,210,185,4,111,28,119,202,161,173,198,123,16,0,108,216,180,173,193,117,25,71,43,159,243,234,134,50,94,142,226,86,58,35,79,251,151,201,165,17,125,100,8,188,208,1,109,217,181,172,192,116,24,70,42,158,242,235,135,51,95,143,227,87,59,34,78,250,150,200,164,16,124,101,9,189,209,2,110,218,182,175,195,119,27,69,41,157,241,232,132,48,92,140,224,84,56,33,77,249,149,203,167,19,127,102,10,190,210,3,111,219,183,174,194,118,26,68,40,156,240,233,133,49,93,141,225,85,57,32,76,248,148,202,166,18,126,103,11,191,211,4,104,220,176,169,197,113,29,67,47,155,247,238,130,54,90,138,230,82,62,39,75,255,147,205,161,21,121,96,12,184,212,5,105,221,177,168,196,112,28,66,46,154,246,239,131,55,91,139,231,83,63,38,74,254,146,204,160,20,120,97,13,185,213,6,106,222,178,171,199,115,31,65,45,153,245,236,128,52,88,136,228,80,60,37,73,253,145,207,163,23,123,98,14,186,214,7,107,223,179,170,198,114,30,64,44,152,244,237,129,53,89,137,229,81,61,36,72,252,144,206,162,22,122,99,15,187,215,0,109,218,183,169,196,115,30,79,34,149,248,230,139,60,81,158,243,68,41,55,90,237,128,209,188,11,102,120,21,162,207,33,76,251,150,136,229,82,63,110,3,180,217,199,170,29,112,191,210,101,8,22,123,204,161,240,157,42,71,89,52,131,238,66,47,152,245,235,134,49,92,13,96,215,186,164,201,126,19,220,177,6,107,117,24,175,194,147,254,73,36,58,87,224,141,99,14,185,212,202,167,16,125,44,65,246,155,133,232,95,50,253,144,39,74,84,57,142,227,178,223,104,5,27,118,193,172,132,233,94,51,45,64,247,154,203,166,17,124,98,15,184,213,26,119,192,173,179,222,105,4,85,56,143,226,252,145,38,75,165,200,127,18,12,97,214,187,234,135,48,93,67,46,153,244,59,86,225,140,146,255,72,37,116,25,174,195,221,176,7,106,198,171,28,113,111,2,181,216,137,228,83,62,32,77,250,151,88,53,130,239,241,156,43,70,23,122,205,160,190,211,100,9,231,138,61,80,78,35,148,249,168,197,114,31,1,108,219,182,121,20,163,206,208,189,10,103,54,91,236,129,159,242,69,40,0,110,220,178,165,203,121,23,87,57,139,229,242,156,46,64,174,192,114,28,11,101,215,185,249,151,37,75,92,50,128,238,65,47,157,243,228,138,56,86,22,120,202,164,179,221,111,1,239,129,51,93,74,36,150,248,184,214,100,10,29,115,193,175,130,236,94,48,39,73,251,149,213,187,9,103,112,30,172,194,44,66,240,158,137,231,85,59,123,21,167,201,222,176,2,108,195,173,31,113,102,8,186,212,148,250,72,38,49,95,237,131,109,3,177,223,200,166,20,122,58,84,230,136,159,241,67,45,25,119,197,171,188,210,96,14,78,32,146,252,235,133,55,89,183,217,107,5,18,124,206,160,224,142,60,82,69,43,153,247,88,54,132,234,253,147,33,79,15,97,211,189,170,196,118,24,246,152,42,68,83,61,143,225,161,207,125,19,4,106,216,182,155,245,71,41,62,80,226,140,204,162,16,126,105,7,181,219,53,91,233,135,144,254,76,34,98,12,190,208,199,169,27,117,218,180,6,104,127,17,163,205,141,227,81,63,40,70,244,154,116,26,168,198,209,191,13,99,35,77,255,145,134,232,90,52,0,111,222,177,161,206,127,16,95,48,129,238,254,145,32,79,190,209,96,15,31,112,193,174,225,142,63,80,64,47,158,241,97,14,191,208,192,175,30,113,62,81,224,143,159,240,65,46,223,176,1,110,126,17,160,207,128,239,94,49,33,78,255,144,194,173,28,115,99,12,189,210,157,242,67,44,60,83,226,141,124,19,162,205,221,178,3,108,35,76,253,146,130,237,92,51,163,204,125,18,2,109,220,179,252,147,34,77,93,50,131,236,29,114,195,172,188,211,98,13,66,45,156,243,227,140,61,82,153,246,71,40,56,87,230,137,198,169,24,119,103,8,185,214,39,72,249,150,134,233,88,55,120,23,166,201,217,182,7,104,248,151,38,73,89,54,135,232,167,200,121,22,6,105,216,183,70,41,152,247,231,136,57,86,25,118,199,168,184,215,102,9,91,52,133,234,250,149,36,75,4,107,218,181,165,202,123,20,229,138,59,84,68,43,154,245,186,213,100,11,27,116,197,170,58,85,228,139,155,244,69,42,101,10,187,212,196,171,26,117,132,235,90,53,37,74,251,148,219,180,5,106,122,21,164,203,0,112,224,144,221,173,61,77,167,215,71,55,122,10,154,234,83,35,179,195,142,254,110,30,244,132,20,100,41,89,201,185,166,214,70,54,123,11,155,235,1,113,225,145,220,172,60,76,245,133,21,101,40,88,200,184,82,34,178,194,143,255,111,31,81,33,177,193,140,252,108,28,246,134,22,102,43,91,203,187,2,114,226,146,223,175,63,79,165,213,69,53,120,8,152,232,247,135,23,103,42,90,202,186,80,32,176,192,141,253,109,29,164,212,68,52,121,9,153,233,3,115,227,147,222,174,62,78,162,210,66,50,127,15,159,239,5,117,229,149,216,168,56,72,241,129,17,97,44,92,204,188,86,38,182,198,139,251,107,27,4,116,228,148,217,169,57,73,163,211,67,51,126,14,158,238,87,39,183,199,138,250,106,26,240,128,16,96,45,93,205,189,243,131,19,99,46,94,206,190,84,36,180,196,137,249,105,25,160,208,64,48,125,13,157,237,7,119,231,151,218,170,58,74,85,37,181,197,136,248,104,24,242,130,18,98,47,95,207,191,6,118,230,150,219,171,59,75,161,209,65,49,124,12,156,236,0,113,226,147,217,168,59,74,175,222,77,60,118,7,148,229,67,50,161,208,154,235,120,9,236,157,14,127,53,68,215,166,134,247,100,21,95,46,189,204,41,88,203,186,240,129,18,99,197,180,39,86,28,109,254,143,106,27,136,249,179,194,81,32,17,96,243,130,200,185,42,91,190,207,92,45,103,22,133,244,82,35,176,193,139,250,105,24,253,140,31,110,36,85,198,183,151,230,117,4,78,63,172,221,56,73,218,171,225,144,3,114,212,165,54,71,13,124,239,158,123,10,153,232,162,211,64,49,34,83,192,177,251,138,25,104,141,252,111,30,84,37,182,199,97,16,131,242,184,201,90,43,206,191,44,93,23,102,245,132,164,213,70,55,125,12,159,238,11,122,233,152,210,163,48,65,231,150,5,116,62,79,220,173,72,57,170,219,145,224,115,2,51,66,209,160,234,155,8,121,156,237,126,15,69,52,167,214,112,1,146,227,169,216,75,58,223,174,61,76,6,119,228,149,181,196,87,38,108,29,142,255,26,107,248,137,195,178,33,80,246,135,20,101,47,94,205,188,89,40,187,202,128,241,98,19,0,114,228,150,213,167,49,67,183,197,83,33,98,16,134,244,115,1,151,229,166,212,66,48,196,182,32,82,17,99,245,135,230,148,2,112,51,65,215,165,81,35,181,199,132,246,96,18,149,231,113,3,64,50,164,214,34,80,198,180,247,133,19,97,209,163,53,71,4,118,224,146,102,20,130,240,179,193,87,37,162,208,70,52,119,5,147,225,21,103,241,131,192,178,36,86,55,69,211,161,226,144,6,116,128,242,100,22,85,39,177,195,68,54,160,210,145,227,117,7,243,129,23,101,38,84,194,176,191,205,91,41,106,24,142,252,8,122,236,158,221,175,57,75,204,190,40,90,25,107,253,143,123,9,159,237,174,220,74,56,89,43,189,207,140,254,104,26,238,156,10,120,59,73,223,173,42,88,206,188,255,141,27,105,157,239,121,11,72,58,172,222,110,28,138,248,187,201,95,45,217,171,61,79,12,126,232,154,29,111,249,139,200,186,44,94,170,216,78,60,127,13,155,233,136,250,108,30,93,47,185,203,63,77,219,169,234,152,14,124,251,137,31,109,46,92,202,184,76,62,168,218,153,235,125,15,0,115,230,149,209,162,55,68,191,204,89,42,110,29,136,251,99,16,133,246,178,193,84,39,220,175,58,73,13,126,235,152,198,181,32,83,23,100,241,130,121,10,159,236,168,219,78,61,165,214,67,48,116,7,146,225,26,105,252,143,203,184,45,94,145,226,119,4,64,51,166,213,46,93,200,187,255,140,25,106,242,129,20,103,35,80,197,182,77,62,171,216,156,239,122,9,87,36,177,194,134,245,96,19,232,155,14,125,57,74,223,172,52,71,210,161,229,150,3,112,139,248,109,30,90,41,188,207,63,76,217,170,238,157,8,123,128,243,102,21,81,34,183,196,92,47,186,201,141,254,107,24,227,144,5,118,50,65,212,167,249,138,31,108,40,91,206,189,70,53,160,211,151,228,113,2,154,233,124,15,75,56,173,222,37,86,195,176,244,135,18,97,174,221,72,59,127,12,153,234,17,98,247,132,192,179,38,85,205,190,43,88,28,111,250,137,114,1,148,231,163,208,69,54,104,27,142,253,185,202,95,44,215,164,49,66,6,117,224,147,11,120,237,158,218,169,60,79,180,199,82,33,101,22,131,240,0,116,232,156,205,185,37,81,135,243,111,27,74,62,162,214,19,103,251,143,222,170,54,66,148,224,124,8,89,45,177,197,38,82,206,186,235,159,3,119,161,213,73,61,108,24,132,240,53,65,221,169,248,140,16,100,178,198,90,46,127,11,151,227,76,56,164,208,129,245,105,29,203,191,35,87,6,114,238,154,95,43,183,195,146,230,122,14,216,172,48,68,21,97,253,137,106,30,130,246,167,211,79,59,237,153,5,113,32,84,200,188,121,13,145,229,180,192,92,40,254,138,22,98,51,71,219,175,152,236,112,4,85,33,189,201,31,107,247,131,210,166,58,78,139,255,99,23,70,50,174,218,12,120,228,144,193,181,41,93,190,202,86,34,115,7,155,239,57,77,209,165,244,128,28,104,173,217,69,49,96,20,136,252,42,94,194,182,231,147,15,123,212,160,60,72,25,109,241,133,83,39,187,207,158,234,118,2,199,179,47,91,10,126,226,150,64,52,168,220,141,249,101,17,242,134,26,110,63,75,215,163,117,1,157,233,184,204,80,36,225,149,9,125,44,88,196,176,102,18,142,250,171,223,67,55,0,117,234,159,201,188,35,86,143,250,101,16,70,51,172,217,3,118,233,156,202,191,32,85,140,249,102,19,69,48,175,218,6,115,236,153,207,186,37,80,137,252,99,22,64,53,170,223,5,112,239,154,204,185,38,83,138,255,96,21,67,54,169,220,12,121,230,147,197,176,47,90,131,246,105,28,74,63,160,213,15,122,229,144,198,179,44,89,128,245,106,31,73,60,163,214,10,127,224,149,195,182,41,92,133,240,111,26,76,57,166,211,9,124,227,150,192,181,42,95,134,243,108,25,79,58,165,208,24,109,242,135,209,164,59,78,151,226,125,8,94,43,180,193,27,110,241,132,210,167,56,77,148,225,126,11,93,40,183,194,30,107,244,129,215,162,61,72,145,228,123,14,88,45,178,199,29,104,247,130,212,161,62,75,146,231,120,13,91,46,177,196,20,97,254,139,221,168,55,66,155,238,113,4,82,39,184,205,23,98,253,136,222,171,52,65,152,237,114,7,81,36,187,206,18,103,248,141,219,174,49,68,157,232,119,2,84,33,190,203,17,100,251,142,216,173,50,71,158,235,116,1,87,34,189,200,0,118,236,154,197,179,41,95,151,225,123,13,82,36,190,200,51,69,223,169,246,128,26,108,164,210,72,62,97,23,141,251,102,16,138,252,163,213,79,57,241,135,29,107,52,66,216,174,85,35,185,207,144,230,124,10,194,180,46,88,7,113,235,157,204,186,32,86,9,127,229,147,91,45,183,193,158,232,114,4,255,137,19,101,58,76,214,160,104,30,132,242,173,219,65,55,170,220,70,48,111,25,131,245,61,75,209,167,248,142,20,98,153,239,117,3,92,42,176,198,14,120,226,148,203,189,39,81,133,243,105,31,64,54,172,218,18,100,254,136,215,161,59,77,182,192,90,44,115,5,159,233,33,87,205,187,228,146,8,126,227,149,15,121,38,80,202,188,116,2,152,238,177,199,93,43,208,166,60,74,21,99,249,143,71,49,171,221,130,244,110,24,73,63,165,211,140,250,96,22,222,168,50,68,27,109,247,129,122,12,150,224,191,201,83,37,237,155,1,119,40,94,196,178,47,89,195,181,234,156,6,112,184,206,84,34,125,11,145,231,28,106,240,134,217,175,53,67,139,253,103,17,78,56,162,212,0,119,238,153,193,182,47,88,159,232,113,6,94,41,176,199,35,84,205,186,226,149,12,123,188,203,82,37,125,10,147,228,70,49,168,223,135,240,105,30,217,174,55,64,24,111,246,129,101,18,139,252,164,211,74,61,250,141,20,99,59,76,213,162,140,251,98,21,77,58,163,212,19,100,253,138,210,165,60,75,175,216,65,54,110,25,128,247,48,71,222,169,241,134,31,104,202,189,36,83,11,124,229,146,85,34,187,204,148,227,122,13,233,158,7,112,40,95,198,177,118,1,152,239,183,192,89,46,5,114,235,156,196,179,42,93,154,237,116,3,91,44,181,194,38,81,200,191,231,144,9,126,185,206,87,32,120,15,150,225,67,52,173,218,130,245,108,27,220,171,50,69,29,106,243,132,96,23,142,249,161,214,79,56,255,136,17,102,62,73,208,167,137,254,103,16,72,63,166,209,22,97,248,143,215,160,57,78,170,221,68,51,107,28,133,242,53,66,219,172,244,131,26,109,207,184,33,86,14,121,224,151,80,39,190,201,145,230,127,8,236,155,2,117,45,90,195,180,115,4,157,234,178,197,92,43,0,120,240,136,253,133,13,117,231,159,23,111,26,98,234,146,211,171,35,91,46,86,222,166,52,76,196,188,201,177,57,65,187,195,75,51,70,62,182,206,92,36,172,212,161,217,81,41,104,16,152,224,149,237,101,29,143,247,127,7,114,10,130,250,107,19,155,227,150,238,102,30,140,244,124,4,113,9,129,249,184,192,72,48,69,61,181,205,95,39,175,215,162,218,82,42,208,168,32,88,45,85,221,165,55,79,199,191,202,178,58,66,3,123,243,139,254,134,14,118,228,156,20,108,25,97,233,145,214,174,38,94,43,83,219,163,49,73,193,185,204,180,60,68,5,125,245,141,248,128,8,112,226,154,18,106,31,103,239,151,109,21,157,229,144,232,96,24,138,242,122,2,119,15,135,255,190,198,78,54,67,59,179,203,89,33,169,209,164,220,84,44,189,197,77,53,64,56,176,200,90,34,170,210,167,223,87,47,110,22,158,230,147,235,99,27,137,241,121,1,116,12,132,252,6,126,246,142,251,131,11,115,225,153,17,105,28,100,236,148,213,173,37,93,40,80,216,160,50,74,194,186,207,183,63,71,0,121,242,139,249,128,11,114,239,150,29,100,22,111,228,157,195,186,49,72,58,67,200,177,44,85,222,167,213,172,39,94,155,226,105,16,98,27,144,233,116,13,134,255,141,244,127,6,88,33,170,211,161,216,83,42,183,206,69,60,78,55,188,197,43,82,217,160,210,171,32,89,196,189,54,79,61,68,207,182,232,145,26,99,17,104,227,154,7,126,245,140,254,135,12,117,176,201,66,59,73,48,187,194,95,38,173,212,166,223,84,45,115,10,129,248,138,243,120,1,156,229,110,23,101,28,151,238,86,47,164,221,175,214,93,36,185,192,75,50,64,57,178,203,149,236,103,30,108,21,158,231,122,3,136,241,131,250,113,8,205,180,63,70,52,77,198,191,34,91,208,169,219,162,41,80,14,119,252,133,247,142,5,124,225,152,19,106,24,97,234,147,125,4,143,246,132,253,118,15,146,235,96,25,107,18,153,224,190,199,76,53,71,62,181,204,81,40,163,218,168,209,90,35,230,159,20,109,31,102,237,148,9,112,251,130,240,137,2,123,37,92,215,174,220,165,46,87,202,179,56,65,51,74,193,184,0,122,244,142,245,143,1,123,247,141,3,121,2,120,246,140,243,137,7,125,6,124,242,136,4,126,240,138,241,139,5,127,251,129,15,117,14,116,250,128,12,118,248,130,249,131,13,119,8,114,252,134,253,135,9,115,255,133,11,113,10,112,254,132,235,145,31,101,30,100,234,144,28,102,232,146,233,147,29,103,24,98,236,150,237,151,25,99,239,149,27,97,26,96,238,148,16,106,228,158,229,159,17,107,231,157,19,105,18,104,230,156,227,153,23,109,22,108,226,152,20,110,224,154,225,155,21,111,203,177,63,69,62,68,202,176,60,70,200,178,201,179,61,71,56,66,204,182,205,183,57,67,207,181,59,65,58,64,206,180,48,74,196,190,197,191,49,75,199,189,51,73,50,72,198,188,195,185,55,77,54,76,194,184,52,78,192,186,193,187,53,79,32,90,212,174,213,175,33,91,215,173,35,89,34,88,214,172,211,169,39,93,38,92,210,168,36,94,208,170,209,171,37,95,219,161,47,85,46,84,218,160,44,86,216,162,217,163,45,87,40,82,220,166,221,167,41,83,223,165,43,81,42,80,222,164,0,123,246,141,241,138,7,124,255,132,9,114,14,117,248,131,227,152,21,110,18,105,228,159,28,103,234,145,237,150,27,96,219,160,45,86,42,81,220,167,36,95,210,169,213,174,35,88,56,67,206,181,201,178,63,68,199,188,49,74,54,77,192,187,171,208,93,38,90,33,172,215,84,47,162,217,165,222,83,40,72,51,190,197,185,194,79,52,183,204,65,58,70,61,176,203,112,11,134,253,129,250,119,12,143,244,121,2,126,5,136,243,147,232,101,30,98,25,148,239,108,23,154,225,157,230,107,16,75,48,189,198,186,193,76,55,180,207,66,57,69,62,179,200,168,211,94,37,89,34,175,212,87,44,161,218,166,221,80,43,144,235,102,29,97,26,151,236,111,20,153,226,158,229,104,19,115,8,133,254,130,249,116,15,140,247,122,1,125,6,139,240,224,155,22,109,17,106,231,156,31,100,233,146,238,149,24,99,3,120,245,142,242,137,4,127,252,135,10,113,13,118,251,128,59,64,205,182,202,177,60,71,196,191,50,73,53,78,195,184,216,163,46,85,41,82,223,164,39,92,209,170,214,173,32,91,0,124,248,132,237,145,21,105,199,187,63,67,42,86,210,174,147,239,107,23,126,2,134,250,84,40,172,208,185,197,65,61,59,71,195,191,214,170,46,82,252,128,4,120,17,109,233,149,168,212,80,44,69,57,189,193,111,19,151,235,130,254,122,6,118,10,142,242,155,231,99,31,177,205,73,53,92,32,164,216,229,153,29,97,8,116,240,140,34,94,218,166,207,179,55,75,77,49,181,201,160,220,88,36,138,246,114,14,103,27,159,227,222,162,38,90,51,79,203,183,25,101,225,157,244,136,12,112,236,144,20,104,1,125,249,133,43,87,211,175,198,186,62,66,127,3,135,251,146,238,106,22,184,196,64,60,85,41,173,209,215,171,47,83,58,70,194,190,16,108,232,148,253,129,5,121,68,56,188,192,169,213,81,45,131,255,123,7,110,18,150,234,154,230,98,30,119,11,143,243,93,33,165,217,176,204,72,52,9,117,241,141,228,152,28,96,206,178,54,74,35,95,219,167,161,221,89,37,76,48,180,200,102,26,158,226,139,247,115,15,50,78,202,182,223,163,39,91,245,137,13,113,24,100,224,156,0,125,250,135,233,148,19,110,207,178,53,72,38,91,220,161,131,254,121,4,106,23,144,237,76,49,182,203,165,216,95,34,27,102,225,156,242,143,8,117,212,169,46,83,61,64,199,186,152,229,98,31,113,12,139,246,87,42,173,208,190,195,68,57,54,75,204,177,223,162,37,88,249,132,3,126,16,109,234,151,181,200,79,50,92,33,166,219,122,7,128,253,147,238,105,20,45,80,215,170,196,185,62,67,226,159,24,101,11,118,241,140,174,211,84,41,71,58,189,192,97,28,155,230,136,245,114,15,108,17,150,235,133,248,127,2,163,222,89,36,74,55,176,205,239,146,21,104,6,123,252,129,32,93,218,167,201,180,51,78,119,10,141,240,158,227,100,25,184,197,66,63,81,44,171,214,244,137,14,115,29,96,231,154,59,70,193,188,210,175,40,85,90,39,160,221,179,206,73,52,149,232,111,18,124,1,134,251,217,164,35,94,48,77,202,183,22,107,236,145,255,130,5,120,65,60,187,198,168,213,82,47,142,243,116,9,103,26,157,224,194,191,56,69,43,86,209,172,13,112,247,138,228,153,30,99,0,126,252,130,229,155,25,103,215,169,43,85,50,76,206,176,179,205,79,49,86,40,170,212,100,26,152,230,129,255,125,3,123,5,135,249,158,224,98,28,172,210,80,46,73,55,181,203,200,182,52,74,45,83,209,175,31,97,227,157,250,132,6,120,246,136,10,116,19,109,239,145,33,95,221,163,196,186,56,70,69,59,185,199,160,222,92,34,146,236,110,16,119,9,139,245,141,243,113,15,104,22,148,234,90,36,166,216,191,193,67,61,62,64,194,188,219,165,39,89,233,151,21,107,12,114,240,142,241,143,13,115,20,106,232,150,38,88,218,164,195,189,63,65,66,60,190,192,167,217,91,37,149,235,105,23,112,14,140,242,138,244,118,8,111,17,147,237,93,35,161,223,184,198,68,58,57,71,197,187,220,162,32,94,238,144,18,108,11,117,247,137,7,121,251,133,226,156,30,96,208,174,44,82,53,75,201,183,180,202,72,54,81,47,173,211,99,29,159,225,134,248,122,4,124,2,128,254,153,231,101,27,171,213,87,41,78,48,178,204,207,177,51,77,42,84,214,168,24,102,228,154,253,131,1,127,0,127,254,129,225,158,31,96,223,160,33,94,62,65,192,191,163,220,93,34,66,61,188,195,124,3,130,253,157,226,99,28,91,36,165,218,186,197,68,59,132,251,122,5,101,26,155,228,248,135,6,121,25,102,231,152,39,88,217,166,198,185,56,71,182,201,72,55,87,40,169,214,105,22,151,232,136,247,118,9,21,106,235,148,244,139,10,117,202,181,52,75,43,84,213,170,237,146,19,108,12,115,242,141,50,77,204,179,211,172,45,82,78,49,176,207,175,208,81,46,145,238,111,16,112,15,142,241,113,14,143,240,144,239,110,17,174,209,80,47,79,48,177,206,210,173,44,83,51,76,205,178,13,114,243,140,236,147,18,109,42,85,212,171,203,180,53,74,245,138,11,116,20,107,234,149,137,246,119,8,104,23,150,233,86,41,168,215,183,200,73,54,199,184,57,70,38,89,216,167,24,103,230,153,249,134,7,120,100,27,154,229,133,250,123,4,187,196,69,58,90,37,164,219,156,227,98,29,125,2,131,252,67,60,189,194,162,221,92,35,63,64,193,190,222,161,32,95,224,159,30,97,1,126,255,128,0,128,29,157,58,186,39,167,116,244,105,233,78,206,83,211,232,104,245,117,210,82,207,79,156,28,129,1,166,38,187,59,205,77,208,80,247,119,234,106,185,57,164,36,131,3,158,30,37,165,56,184,31,159,2,130,81,209,76,204,107,235,118,246,135,7,154,26,189,61,160,32,243,115,238,110,201,73,212,84,111,239,114,242,85,213,72,200,27,155,6,134,33,161,60,188,74,202,87,215,112,240,109,237,62,190,35,163,4,132,25,153,162,34,191,63,152,24,133,5,214,86,203,75,236,108,241,113,19,147,14,142,41,169,52,180,103,231,122,250,93,221,64,192,251,123,230,102,193,65,220,92,143,15,146,18,181,53,168,40,222,94,195,67,228,100,249,121,170,42,183,55,144,16,141,13,54,182,43,171,12,140,17,145,66,194,95,223,120,248,101,229,148,20,137,9,174,46,179,51,224,96,253,125,218,90,199,71,124,252,97,225,70,198,91,219,8,136,21,149,50,178,47,175,89,217,68,196,99,227,126,254,45,173,48,176,23,151,10,138,177,49,172,44,139,11,150,22,197,69,216,88,255,127,226,98,0,129,31,158,62,191,33,160,124,253,99,226,66,195,93,220,248,121,231,102,198,71,217,88,132,5,155,26,186,59,165,36,237,108,242,115,211,82,204,77,145,16,142,15,175,46,176,49,21,148,10,139,43,170,52,181,105,232,118,247,87,214,72,201,199,70,216,89,249,120,230,103,187,58,164,37,133,4,154,27,63,190,32,161,1,128,30,159,67,194,92,221,125,252,98,227,42,171,53,180,20,149,11,138,86,215,73,200,104,233,119,246,210,83,205,76,236,109,243,114,174,47,177,48,144,17,143,14,147,18,140,13,173,44,178,51,239,110,240,113,209,80,206,79,107,234,116,245,85,212,74,203,23,150,8,137,41,168,54,183,126,255,97,224,64,193,95,222,2,131,29,156,60,189,35,162,134,7,153,24,184,57,167,38,250,123,229,100,196,69,219,90,84,213,75,202,106,235,117,244,40,169,55,182,22,151,9,136,172,45,179,50,146,19,141,12,208,81,207,78,238,111,241,112,185,56,166,39,135,6,152,25,197,68,218,91,251,122,228,101,65,192,94,223,127,254,96,225,61,188,34,163,3,130,28,157,0,130,25,155,50,176,43,169,100,230,125,255,86,212,79,205,200,74,209,83,250,120,227,97,172,46,181,55,158,28,135,5,141,15,148,22,191,61,166,36,233,107,240,114,219,89,194,64,69,199,92,222,119,245,110,236,33,163,56,186,19,145,10,136,7,133,30,156,53,183,44,174,99,225,122,248,81,211,72,202,207,77,214,84,253,127,228,102,171,41,178,48,153,27,128,2,138,8,147,17,184,58,161,35,238,108,247,117,220,94,197,71,66,192,91,217,112,242,105,235,38,164,63,189,20,150,13,143,14,140,23,149,60,190,37,167,106,232,115,241,88,218,65,195,198,68,223,93,244,118,237,111,162,32,187,57,144,18,137,11,131,1,154,24,177,51,168,42,231,101,254,124,213,87,204,78,75,201,82,208,121,251,96,226,47,173,54,180,29,159,4,134,9,139,16,146,59,185,34,160,109,239,116,246,95,221,70,196,193,67,216,90,243,113,234,104,165,39,188,62,151,21,142,12,132,6,157,31,182,52,175,45,224,98,249,123,210,80,203,73,76,206,85,215,126,252,103,229,40,170,49,179,26,152,3,129,0,131,27,152,54,181,45,174,108,239,119,244,90,217,65,194,216,91,195,64,238,109,245,118,180,55,175,44,130,1,153,26,173,46,182,53,155,24,128,3,193,66,218,89,247,116,236,111,117,246,110,237,67,192,88,219,25,154,2,129,47,172,52,183,71,196,92,223,113,242,106,233,43,168,48,179,29,158,6,133,159,28,132,7,169,42,178,49,243,112,232,107,197,70,222,93,234,105,241,114,220,95,199,68,134,5,157,30,176,51,171,40,50,177,41,170,4,135,31,156,94,221,69,198,104,235,115,240,142,13,149,22,184,59,163,32,226,97,249,122,212,87,207,76,86,213,77,206,96,227,123,248,58,185,33,162,12,143,23,148,35,160,56,187,21,150,14,141,79,204,84,215,121,250,98,225,251,120,224,99,205,78,214,85,151,20,140,15,161,34,186,57,201,74,210,81,255,124,228,103,165,38,190,61,147,16,136,11,17,146,10,137,39,164,60,191,125,254,102,229,75,200,80,211,100,231,127,252,82,209,73,202,8,139,19,144,62,189,37,166,188,63,167,36,138,9,145,18,208,83,203,72,230,101,253,126,0,132,21,145,42,174,63,187,84,208,65,197,126,250,107,239,168,44,189,57,130,6,151,19,252,120,233,109,214,82,195,71,77,201,88,220,103,227,114,246,25,157,12,136,51,183,38,162,229,97,240,116,207,75,218,94,177,53,164,32,155,31,142,10,154,30,143,11,176,52,165,33,206,74,219,95,228,96,241,117,50,182,39,163,24,156,13,137,102,226,115,247,76,200,89,221,215,83,194,70,253,121,232,108,131,7,150,18,169,45,188,56,127,251,106,238,85,209,64,196,43,175,62,186,1,133,20,144,41,173,60,184,3,135,22,146,125,249,104,236,87,211,66,198,129,5,148,16,171,47,190,58,213,81,192,68,255,123,234,110,100,224,113,245,78,202,91,223,48,180,37,161,26,158,15,139,204,72,217,93,230,98,243,119,152,28,141,9,178,54,167,35,179,55,166,34,153,29,140,8,231,99,242,118,205,73,216,92,27,159,14,138,49,181,36,160,79,203,90,222,101,225,112,244,254,122,235,111,212,80,193,69,170,46,191,59,128,4,149,17,86,210,67,199,124,248,105,237,2,134,23,147,40,172,61,185,0,133,23,146,46,171,57,188,92,217,75,206,114,247,101,224,184,61,175,42,150,19,129,4,228,97,243,118,202,79,221,88,109,232,122,255,67,198,84,209,49,180,38,163,31,154,8,141,213,80,194,71,251,126,236,105,137,12,158,27,167,34,176,53,218,95,205,72,244,113,227,102,134,3,145,20,168,45,191,58,98,231,117,240,76,201,91,222,62,187,41,172,16,149,7,130,183,50,160,37,153,28,142,11,235,110,252,121,197,64,210,87,15,138,24,157,33,164,54,179,83,214,68,193,125,248,106,239,169,44,190,59,135,2,144,21,245,112,226,103,219,94,204,73,17,148,6,131,63,186,40,173,77,200,90,223,99,230,116,241,196,65,211,86,234,111,253,120,152,29,143,10,182,51,161,36,124,249,107,238,82,215,69,192,32,165,55,178,14,139,25,156,115,246,100,225,93,216,74,207,47,170,56,189,1,132,22,147,203,78,220,89,229,96,242,119,151,18,128,5,185,60,174,43,30,155,9,140,48,181,39,162,66,199,85,208,108,233,123,254,166,35,177,52,136,13,159,26,250,127,237,104,212,81,195,70,0,134,17,151,34,164,51,181,68,194,85,211,102,224,119,241,136,14,153,31,170,44,187,61,204,74,221,91,238,104,255,121,13,139,28,154,47,169,62,184,73,207,88,222,107,237,122,252,133,3,148,18,167,33,182,48,193,71,208,86,227,101,242,116,26,156,11,141,56,190,41,175,94,216,79,201,124,250,109,235,146,20,131,5,176,54,161,39,214,80,199,65,244,114,229,99,23,145,6,128,53,179,36,162,83,213,66,196,113,247,96,230,159,25,142,8,189,59,172,42,219,93,202,76,249,127,232,110,52,178,37,163,22,144,7,129,112,246,97,231,82,212,67,197,188,58,173,43,158,24,143,9,248,126,233,111,218,92,203,77,57,191,40,174,27,157,10,140,125,251,108,234,95,217,78,200,177,55,160,38,147,21,130,4,245,115,228,98,215,81,198,64,46,168,63,185,12,138,29,155,106,236,123,253,72,206,89,223,166,32,183,49,132,2,149,19,226,100,243,117,192,70,209,87,35,165,50,180,1,135,16,150,103,225,118,240,69,195,84,210,171,45,186,60,137,15,152,30,239,105,254,120,205,75,220,90,0,135,19,148,38,161,53,178,76,203,95,216,106,237,121,254,152,31,139,12,190,57,173,42,212,83,199,64,242,117,225,102,45,170,62,185,11,140,24,159,97,230,114,245,71,192,84,211,181,50,166,33,147,20,128,7,249,126,234,109,223,88,204,75,90,221,73,206,124,251,111,232,22,145,5,130,48,183,35,164,194,69,209,86,228,99,247,112,142,9,157,26,168,47,187,60,119,240,100,227,81,214,66,197,59,188,40,175,29,154,14,137,239,104,252,123,201,78,218,93,163,36,176,55,133,2,150,17,180,51,167,32,146,21,129,6,248,127,235,108,222,89,205,74,44,171,63,184,10,141,25,158,96,231,115,244,70,193,85,210,153,30,138,13,191,56,172,43,213,82,198,65,243,116,224,103,1,134,18,149,39,160,52,179,77,202,94,217,107,236,120,255,238,105,253,122,200,79,219,92,162,37,177,54,132,3,151,16,118,241,101,226,80,215,67,196,58,189,41,174,28,155,15,136,195,68,208,87,229,98,246,113,143,8,156,27,169,46,186,61,91,220,72,207,125,250,110,233,23,144,4,131,49,182,34,165,0,136,13,133,26,146,23,159,52,188,57,177,46,166,35,171,104,224,101,237,114,250,127,247,92,212,81,217,70,206,75,195,208,88,221,85,202,66,199,79,228,108,233,97,254,118,243,123,184,48,181,61,162,42,175,39,140,4,129,9,150,30,155,19,189,53,176,56,167,47,170,34,137,1,132,12,147,27,158,22,213,93,216,80,207,71,194,74,225,105,236,100,251,115,246,126,109,229,96,232,119,255,122,242,89,209,84,220,67,203,78,198,5,141,8,128,31,151,18,154,49,185,60,180,43,163,38,174,103,239,106,226,125,245,112,248,83,219,94,214,73,193,68,204,15,135,2,138,21,157,24,144,59,179,54,190,33,169,44,164,183,63,186,50,173,37,160,40,131,11,142,6,153,17,148,28,223,87,210,90,197,77,200,64,235,99,230,110,241,121,252,116,218,82,215,95,192,72,205,69,238,102,227,107,244,124,249,113,178,58,191,55,168,32,165,45,134,14,139,3,156,20,145,25,10,130,7,143,16,152,29,149,62,182,51,187,36,172,41,161,98,234,111,231,120,240,117,253,86,222,91,211,76,196,65,201,0,137,15,134,30,151,17,152,60,181,51,186,34,171,45,164,120,241,119,254,102,239,105,224,68,205,75,194,90,211,85,220,240,121,255,118,238,103,225,104,204,69,195,74,210,91,221,84,136,1,135,14,150,31,153,16,180,61,187,50,170,35,165,44,253,116,242,123,227,106,236,101,193,72,206,71,223,86,208,89,133,12,138,3,155,18,148,29,185,48,182,63,167,46,168,33,13,132,2,139,19,154,28,149,49,184,62,183,47,166,32,169,117,252,122,243,107,226,100,237,73,192,70,207,87,222,88,209,231,110,232,97,249,112,246,127,219,82,212,93,197,76,202,67,159,22,144,25,129,8,142,7,163,42,172,37,189,52,178,59,23,158,24,145,9,128,6,143,43,162,36,173,53,188,58,179,111,230,96,233,113,248,126,247,83,218,92,213,77,196,66,203,26,147,21,156,4,141,11,130,38,175,41,160,56,177,55,190,98,235,109,228,124,245,115,250,94,215,81,216,64,201,79,198,234,99,229,108,244,125,251,114,214,95,217,80,200,65,199,78,146,27,157,20,140,5,131,10,174,39,161,40,176,57,191,54,0,138,9,131,18,152,27,145,36,174,45,167,54,188,63,181,72,194,65,203,90,208,83,217,108,230,101,239,126,244,119,253,144,26,153,19,130,8,139,1,180,62,189,55,166,44,175,37,216,82,209,91,202,64,195,73,252,118,245,127,238,100,231,109,61,183,52,190,47,165,38,172,25,147,16,154,11,129,2,136,117,255,124,246,103,237,110,228,81,219,88,210,67,201,74,192,173,39,164,46,191,53,182,60,137,3,128,10,155,17,146,24,229,111,236,102,247,125,254,116,193,75,200,66,211,89,218,80,122,240,115,249,104,226,97,235,94,212,87,221,76,198,69,207,50,184,59,177,32,170,41,163,22,156,31,149,4,142,13,135,234,96,227,105,248,114,241,123,206,68,199,77,220,86,213,95,162,40,171,33,176,58,185,51,134,12,143,5,148,30,157,23,71,205,78,196,85,223,92,214,99,233,106,224,113,251,120,242,15,133,6,140,29,151,20,158,43,161,34,168,57,179,48,186,215,93,222,84,197,79,204,70,243,121,250,112,225,107,232,98,159,21,150,28,141,7,132,14,187,49,178,56,169,35,160,42,0,139,11,128,22,157,29,150,44,167,39,172,58,177,49,186,88,211,83,216,78,197,69,206,116,255,127,244,98,233,105,226,176,59,187,48,166,45,173,38,156,23,151,28,138,1,129,10,232,99,227,104,254,117,245,126,196,79,207,68,210,89,217,82,125,246,118,253,107,224,96,235,81,218,90,209,71,204,76,199,37,174,46,165,51,184,56,179,9,130,2,137,31,148,20,159,205,70,198,77,219,80,208,91,225,106,234,97,247,124,252,119,149,30,158,21,131,8,136,3,185,50,178,57,175,36,164,47,250,113,241,122,236,103,231,108,214,93,221,86,192,75,203,64,162,41,169,34,180,63,191,52,142,5,133,14,152,19,147,24,74,193,65,202,92,215,87,220,102,237,109,230,112,251,123,240,18,153,25,146,4,143,15,132,62,181,53,190,40,163,35,168,135,12,140,7,145,26,154,17,171,32,160,43,189,54,182,61,223,84,212,95,201,66,194,73,243,120,248,115,229,110,238,101,55,188,60,183,33,170,42,161,27,144,16,155,13,134,6,141,111,228,100,239,121,242,114,249,67,200,72,195,85,222,94,213,0,140,5,137,10,134,15,131,20,152,17,157,30,146,27,151,40,164,45,161,34,174,39,171,60,176,57,181,54,186,51,191,80,220,85,217,90,214,95,211,68,200,65,205,78,194,75,199,120,244,125,241,114,254,119,251,108,224,105,229,102,234,99,239,160,44,165,41,170,38,175,35,180,56,177,61,190,50,187,55,136,4,141,1,130,14,135,11,156,16,153,21,150,26,147,31,240,124,245,121,250,118,255,115,228,104,225,109,238,98,235,103,216,84,221,81,210,94,215,91,204,64,201,69,198,74,195,79,93,209,88,212,87,219,82,222,73,197,76,192,67,207,70,202,117,249,112,252,127,243,122,246,97,237,100,232,107,231,110,226,13,129,8,132,7,139,2,142,25,149,28,144,19,159,22,154,37,169,32,172,47,163,42,166,49,189,52,184,59,183,62,178,253,113,248,116,247,123,242,126,233,101,236,96,227,111,230,106,213,89,208,92,223,83,218,86,193,77,196,72,203,71,206,66,173,33,168,36,167,43,162,46,185,53,188,48,179,63,182,58,133,9,128,12,143,3,138,6,145,29,148,24,155,23,158,18,0,141,7,138,14,131,9,132,28,145,27,150,18,159,21,152,56,181,63,178,54,187,49,188,36,169,35,174,42,167,45,160,112,253,119,250,126,243,121,244,108,225,107,230,98,239,101,232,72,197,79,194,70,203,65,204,84,217,83,222,90,215,93,208,224,109,231,106,238,99,233,100,252,113,251,118,242,127,245,120,216,85,223,82,214,91,209,92,196,73,195,78,202,71,205,64,144,29,151,26,158,19,153,20,140,1,139,6,130,15,133,8,168,37,175,34,166,43,161,44,180,57,179,62,186,55,189,48,221,80,218,87,211,94,212,89,193,76,198,75,207,66,200,69,229,104,226,111,235,102,236,97,249,116,254,115,247,122,240,125,173,32,170,39,163,46,164,41,177,60,182,59,191,50,184,53,149,24,146,31,155,22,156,17,137,4,142,3,135,10,128,13,61,176,58,183,51,190,52,185,33,172,38,171,47,162,40,165,5,136,2,143,11,134,12,129,25,148,30,147,23,154,16,157,77,192,74,199,67,206,68,201,81,220,86,219,95,210,88,213,117,248,114,255,123,246,124,241,105,228,110,227,103,234,96,237,0,142,1,143,2,140,3,141,4,138,5,139,6,136,7,137,8,134,9,135,10,132,11,133,12,130,13,131,14,128,15,129,16,158,17,159,18,156,19,157,20,154,21,155,22,152,23,153,24,150,25,151,26,148,27,149,28,146,29,147,30,144,31,145,32,174,33,175,34,172,35,173,36,170,37,171,38,168,39,169,40,166,41,167,42,164,43,165,44,162,45,163,46,160,47,161,48,190,49,191,50,188,51,189,52,186,53,187,54,184,55,185,56,182,57,183,58,180,59,181,60,178,61,179,62,176,63,177,64,206,65,207,66,204,67,205,68,202,69,203,70,200,71,201,72,198,73,199,74,196,75,197,76,194,77,195,78,192,79,193,80,222,81,223,82,220,83,221,84,218,85,219,86,216,87,217,88,214,89,215,90,212,91,213,92,210,93,211,94,208,95,209,96,238,97,239,98,236,99,237,100,234,101,235,102,232,103,233,104,230,105,231,106,228,107,229,108,226,109,227,110,224,111,225,112,254,113,255,114,252,115,253,116,250,117,251,118,248,119,249,120,246,121,247,122,244,123,245,124,242,125,243,126,240,127,241,0,143,3,140,6,137,5,138,12,131,15,128,10,133,9,134,24,151,27,148,30,145,29,146,20,155,23,152,18,157,17,158,48,191,51,188,54,185,53,186,60,179,63,176,58,181,57,182,40,167,43,164,46,161,45,162,36,171,39,168,34,173,33,174,96,239,99,236,102,233,101,234,108,227,111,224,106,229,105,230,120,247,123,244,126,241,125,242,116,251,119,248,114,253,113,254,80,223,83,220,86,217,85,218,92,211,95,208,90,213,89,214,72,199,75,196,78,193,77,194,68,203,71,200,66,205,65,206,192,79,195,76,198,73,197,74,204,67,207,64,202,69,201,70,216,87,219,84,222,81,221,82,212,91,215,88,210,93,209,94,240,127,243,124,246,121,245,122,252,115,255,112,250,117,249,118,232,103,235,100,238,97,237,98,228,107,231,104,226,109,225,110,160,47,163,44,166,41,165,42,172,35,175,32,170,37,169,38,184,55,187,52,190,49,189,50,180,59,183,56,178,61,177,62,144,31,147,28,150,25,149,26,156,19,159,16,154,21,153,22,136,7,139,4,142,1,141,2,132,11,135,8,130,13,129,14,0,144,61,173,122,234,71,215,244,100,201,89,142,30,179,35,245,101,200,88,143,31,178,34,1,145,60,172,123,235,70,214,247,103,202,90,141,29,176,32,3,147,62,174,121,233,68,212,2,146,63,175,120,232,69,213,246,102,203,91,140,28,177,33,243,99,206,94,137,25,180,36,7,151,58,170,125,237,64,208,6,150,59,171,124,236,65,209,242,98,207,95,136,24,181,37,4,148,57,169,126,238,67,211,240,96,205,93,138,26,183,39,241,97,204,92,139,27,182,38,5,149,56,168,127,239,66,210,251,107,198,86,129,17,188,44,15,159,50,162,117,229,72,216,14,158,51,163,116,228,73,217,250,106,199,87,128,16,189,45,12,156,49,161,118,230,75,219,248,104,197,85,130,18,191,47,249,105,196,84,131,19,190,46,13,157,48,160,119,231,74,218,8,152,53,165,114,226,79,223,252,108,193,81,134,22,187,43,253,109,192,80,135,23,186,42,9,153,52,164,115,227,78,222,255,111,194,82,133,21,184,40,11,155,54,166,113,225,76,220,10,154,55,167,112,224,77,221,254,110,195,83,132,20,185,41,0,145,63,174,126,239,65,208,252,109,195,82,130,19,189,44,229,116,218,75,155,10,164,53,25,136,38,183,103,246,88,201,215,70,232,121,169,56,150,7,43,186,20,133,85,196,106,251,50,163,13,156,76,221,115,226,206,95,241,96,176,33,143,30,179,34,140,29,205,92,242,99,79,222,112,225,49,160,14,159,86,199,105,248,40,185,23,134,170,59,149,4,212,69,235,122,100,245,91,202,26,139,37,180,152,9,167,54,230,119,217,72,129,16,190,47,255,110,192,81,125,236,66,211,3,146,60,173,123,234,68,213,5,148,58,171,135,22,184,41,249,104,198,87,158,15,161,48,224,113,223,78,98,243,93,204,28,141,35,178,172,61,147,2,210,67,237,124,80,193,111,254,46,191,17,128,73,216,118,231,55,166,8,153,181,36,138,27,203,90,244,101,200,89,247,102,182,39,137,24,52,165,11,154,74,219,117,228,45,188,18,131,83,194,108,253,209,64,238,127,175,62,144,1,31,142,32,177,97,240,94,207,227,114,220,77,157,12,162,51,250,107,197,84,132,21,187,42,6,151,57,168,120,233,71,214,0,146,57,171,114,224,75,217,228,118,221,79,150,4,175,61,213,71,236,126,167,53,158,12,49,163,8,154,67,209,122,232,183,37,142,28,197,87,252,110,83,193,106,248,33,179,24,138,98,240,91,201,16,130,41,187,134,20,191,45,244,102,205,95,115,225,74,216,1,147,56,170,151,5,174,60,229,119,220,78,166,52,159,13,212,70,237,127,66,208,123,233,48,162,9,155,196,86,253,111,182,36,143,29,32,178,25,139,82,192,107,249,17,131,40,186,99,241,90,200,245,103,204,94,135,21,190,44,230,116,223,77,148,6,173,63,2,144,59,169,112,226,73,219,51,161,10,152,65,211,120,234,215,69,238,124,165,55,156,14,81,195,104,250,35,177,26,136,181,39,140,30,199,85,254,108,132,22,189,47,246,100,207,93,96,242,89,203,18,128,43,185,149,7,172,62,231,117,222,76,113,227,72,218,3,145,58,168,64,210,121,235,50,160,11,153,164,54,157,15,214,68,239,125,34,176,27,137,80,194,105,251,198,84,255,109,180,38,141,31,247,101,206,92,133,23,188,46,19,129,42,184,97,243,88,202,0,147,59,168,118,229,77,222,236,127,215,68,154,9,161,50,197,86,254,109,179,32,136,27,41,186,18,129,95,204,100,247,151,4,172,63,225,114,218,73,123,232,64,211,13,158,54,165,82,193,105,250,36,183,31,140,190,45,133,22,200,91,243,96,51,160,8,155,69,214,126,237,223,76,228,119,169,58,146,1,246,101,205,94,128,19,187,40,26,137,33,178,108,255,87,196,164,55,159,12,210,65,233,122,72,219,115,224,62,173,5,150,97,242,90,201,23,132,44,191,141,30,182,37,251,104,192,83,102,245,93,206,16,131,43,184,138,25,177,34,252,111,199,84,163,48,152,11,213,70,238,125,79,220,116,231,57,170,2,145,241,98,202,89,135,20,188,47,29,142,38,181,107,248,80,195,52,167,15,156,66,209,121,234,216,75,227,112,174,61,149,6,85,198,110,253,35,176,24,139,185,42,130,17,207,92,244,103,144,3,171,56,230,117,221,78,124,239,71,212,10,153,49,162,194,81,249,106,180,39,143,28,46,189,21,134,88,203,99,240,7,148,60,175,113,226,74,217,235,120,208,67,157,14,166,53,0,148,53,161,106,254,95,203,212,64,225,117,190,42,139,31,181,33,128,20,223,75,234,126,97,245,84,192,11,159,62,170,119,227,66,214,29,137,40,188,163,55,150,2,201,93,252,104,194,86,247,99,168,60,157,9,22,130,35,183,124,232,73,221,238,122,219,79,132,16,177,37,58,174,15,155,80,196,101,241,91,207,110,250,49,165,4,144,143,27,186,46,229,113,208,68,153,13,172,56,243,103,198,82,77,217,120,236,39,179,18,134,44,184,25,141,70,210,115,231,248,108,205,89,146,6,167,51,193,85,244,96,171,63,158,10,21,129,32,180,127,235,74,222,116,224,65,213,30,138,43,191,160,52,149,1,202,94,255,107,182,34,131,23,220,72,233,125,98,246,87,195,8,156,61,169,3,151,54,162,105,253,92,200,215,67,226,118,189,41,136,28,47,187,26,142,69,209,112,228,251,111,206,90,145,5,164,48,154,14,175,59,240,100,197,81,78,218,123,239,36,176,17,133,88,204,109,249,50,166,7,147,140,24,185,45,230,114,211,71,237,121,216,76,135,19,178,38,57,173,12,152,83,199,102,242,0,149,55,162,110,251,89,204,220,73,235,126,178,39,133,16,165,48,146,7,203,94,252,105,121,236,78,219,23,130,32,181,87,194,96,245,57,172,14,155,139,30,188,41,229,112,210,71,242,103,197,80,156,9,171,62,46,187,25,140,64,213,119,226,174,59,153,12,192,85,247,98,114,231,69,208,28,137,43,190,11,158,60,169,101,240,82,199,215,66,224,117,185,44,142,27,249,108,206,91,151,2,160,53,37,176,18,135,75,222,124,233,92,201,107,254,50,167,5,144,128,21,183,34,238,123,217,76,65,212,118,227,47,186,24,141,157,8,170,63,243,102,196,81,228,113,211,70,138,31,189,40,56,173,15,154,86,195,97,244,22,131,33,180,120,237,79,218,202,95,253,104,164,49,147,6,179,38,132,17,221,72,234,127,111,250,88,205,1,148,54,163,239,122,216,77,129,20,182,35,51,166,4,145,93,200,106,255,74,223,125,232,36,177,19,134,150,3,161,52,248,109,207,90,184,45,143,26,214,67,225,116,100,241,83,198,10,159,61,168,29,136,42,191,115,230,68,209,193,84,246,99,175,58,152,13,0,150,49,167,98,244,83,197,196,82,245,99,166,48,151,1,149,3,164,50,247,97,198,80,81,199,96,246,51,165,2,148,55,161,6,144,85,195,100,242,243,101,194,84,145,7,160,54,162,52,147,5,192,86,241,103,102,240,87,193,4,146,53,163,110,248,95,201,12,154,61,171,170,60,155,13,200,94,249,111,251,109,202,92,153,15,168,62,63,169,14,152,93,203,108,250,89,207,104,254,59,173,10,156,157,11,172,58,255,105,206,88,204,90,253,107,174,56,159,9,8,158,57,175,106,252,91,205,220,74,237,123,190,40,143,25,24,142,41,191,122,236,75,221,73,223,120,238,43,189,26,140,141,27,188,42,239,121,222,72,235,125,218,76,137,31,184,46,47,185,30,136,77,219,124,234,126,232,79,217,28,138,45,187,186,44,139,29,216,78,233,127,178,36,131,21,208,70,225,119,118,224,71,209,20,130,37,179,39,177,22,128,69,211,116,226,227,117,210,68,129,23,176,38,133,19,180,34,231,113,214,64,65,215,112,230,35,181,18,132,16,134,33,183,114,228,67,213,212,66,229,115,182,32,135,17,0,151,51,164,102,241,85,194,204,91,255,104,170,61,153,14,133,18,182,33,227,116,208,71,73,222,122,237,47,184,28,139,23,128,36,179,113,230,66,213,219,76,232,127,189,42,142,25,146,5,161,54,244,99,199,80,94,201,109,250,56,175,11,156,46,185,29,138,72,223,123,236,226,117,209,70,132,19,183,32,171,60,152,15,205,90,254,105,103,240,84,195,1,150,50,165,57,174,10,157,95,200,108,251,245,98,198,81,147,4,160,55,188,43,143,24,218,77,233,126,112,231,67,212,22,129,37,178,92,203,111,248,58,173,9,158,144,7,163,52,246,97,197,82,217,78,234,125,191,40,140,27,21,130,38,177,115,228,64,215,75,220,120,239,45,186,30,137,135,16,180,35,225,118,210,69,206,89,253,106,168,63,155,12,2,149,49,166,100,243,87,192,114,229,65,214,20,131,39,176,190,41,141,26,216,79,235,124,247,96,196,83,145,6,162,53,59,172,8,159,93,202,110,249,101,242,86,193,3,148,48,167,169,62,154,13,207,88,252,107,224,119,211,68,134,17,181,34,44,187,31,136,74,221,121,238,0,152,45,181,90,194,119,239,180,44,153,1,238,118,195,91,117,237,88,192,47,183,2,154,193,89,236,116,155,3,182,46,234,114,199,95,176,40,157,5,94,198,115,235,4,156,41,177,159,7,178,42,197,93,232,112,43,179,6,158,113,233,92,196,201,81,228,124,147,11,190,38,125,229,80,200,39,191,10,146,188,36,145,9,230,126,203,83,8,144,37,189,82,202,127,231,35,187,14,150,121,225,84,204,151,15,186,34,205,85,224,120,86,206,123,227,12,148,33,185,226,122,207,87,184,32,149,13,143,23,162,58,213,77,248,96,59,163,22,142,97,249,76,212,250,98,215,79,160,56,141,21,78,214,99,251,20,140,57,161,101,253,72,208,63,167,18,138,209,73,252,100,139,19,166,62,16,136,61,165,74,210,103,255,164,60,137,17,254,102,211,75,70,222,107,243,28,132,49,169,242,106,223,71,168,48,133,29,51,171,30,134,105,241,68,220,135,31,170,50,221,69,240,104,172,52,129,25,246,110,219,67,24,128,53,173,66,218,111,247,217,65,244,108,131,27,174,54,109,245,64,216,55,175,26,130,0,153,47,182,94,199,113,232,188,37,147,10,226,123,205,84,101,252,74,211,59,162,20,141,217,64,246,111,135,30,168,49,202,83,229,124,148,13,187,34,118,239,89,192,40,177,7,158,175,54,128,25,241,104,222,71,19,138,60,165,77,212,98,251,137,16,166,63,215,78,248,97,53,172,26,131,107,242,68,221,236,117,195,90,178,43,157,4,80,201,127,230,14,151,33,184,67,218,108,245,29,132,50,171,255,102,208,73,161,56,142,23,38,191,9,144,120,225,87,206,154,3,181,44,196,93,235,114,15,150,32,185,81,200,126,231,179,42,156,5,237,116,194,91,106,243,69,220,52,173,27,130,214,79,249,96,136,17,167,62,197,92,234,115,155,2,180,45,121,224,86,207,39,190,8,145,160,57,143,22,254,103,209,72,28,133,51,170,66,219,109,244,134,31,169,48,216,65,247,110,58,163,21,140,100,253,75,210,227,122,204,85,189,36,146,11,95,198,112,233,1,152,46,183,76,213,99,250,18,139,61,164,240,105,223,70,174,55,129,24,41,176,6,159,119,238,88,193,149,12,186,35,203,82,228,125,0,154,41,179,82,200,123,225,164,62,141,23,246,108,223,69,85,207,124,230,7,157,46,180,241,107,216,66,163,57,138,16,170,48,131,25,248,98,209,75,14,148,39,189,92,198,117,239,255,101,214,76,173,55,132,30,91,193,114,232,9,147,32,186,73,211,96,250,27,129,50,168,237,119,196,94,191,37,150,12,28,134,53,175,78,212,103,253,184,34,145,11,234,112,195,89,227,121,202,80,177,43,152,2,71,221,110,244,21,143,60,166,182,44,159,5,228,126,205,87,18,136,59,161,64,218,105,243,146,8,187,33,192,90,233,115,54,172,31,133,100,254,77,215,199,93,238,116,149,15,188,38,99,249,74,208,49,171,24,130,56,162,17,139,106,240,67,217,156,6,181,47,206,84,231,125,109,247,68,222,63,165,22,140,201,83,224,122,155,1,178,40,219,65,242,104,137,19,160,58,127,229,86,204,45,183,4,158,142,20,167,61,220,70,245,111,42,176,3,153,120,226,81,203,113,235,88,194,35,185,10,144,213,79,252,102,135,29,174,52,36,190,13,151,118,236,95,197,128,26,169,51,210,72,251,97,0,155,43,176,86,205,125,230,172,55,135,28,250,97,209,74,69,222,110,245,19,136,56,163,233,114,194,89,191,36,148,15,138,17,161,58,220,71,247,108,38,189,13,150,112,235,91,192,207,84,228,127,153,2,178,41,99,248,72,211,53,174,30,133,9,146,34,185,95,196,116,239,165,62,142,21,243,104,216,67,76,215,103,252,26,129,49,170,224,123,203,80,182,45,157,6,131,24,168,51,213,78,254,101,47,180,4,159,121,226,82,201,198,93,237,118,144,11,187,32,106,241,65,218,60,167,23,140,18,137,57,162,68,223,111,244,190,37,149,14,232,115,195,88,87,204,124,231,1,154,42,177,251,96,208,75,173,54,134,29,152,3,179,40,206,85,229,126,52,175,31,132,98,249,73,210,221,70,246,109,139,16,160,59,113,234,90,193,39,188,12,151,27,128,48,171,77,214,102,253,183,44,156,7,225,122,202,81,94,197,117,238,8,147,35,184,242,105,217,66,164,63,143,20,145,10,186,33,199,92,236,119,61,166,22,141,107,240,64,219,212,79,255,100,130,25,169,50,120,227,83,200,46,181,5,158,0,156,37,185,74,214,111,243,148,8,177,45,222,66,251,103,53,169,16,140,127,227,90,198,161,61,132,24,235,119,206,82,106,246,79,211,32,188,5,153,254,98,219,71,180,40,145,13,95,195,122,230,21,137,48,172,203,87,238,114,129,29,164,56,212,72,241,109,158,2,187,39,64,220,101,249,10,150,47,179,225,125,196,88,171,55,142,18,117,233,80,204,63,163,26,134,190,34,155,7,244,104,209,77,42,182,15,147,96,252,69,217,139,23,174,50,193,93,228,120,31,131,58,166,85,201,112,236,181,41,144,12,255,99,218,70,33,189,4,152,107,247,78,210,128,28,165,57,202,86,239,115,20,136,49,173,94,194,123,231,223,67,250,102,149,9,176,44,75,215,110,242,1,157,36,184,234,118,207,83,160,60,133,25,126,226,91,199,52,168,17,141,97,253,68,216,43,183,14,146,245,105,208,76,191,35,154,6,84,200,113,237,30,130,59,167,192,92,229,121,138,22,175,51,11,151,46,178,65,221,100,248,159,3,186,38,213,73,240,108,62,162,27,135,116,232,81,205,170,54,143,19,224,124,197,89,0,157,39,186,78,211,105,244,156,1,187,38,210,79,245,104,37,184,2,159,107,246,76,209,185,36,158,3,247,106,208,77,74,215,109,240,4,153,35,190,214,75,241,108,152,5,191,34,111,242,72,213,33,188,6,155,243,110,212,73,189,32,154,7,148,9,179,46,218,71,253,96,8,149,47,178,70,219,97,252,177,44,150,11,255,98,216,69,45,176,10,151,99,254,68,217,222,67,249,100,144,13,183,42,66,223,101,248,12,145,43,182,251,102,220,65,181,40,146,15,103,250,64,221,41,180,14,147,53,168,18,143,123,230,92,193,169,52,142,19,231,122,192,93,16,141,55,170,94,195,121,228,140,17,171,54,194,95,229,120,127,226,88,197,49,172,22,139,227,126,196,89,173,48,138,23,90,199,125,224,20,137,51,174,198,91,225,124,136,21,175,50,161,60,134,27,239,114,200,85,61,160,26,135,115,238,84,201,132,25,163,62,202,87,237,112,24,133,63,162,86,203,113,236,235,118,204,81,165,56,130,31,119,234,80,205,57,164,30,131,206,83,233,116,128,29,167,58,82,207,117,232,28,129,59,166,0,158,33,191,66,220,99,253,132,26,165,59,198,88,231,121,21,139,52,170,87,201,118,232,145,15,176,46,211,77,242,108,42,180,11,149,104,246,73,215,174,48,143,17,236,114,205,83,63,161,30,128,125,227,92,194,187,37,154,4,249,103,216,70,84,202,117,235,22,136,55,169,208,78,241,111,146,12,179,45,65,223,96,254,3,157,34,188,197,91,228,122,135,25,166,56,126,224,95,193,60,162,29,131,250,100,219,69,184,38,153,7,107,245,74,212,41,183,8,150,239,113,206,80,173,51,140,18,168,54,137,23,234,116,203,85,44,178,13,147,110,240,79,209,189,35,156,2,255,97,222,64,57,167,24,134,123,229,90,196,130,28,163,61,192,94,225,127,6,152,39,185,68,218,101,251,151,9,182,40,213,75,244,106,19,141,50,172,81,207,112,238,252,98,221,67,190,32,159,1,120,230,89,199,58,164,27,133,233,119,200,86,171,53,138,20,109,243,76,210,47,177,14,144,214,72,247,105,148,10,181,43,82,204,115,237,16,142,49,175,195,93,226,124,129,31,160,62,71,217,102,248,5,155,36,186,0,159,35,188,70,217,101,250,140,19,175,48,202,85,233,118,5,154,38,185,67,220,96,255,137,22,170,53,207,80,236,115,10,149,41,182,76,211,111,240,134,25,165,58,192,95,227,124,15,144,44,179,73,214,106,245,131,28,160,63,197,90,230,121,20,139,55,168,82,205,113,238,152,7,187,36,222,65,253,98,17,142,50,173,87,200,116,235,157,2,190,33,219,68,248,103,30,129,61,162,88,199,123,228,146,13,177,46,212,75,247,104,27,132,56,167,93,194,126,225,151,8,180,43,209,78,242,109,40,183,11,148,110,241,77,210,164,59,135,24,226,125,193,94,45,178,14,145,107,244,72,215,161,62,130,29,231,120,196,91,34,189,1,158,100,251,71,216,174,49,141,18,232,119,203,84,39,184,4,155,97,254,66,221,171,52,136,23,237,114,206,81,60,163,31,128,122,229,89,198,176,47,147,12,246,105,213,74,57,166,26,133,127,224,92,195,181,42,150,9,243,108,208,79,54,169,21,138,112,239,83,204,186,37,153,6,252,99,223,64,51,172,16,143,117,234,86,201,191,32,156,3,249,102,218,69,0,160,93,253,186,26,231,71,105,201,52,148,211,115,142,46,210,114,143,47,104,200,53,149,187,27,230,70,1,161,92,252,185,25,228,68,3,163,94,254,208,112,141,45,106,202,55,151,107,203,54,150,209,113,140,44,2,162,95,255,184,24,229,69,111,207,50,146,213,117,136,40,6,166,91,251,188,28,225,65,189,29,224,64,7,167,90,250,212,116,137,41,110,206,51,147,214,118,139,43,108,204,49,145,191,31,226,66,5,165,88,248,4,164,89,249,190,30,227,67,109,205,48,144,215,119,138,42,222,126,131,35,100,196,57,153,183,23,234,74,13,173,80,240,12,172,81,241,182,22,235,75,101,197,56,152,223,127,130,34,103,199,58,154,221,125,128,32,14,174,83,243,180,20,233,73,181,21,232,72,15,175,82,242,220,124,129,33,102,198,59,155,177,17,236,76,11,171,86,246,216,120,133,37,98,194,63,159,99,195,62,158,217,121,132,36,10,170,87,247,176,16,237,77,8,168,85,245,178,18,239,79,97,193,60,156,219,123,134,38,218,122,135,39,96,192,61,157,179,19,238,78,9,169,84,244,0,161,95,254,190,31,225,64,97,192,62,159,223,126,128,33,194,99,157,60,124,221,35,130,163,2,252,93,29,188,66,227,153,56,198,103,39,134,120,217,248,89,167,6,70,231,25,184,91,250,4,165,229,68,186,27,58,155,101,196,132,37,219,122,47,142,112,209,145,48,206,111,78,239,17,176,240,81,175,14,237,76,178,19,83,242,12,173,140,45,211,114,50,147,109,204,182,23,233,72,8,169,87,246,215,118,136,41,105,200,54,151,116,213,43,138,202,107,149,52,21,180,74,235,171,10,244,85,94,255,1,160,224,65,191,30,63,158,96,193,129,32,222,127,156,61,195,98,34,131,125,220,253,92,162,3,67,226,28,189,199,102,152,57,121,216,38,135,166,7,249,88,24,185,71,230,5,164,90,251,187,26,228,69,100,197,59,154,218,123,133,36,113,208,46,143,207,110,144,49,16,177,79,238,174,15,241,80,179,18,236,77,13,172,82,243,210,115,141,44,108,205,51,146,232,73,183,22,86,247,9,168,137,40,214,119,55,150,104,201,42,139,117,212,148,53,203,106,75,234,20,181,245,84,170,11,0,162,89,251,178,16,235,73,121,219,32,130,203,105,146,48,242,80,171,9,64,226,25,187,139,41,210,112,57,155,96,194,249,91,160,2,75,233,18,176,128,34,217,123,50,144,107,201,11,169,82,240,185,27,224,66,114,208,43,137,192,98,153,59,239,77,182,20,93,255,4,166,150,52,207,109,36,134,125,223,29,191,68,230,175,13,246,84,100,198,61,159,214,116,143,45,22,180,79,237,164,6,253,95,111,205,54,148,221,127,132,38,228,70,189,31,86,244,15,173,157,63,196,102,47,141,118,212,195,97,154,56,113,211,40,138,186,24,227,65,8,170,81,243,49,147,104,202,131,33,218,120,72,234,17,179,250,88,163,1,58,152,99,193,136,42,209,115,67,225,26,184,241,83,168,10,200,106,145,51,122,216,35,129,177,19,232,74,3,161,90,248,44,142,117,215,158,60,199,101,85,247,12,174,231,69,190,28,222,124,135,37,108,206,53,151,167,5,254,92,21,183,76,238,213,119,140,46,103,197,62,156,172,14,245,87,30,188,71,229,39,133,126,220,149,55,204,110,94,252,7,165,236,78,181,23,0,163,91,248,182,21,237,78,113,210,42,137,199,100,156,63,226,65,185,26,84,247,15,172,147,48,200,107,37,134,126,221,217,122,130,33,111,204,52,151,168,11,243,80,30,189,69,230,59,152,96,195,141,46,214,117,74,233,17,178,252,95,167,4,175,12,244,87,25,186,66,225,222,125,133,38,104,203,51,144,77,238,22,181,251,88,160,3,60,159,103,196,138,41,209,114,118,213,45,142,192,99,155,56,7,164,92,255,177,18,234,73,148,55,207,108,34,129,121,218,229,70,190,29,83,240,8,171,67,224,24,187,245,86,174,13,50,145,105,202,132,39,223,124,161,2,250,89,23,180,76,239,208,115,139,40,102,197,61,158,154,57,193,98,44,143,119,212,235,72,176,19,93,254,6,165,120,219,35,128,206,109,149,54,9,170,82,241,191,28,228,71,236,79,183,20,90,249,1,162,157,62,198,101,43,136,112,211,14,173,85,246,184,27,227,64,127,220,36,135,201,106,146,49,53,150,110,205,131,32,216,123,68,231,31,188,242,81,169,10,215,116,140,47,97,194,58,153,166,5,253,94,16,179,75,232,0,164,85,241,170,14,255,91,73,237,28,184,227,71,182,18,146,54,199,99,56,156,109,201,219,127,142,42,113,213,36,128,57,157,108,200,147,55,198,98,112,212,37,129,218,126,143,43,171,15,254,90,1,165,84,240,226,70,183,19,72,236,29,185,114,214,39,131,216,124,141,41,59,159,110,202,145,53,196,96,224,68,181,17,74,238,31,187,169,13,252,88,3,167,86,242,75,239,30,186,225,69,180,16,2,166,87,243,168,12,253,89,217,125,140,40,115,215,38,130,144,52,197,97,58,158,111,203,228,64,177,21,78,234,27,191,173,9,248,92,7,163,82,246,118,210,35,135,220,120,137,45,63,155,106,206,149,49,192,100,221,121,136,44,119,211,34,134,148,48,193,101,62,154,107,207,79,235,26,190,229,65,176,20,6,162,83,247,172,8,249,93,150,50,195,103,60,152,105,205,223,123,138,46,117,209,32,132,4,160,81,245,174,10,251,95,77,233,24,188,231,67,178,22,175,11,250,94,5,161,80,244,230,66,179,23,76,232,25,189,61,153,104,204,151,51,194,102,116,208,33,133,222,122,139,47,0,165,87,242,174,11,249,92,65,228,22,179,239,74,184,29,130,39,213,112,44,137,123,222,195,102,148,49,109,200,58,159,25,188,78,235,183,18,224,69,88,253,15,170,246,83,161,4,155,62,204,105,53,144,98,199,218,127,141,40,116,209,35,134,50,151,101,192,156,57,203,110,115,214,36,129,221,120,138,47,176,21,231,66,30,187,73,236,241,84,166,3,95,250,8,173,43,142,124,217,133,32,210,119,106,207,61,152,196,97,147,54,169,12,254,91,7,162,80,245,232,77,191,26,70,227,17,180,100,193,51,150,202,111,157,56,37,128,114,215,139,46,220,121,230,67,177,20,72,237,31,186,167,2,240,85,9,172,94,251,125,216,42,143,211,118,132,33,60,153,107,206,146,55,197,96,255,90,168,13,81,244,6,163,190,27,233,76,16,181,71,226,86,243,1,164,248,93,175,10,23,178,64,229,185,28,238,75,212,113,131,38,122,223,45,136,149,48,194,103,59,158,108,201,79,234,24,189,225,68,182,19,14,171,89,252,160,5,247,82,205,104,154,63,99,198,52,145,140,41,219,126,34,135,117,208,0,166,81,247,162,4,243,85,89,255,8,174,251,93,170,12,178,20,227,69,16,182,65,231,235,77,186,28,73,239,24,190,121,223,40,142,219,125,138,44,32,134,113,215,130,36,211,117,203,109,154,60,105,207,56,158,146,52,195,101,48,150,97,199,242,84,163,5,80,246,1,167,171,13,250,92,9,175,88,254,64,230,17,183,226,68,179,21,25,191,72,238,187,29,234,76,139,45,218,124,41,143,120,222,210,116,131,37,112,214,33,135,57,159,104,206,155,61,202,108,96,198,49,151,194,100,147,53,249,95,168,14,91,253,10,172,160,6,241,87,2,164,83,245,75,237,26,188,233,79,184,30,18,180,67,229,176,22,225,71,128,38,209,119,34,132,115,213,217,127,136,46,123,221,42,140,50,148,99,197,144,54,193,103,107,205,58,156,201,111,152,62,11,173,90,252,169,15,248,94,82,244,3,165,240,86,161,7,185,31,232,78,27,189,74,236,224,70,177,23,66,228,19,181,114,212,35,133,208,118,129,39,43,141,122,220,137,47,216,126,192,102,145,55,98,196,51,149,153,63,200,110,59,157,106,204,0,167,83,244,166,1,245,82,81,246,2,165,247,80,164,3,162,5,241,86,4,163,87,240,243,84,160,7,85,242,6,161,89,254,10,173,255,88,172,11,8,175,91,252,174,9,253,90,251,92,168,15,93,250,14,169,170,13,249,94,12,171,95,248,178,21,225,70,20,179,71,224,227,68,176,23,69,226,22,177,16,183,67,228,182,17,229,66,65,230,18,181,231,64,180,19,235,76,184,31,77,234,30,185,186,29,233,78,28,187,79,232,73,238,26,189,239,72,188,27,24,191,75,236,190,25,237,74,121,222,42,141,223,120,140,43,40,143,123,220,142,41,221,122,219,124,136,47,125,218,46,137,138,45,217,126,44,139,127,216,32,135,115,212,134,33,213,114,113,214,34,133,215,112,132,35,130,37,209,118,36,131,119,208,211,116,128,39,117,210,38,129,203,108,152,63,109,202,62,153,154,61,201,110,60,155,111,200,105,206,58,157,207,104,156,59,56,159,107,204,158,57,205,106,146,53,193,102,52,147,103,192,195,100,144,55,101,194,54,145,48,151,99,196,150,49,197,98,97,198,50,149,199,96,148,51,0,168,77,229,154,50,215,127,41,129,100,204,179,27,254,86,82,250,31,183,200,96,133,45,123,211,54,158,225,73,172,4,164,12,233,65,62,150,115,219,141,37,192,104,23,191,90,242,246,94,187,19,108,196,33,137,223,119,146,58,69,237,8,160,85,253,24,176,207,103,130,42,124,212,49,153,230,78,171,3,7,175,74,226,157,53,208,120,46,134,99,203,180,28,249,81,241,89,188,20,107,195,38,142,216,112,149,61,66,234,15,167,163,11,238,70,57,145,116,220,138,34,199,111,16,184,93,245,170,2,231,79,48,152,125,213,131,43,206,102,25,177,84,252,248,80,181,29,98,202,47,135,209,121,156,52,75,227,6,174,14,166,67,235,148,60,217,113,39,143,106,194,189,21,240,88,92,244,17,185,198,110,139,35,117,221,56,144,239,71,162,10,255,87,178,26,101,205,40,128,214,126,155,51,76,228,1,169,173,5,224,72,55,159,122,210,132,44,201,97,30,182,83,251,91,243,22,190,193,105,140,36,114,218,63,151,232,64,165,13,9,161,68,236,147,59,222,118,32,136,109,197,186,18,247,95,0,169,79,230,158,55,209,120,33,136,110,199,191,22,240,89,66,235,13,164,220,117,147,58,99,202,44,133,253,84,178,27,132,45,203,98,26,179,85,252,165,12,234,67,59,146,116,221,198,111,137,32,88,241,23,190,231,78,168,1,121,208,54,159,21,188,90,243,139,34,196,109,52,157,123,210,170,3,229,76,87,254,24,177,201,96,134,47,118,223,57,144,232,65,167,14,145,56,222,119,15,166,64,233,176,25,255,86,46,135,97,200,211,122,156,53,77,228,2,171,242,91,189,20,108,197,35,138,42,131,101,204,180,29,251,82,11,162,68,237,149,60,218,115,104,193,39,142,246,95,185,16,73,224,6,175,215,126,152,49,174,7,225,72,48,153,127,214,143,38,192,105,17,184,94,247,236,69,163,10,114,219,61,148,205,100,130,43,83,250,28,181,63,150,112,217,161,8,238,71,30,183,81,248,128,41,207,102,125,212,50,155,227,74,172,5,92,245,19,186,194,107,141,36,187,18,244,93,37,140,106,195,154,51,213,124,4,173,75,226,249,80,182,31,103,206,40,129,216,113,151,62,70,239,9,160,0,170,73,227,146,56,219,113,57,147,112,218,171,1,226,72,114,216,59,145,224,74,169,3,75,225,2,168,217,115,144,58,228,78,173,7,118,220,63,149,221,119,148,62,79,229,6,172,150,60,223,117,4,174,77,231,175,5,230,76,61,151,116,222,213,127,156,54,71,237,14,164,236,70,165,15,126,212,55,157,167,13,238,68,53,159,124,214,158,52,215,125,12,166,69,239,49,155,120,210,163,9,234,64,8,162,65,235,154,48,211,121,67,233,10,160,209,123,152,50,122,208,51,153,232,66,161,11,183,29,254,84,37,143,108,198,142,36,199,109,28,182,85,255,197,111,140,38,87,253,30,180,252,86,181,31,110,196,39,141,83,249,26,176,193,107,136,34,106,192,35,137,248,82,177,27,33,139,104,194,179,25,250,80,24,178,81,251,138,32,195,105,98,200,43,129,240,90,185,19,91,241,18,184,201,99,128,42,16,186,89,243,130,40,203,97,41,131,96,202,187,17,242,88,134,44,207,101,20,190,93,247,191,21,246,92,45,135,100,206,244,94,189,23,102,204,47,133,205,103,132,46,95,245,22,188,0,171,75,224,150,61,221,118,49,154,122,209,167,12,236,71,98,201,41,130,244,95,191,20,83,248,24,179,197,110,142,37,196,111,143,36,82,249,25,178,245,94,190,21,99,200,40,131,166,13,237,70,48,155,123,208,151,60,220,119,1,170,74,225,149,62,222,117,3,168,72,227,164,15,239,68,50,153,121,210,247,92,188,23,97,202,42,129,198,109,141,38,80,251,27,176,81,250,26,177,199,108,140,39,96,203,43,128,246,93,189,22,51,152,120,211,165,14,238,69,2,169,73,226,148,63,223,116,55,156,124,215,161,10,234,65,6,173,77,230,144,59,219,112,85,254,30,181,195,104,136,35,100,207,47,132,242,89,185,18,243,88,184,19,101,206,46,133,194,105,137,34,84,255,31,180,145,58,218,113,7,172,76,231,160,11,235,64,54,157,125,214,162,9,233,66,52,159,127,212,147,56,216,115,5,174,78,229,192,107,139,32,86,253,29,182,241,90,186,17,103,204,44,135,102,205,45,134,240,91,187,16,87,252,28,183,193,106,138,33,4,175,79,228,146,57,217,114,53,158,126,213,163,8,232,67,0,172,69,233,138,38,207,99,9,165,76,224,131,47,198,106,18,190,87,251,152,52,221,113,27,183,94,242,145,61,212,120,36,136,97,205,174,2,235,71,45,129,104,196,167,11,226,78,54,154,115,223,188,16,249,85,63,147,122,214,181,25,240,92,72,228,13,161,194,110,135,43,65,237,4,168,203,103,142,34,90,246,31,179,208,124,149,57,83,255,22,186,217,117,156,48,108,192,41,133,230,74,163,15,101,201,32,140,239,67,170,6,126,210,59,151,244,88,177,29,119,219,50,158,253,81,184,20,144,60,213,121,26,182,95,243,153,53,220,112,19,191,86,250,130,46,199,107,8,164,77,225,139,39,206,98,1,173,68,232,180,24,241,93,62,146,123,215,189,17,248,84,55,155,114,222,166,10,227,79,44,128,105,197,175,3,234,70,37,137,96,204,216,116,157,49,82,254,23,187,209,125,148,56,91,247,30,178,202,102,143,35,64,236,5,169,195,111,134,42,73,229,12,160,252,80,185,21,118,218,51,159,245,89,176,28,127,211,58,150,238,66,171,7,100,200,33,141,231,75,162,14,109,193,40,132,0,173,71,234,142,35,201,100,1,172,70,235,143,34,200,101,2,175,69,232,140,33,203,102,3,174,68,233,141,32,202,103,4,169,67,238,138,39,205,96,5,168,66,239,139,38,204,97,6,171,65,236,136,37,207,98,7,170,64,237,137,36,206,99,8,165,79,226,134,43,193,108,9,164,78,227,135,42,192,109,10,167,77,224,132,41,195,110,11,166,76,225,133,40,194,111,12,161,75,230,130,47,197,104,13,160,74,231,131,46,196,105,14,163,73,228,128,45,199,106,15,162,72,229,129,44,198,107,16,189,87,250,158,51,217,116,17,188,86,251,159,50,216,117,18,191,85,248,156,49,219,118,19,190,84,249,157,48,218,119,20,185,83,254,154,55,221,112,21,184,82,255,155,54,220,113,22,187,81,252,152,53,223,114,23,186,80,253,153,52,222,115,24,181,95,242,150,59,209,124,25,180,94,243,151,58,208,125,26,183,93,240,148,57,211,126,27,182,92,241,149,56,210,127,28,177,91,246,146,63,213,120,29,176,90,247,147,62,212,121,30,179,89,244,144,61,215,122,31,178,88,245,145,60,214,123,0,174,65,239,130,44,195,109,25,183,88,246,155,53,218,116,50,156,115,221,176,30,241,95,43,133,106,196,169,7,232,70,100,202,37,139,230,72,167,9,125,211,60,146,255,81,190,16,86,248,23,185,212,122,149,59,79,225,14,160,205,99,140,34,200,102,137,39,74,228,11,165,209,127,144,62,83,253,18,188,250,84,187,21,120,214,57,151,227,77,162,12,97,207,32,142,172,2,237,67,46,128,111,193,181,27,244,90,55,153,118,216,158,48,223,113,28,178,93,243,135,41,198,104,5,171,68,234,141,35,204,98,15,161,78,224,148,58,213,123,22,184,87,249,191,17,254,80,61,147,124,210,166,8,231,73,36,138,101,203,233,71,168,6,107,197,42,132,240,94,177,31,114,220,51,157,219,117,154,52,89,247,24,182,194,108,131,45,64,238,1,175,69,235,4,170,199,105,134,40,92,242,29,179,222,112,159,49,119,217,54,152,245,91,180,26,110,192,47,129,236,66,173,3,33,143,96,206,163,13,226,76,56,150,121,215,186,20,251,85,19,189,82,252,145,63,208,126,10,164,75,229,136,38,201,103,0,175,67,236,134,41,197,106,17,190,82,253,151,56,212,123,34,141,97,206,164,11,231,72,51,156,112,223,181,26,246,89,68,235,7,168,194,109,129,46,85,250,22,185,211,124,144,63,102,201,37,138,224,79,163,12,119,216,52,155,241,94,178,29,136,39,203,100,14,161,77,226,153,54,218,117,31,176,92,243,170,5,233,70,44,131,111,192,187,20,248,87,61,146,126,209,204,99,143,32,74,229,9,166,221,114,158,49,91,244,24,183,238,65,173,2,104,199,43,132,255,80,188,19,121,214,58,149,13,162,78,225,139,36,200,103,28,179,95,240,154,53,217,118,47,128,108,195,169,6,234,69,62,145,125,210,184,23,251,84,73,230,10,165,207,96,140,35,88,247,27,180,222,113,157,50,107,196,40,135,237,66,174,1,122,213,57,150,252,83,191,16,133,42,198,105,3,172,64,239,148,59,215,120,18,189,81,254,167,8,228,75,33,142,98,205,182,25,245,90,48,159,115,220,193,110,130,45,71,232,4,171,208,127,147,60,86,249,21,186,227,76,160,15,101,202,38,137,242,93,177,30,116,219,55,152,0,176,125,205,250,74,135,55,233,89,148,36,19,163,110,222,207,127,178,2,53,133,72,248,38,150,91,235,220,108,161,17,131,51,254,78,121,201,4,180,106,218,23,167,144,32,237,93,76,252,49,129,182,6,203,123,165,21,216,104,95,239,34,146,27,171,102,214,225,81,156,44,242,66,143,63,8,184,117,197,212,100,169,25,46,158,83,227,61,141,64,240,199,119,186,10,152,40,229,85,98,210,31,175,113,193,12,188,139,59,246,70,87,231,42,154,173,29,208,96,190,14,195,115,68,244,57,137,54,134,75,251,204,124,177,1,223,111,162,18,37,149,88,232,249,73,132,52,3,179,126,206,16,160,109,221,234,90,151,39,181,5,200,120,79,255,50,130,92,236,33,145,166,22,219,107,122,202,7,183,128,48,253,77,147,35,238,94,105,217,20,164,45,157,80,224,215,103,170,26,196,116,185,9,62,142,67,243,226,82,159,47,24,168,101,213,11,187,118,198,241,65,140,60,174,30,211,99,84,228,41,153,71,247,58,138,189,13,192,112,97,209,28,172,155,43,230,86,136,56,245,69,114,194,15,191,0,177,127,206,254,79,129,48,225,80,158,47,31,174,96,209,223,110,160,17,33,144,94,239,62,143,65,240,192,113,191,14,163,18,220,109,93,236,34,147,66,243,61,140,188,13,195,114,124,205,3,178,130,51,253,76,157,44,226,83,99,210,28,173,91,234,36,149,165,20,218,107,186,11,197,116,68,245,59,138,132,53,251,74,122,203,5,180,101,212,26,171,155,42,228,85,248,73,135,54,6,183,121,200,25,168,102,215,231,86,152,41,39,150,88,233,217,104,166,23,198,119,185,8,56,137,71,246,182,7,201,120,72,249,55,134,87,230,40,153,169,24,214,103,105,216,22,167,151,38,232,89,136,57,247,70,118,199,9,184,21,164,106,219,235,90,148,37,244,69,139,58,10,187,117,196,202,123,181,4,52,133,75,250,43,154,84,229,213,100,170,27,237,92,146,35,19,162,108,221,12,189,115,194,242,67,141,60,50,131,77,252,204,125,179,2,211,98,172,29,45,156,82,227,78,255,49,128,176,1,207,126,175,30,208,97,81,224,46,159,145,32,238,95,111,222,16,161,112,193,15,190,142,63,241,64,0,178,121,203,242,64,139,57,249,75,128,50,11,185,114,192,239,93,150,36,29,175,100,214,22,164,111,221,228,86,157,47,195,113,186,8,49,131,72,250,58,136,67,241,200,122,177,3,44,158,85,231,222,108,167,21,213,103,172,30,39,149,94,236,155,41,226,80,105,219,16,162,98,208,27,169,144,34,233,91,116,198,13,191,134,52,255,77,141,63,244,70,127,205,6,180,88,234,33,147,170,24,211,97,161,19,216,106,83,225,42,152,183,5,206,124,69,247,60,142,78,252,55,133,188,14,197,119,43,153,82,224,217,107,160,18,210,96,171,25,32,146,89,235,196,118,189,15,54,132,79,253,61,143,68,246,207,125,182,4,232,90,145,35,26,168,99,209,17,163,104,218,227,81,154,40,7,181,126,204,245,71,140,62,254,76,135,53,12,190,117,199,176,2,201,123,66,240,59,137,73,251,48,130,187,9,194,112,95,237,38,148,173,31,212,102,166,20,223,109,84,230,45,159,115,193,10,184,129,51,248,74,138,56,243,65,120,202,1,179,156,46,229,87,110,220,23,165,101,215,28,174,151,37,238,92,0,179,123,200,246,69,141,62,241,66,138,57,7,180,124,207,255,76,132,55,9,186,114,193,14,189,117,198,248,75,131,48,227,80,152,43,21,166,110,221,18,161,105,218,228,87,159,44,28,175,103,212,234,89,145,34,237,94,150,37,27,168,96,211,219,104,160,19,45,158,86,229,42,153,81,226,220,111,167,20,36,151,95,236,210,97,169,26,213,102,174,29,35,144,88,235,56,139,67,240,206,125,181,6,201,122,178,1,63,140,68,247,199,116,188,15,49,130,74,249,54,133,77,254,192,115,187,8,171,24,208,99,93,238,38,149,90,233,33,146,172,31,215,100,84,231,47,156,162,17,217,106,165,22,222,109,83,224,40,155,72,251,51,128,190,13,197,118,185,10,194,113,79,252,52,135,183,4,204,127,65,242,58,137,70,245,61,142,176,3,203,120,112,195,11,184,134,53,253,78,129,50,250,73,119,196,12,191,143,60,244,71,121,202,2,177,126,205,5,182,136,59,243,64,147,32,232,91,101,214,30,173,98,209,25,170,148,39,239,92,108,223,23,164,154,41,225,82,157,46,230,85,107,216,16,163,0,180,117,193,234,94,159,43,201,125,188,8,35,151,86,226,143,59,250,78,101,209,16,164,70,242,51,135,172,24,217,109,3,183,118,194,233,93,156,40,202,126,191,11,32,148,85,225,140,56,249,77,102,210,19,167,69,241,48,132,175,27,218,110,6,178,115,199,236,88,153,45,207,123,186,14,37,145,80,228,137,61,252,72,99,215,22,162,64,244,53,129,170,30,223,107,5,177,112,196,239,91,154,46,204,120,185,13,38,146,83,231,138,62,255,75,96,212,21,161,67,247,54,130,169,29,220,104,12,184,121,205,230,82,147,39,197,113,176,4,47,155,90,238,131,55,246,66,105,221,28,168,74,254,63,139,160,20,213,97,15,187,122,206,229,81,144,36,198,114,179,7,44,152,89,237,128,52,245,65,106,222,31,171,73,253,60,136,163,23,214,98,10,190,127,203,224,84,149,33,195,119,182,2,41,157,92,232,133,49,240,68,111,219,26,174,76,248,57,141,166,18,211,103,9,189,124,200,227,87,150,34,192,116,181,1,42,158,95,235,134,50,243,71,108,216,25,173,79,251,58,142,165,17,208,100,0,181,119,194,238,91,153,44,193,116,182,3,47,154,88,237,159,42,232,93,113,196,6,179,94,235,41,156,176,5,199,114,35,150,84,225,205,120,186,15,226,87,149,32,12,185,123,206,188,9,203,126,82,231,37,144,125,200,10,191,147,38,228,81,70,243,49,132,168,29,223,106,135,50,240,69,105,220,30,171,217,108,174,27,55,130,64,245,24,173,111,218,246,67,129,52,101,208,18,167,139,62,252,73,164,17,211,102,74,255,61,136,250,79,141,56,20,161,99,214,59,142,76,249,213,96,162,23,140,57,251,78,98,215,21,160,77,248,58,143,163,22,212,97,19,166,100,209,253,72,138,63,210,103,165,16,60,137,75,254,175,26,216,109,65,244,54,131,110,219,25,172,128,53,247,66,48,133,71,242,222,107,169,28,241,68,134,51,31,170,104,221,202,127,189,8,36,145,83,230,11,190,124,201,229,80,146,39,85,224,34,151,187,14,204,121,148,33,227,86,122,207,13,184,233,92,158,43,7,178,112,197,40,157,95,234,198,115,177,4,118,195,1,180,152,45,239,90,183,2,192,117,89,236,46,155,0,182,113,199,226,84,147,37,217,111,168,30,59,141,74,252,175,25,222,104,77,251,60,138,118,192,7,177,148,34,229,83,67,245,50,132,161,23,208,102,154,44,235,93,120,206,9,191,236,90,157,43,14,184,127,201,53,131,68,242,215,97,166,16,134,48,247,65,100,210,21,163,95,233,46,152,189,11,204,122,41,159,88,238,203,125,186,12,240,70,129,55,18,164,99,213,197,115,180,2,39,145,86,224,28,170,109,219,254,72,143,57,106,220,27,173,136,62,249,79,179,5,194,116,81,231,32,150,17,167,96,214,243,69,130,52,200,126,185,15,42,156,91,237,190,8,207,121,92,234,45,155,103,209,22,160,133,51,244,66,82,228,35,149,176,6,193,119,139,61,250,76,105,223,24,174,253,75,140,58,31,169,110,216,36,146,85,227,198,112,183,1,151,33,230,80,117,195,4,178,78,248,63,137,172,26,221,107,56,142,73,255,218,108,171,29,225,87,144,38,3,181,114,196,212,98,165,19,54,128,71,241,13,187,124,202,239,89,158,40,123,205,10,188,153,47,232,94,162,20,211,101,64,246,49,135,0,183,115,196,230,81,149,34,209,102,162,21,55,128,68,243,191,8,204,123,89,238,42,157,110,217,29,170,136,63,251,76,99,212,16,167,133,50,246,65,178,5,193,118,84,227,39,144,220,107,175,24,58,141,73,254,13,186,126,201,235,92,152,47,198,113,181,2,32,151,83,228,23,160,100,211,241,70,130,53,121,206,10,189,159,40,236,91,168,31,219,108,78,249,61,138,165,18,214,97,67,244,48,135,116,195,7,176,146,37,225,86,26,173,105,222,252,75,143,56,203,124,184,15,45,154,94,233,145,38,226,85,119,192,4,179,64,247,51,132,166,17,213,98,46,153,93,234,200,127,187,12,255,72,140,59,25,174,106,221,242,69,129,54,20,163,103,208,35,148,80,231,197,114,182,1,77,250,62,137,171,28,216,111,156,43,239,88,122,205,9,190,87,224,36,147,177,6,194,117,134,49,245,66,96,215,19,164,232,95,155,44,14,185,125,202,57,142,74,253,223,104,172,27,52,131,71,240,210,101,161,22,229,82,150,33,3,180,112,199,139,60,248,79,109,218,30,169,90,237,41,158,188,11,207,120,0,184,109,213,218,98,183,15,169,17,196,124,115,203,30,166,79,247,34,154,149,45,248,64,230,94,139,51,60,132,81,233,158,38,243,75,68,252,41,145,55,143,90,226,237,85,128,56,209,105,188,4,11,179,102,222,120,192,21,173,162,26,207,119,33,153,76,244,251,67,150,46,136,48,229,93,82,234,63,135,110,214,3,187,180,12,217,97,199,127,170,18,29,165,112,200,191,7,210,106,101,221,8,176,22,174,123,195,204,116,161,25,240,72,157,37,42,146,71,255,89,225,52,140,131,59,238,86,66,250,47,151,152,32,245,77,235,83,134,62,49,137,92,228,13,181,96,216,215,111,186,2,164,28,201,113,126,198,19,171,220,100,177,9,6,190,107,211,117,205,24,160,175,23,194,122,147,43,254,70,73,241,36,156,58,130,87,239,224,88,141,53,99,219,14,182,185,1,212,108,202,114,167,31,16,168,125,197,44,148,65,249,246,78,155,35,133,61,232,80,95,231,50,138,253,69,144,40,39,159,74,242,84,236,57,129,142,54,227,91,178,10,223,103,104,208,5,189,27,163,118,206,193,121,172,20,0,185,111,214,222,103,177,8,161,24,206,119,127,198,16,169,95,230,48,137,129,56,238,87,254,71,145,40,32,153,79,246,190,7,209,104,96,217,15,182,31,166,112,201,193,120,174,23,225,88,142,55,63,134,80,233,64,249,47,150,158,39,241,72,97,216,14,183,191,6,208,105,192,121,175,22,30,167,113,200,62,135,81,232,224,89,143,54,159,38,240,73,65,248,46,151,223,102,176,9,1,184,110,215,126,199,17,168,160,25,207,118,128,57,239,86,94,231,49,136,33,152,78,247,255,70,144,41,194,123,173,20,28,165,115,202,99,218,12,181,189,4,210,107,157,36,242,75,67,250,44,149,60,133,83,234,226,91,141,52,124,197,19,170,162,27,205,116,221,100,178,11,3,186,108,213,35,154,76,245,253,68,146,43,130,59,237,84,92,229,51,138,163,26,204,117,125,196,18,171,2,187,109,212,220,101,179,10,252,69,147,42,34,155,77,244,93,228,50,139,131,58,236,85,29,164,114,203,195,122,172,21,188,5,211,106,98,219,13,180,66,251,45,148,156,37,243,74,227,90,140,53,61,132,82,235,0,186,105,211,210,104,187,1,185,3,208,106,107,209,2,184,111,213,6,188,189,7,212,110,214,108,191,5,4,190,109,215,222,100,183,13,12,182,101,223,103,221,14,180,181,15,220,102,177,11,216,98,99,217,10,176,8,178,97,219,218,96,179,9,161,27,200,114,115,201,26,160,24,162,113,203,202,112,163,25,206,116,167,29,28,166,117,207,119,205,30,164,165,31,204,118,127,197,22,172,173,23,196,126,198,124,175,21,20,174,125,199,16,170,121,195,194,120,171,17,169,19,192,122,123,193,18,168,95,229,54,140,141,55,228,94,230,92,143,53,52,142,93,231,48,138,89,227,226,88,139,49,137,51,224,90,91,225,50,136,129,59,232,82,83,233,58,128,56,130,81,235,234,80,131,57,238,84,135,61,60,134,85,239,87,237,62,132,133,63,236,86,254,68,151,45,44,150,69,255,71,253,46,148,149,47,252,70,145,43,248,66,67,249,42,144,40,146,65,251,250,64,147,41,32,154,73,243,242,72,155,33,153,35,240,74,75,241,34,152,79,245,38,156,157,39,244,78,246,76,159,37,36,158,77,247,0,187,107,208,214,109,189,6,177,10,218,97,103,220,12,183,127,196,20,175,169,18,194,121,206,117,165,30,24,163,115,200,254,69,149,46,40,147,67,248,79,244,36,159,153,34,242,73,129,58,234,81,87,236,60,135,48,139,91,224,230,93,141,54,225,90,138,49,55,140,92,231,80,235,59,128,134,61,237,86,158,37,245,78,72,243,35,152,47,148,68,255,249,66,146,41,31,164,116,207,201,114,162,25,174,21,197,126,120,195,19,168,96,219,11,176,182,13,221,102,209,106,186,1,7,188,108,215,223,100,180,15,9,178,98,217,110,213,5,190,184,3,211,104,160,27,203,112,118,205,29,166,17,170,122,193,199,124,172,23,33,154,74,241,247,76,156,39,144,43,251,64,70,253,45,150,94,229,53,142,136,51,227,88,239,84,132,63,57,130,82,233,62,133,85,238,232,83,131,56,143,52,228,95,89,226,50,137,65,250,42,145,151,44,252,71,240,75,155,32,38,157,77,246,192,123,171,16,22,173,125,198,113,202,26,161,167,28,204,119,191,4,212,111,105,210,2,185,14,181,101,222,216,99,179,8,0,188,101,217,202,118,175,19,137,53,236,80,67,255,38,154,15,179,106,214,197,121,160,28,134,58,227,95,76,240,41,149,30,162,123,199,212,104,177,13,151,43,242,78,93,225,56,132,17,173,116,200,219,103,190,2,152,36,253,65,82,238,55,139,60,128,89,229,246,74,147,47,181,9,208,108,127,195,26,166,51,143,86,234,249,69,156,32,186,6,223,99,112,204,21,169,34,158,71,251,232,84,141,49,171,23,206,114,97,221,4,184,45,145,72,244,231,91,130,62,164,24,193,125,110,210,11,183,120,196,29,161,178,14,215,107,241,77,148,40,59,135,94,226,119,203,18,174,189,1,216,100,254,66,155,39,52,136,81,237,102,218,3,191,172,16,201,117,239,83,138,54,37,153,64,252,105,213,12,176,163,31,198,122,224,92,133,57,42,150,79,243,68,248,33,157,142,50,235,87,205,113,168,20,7,187,98,222,75,247,46,146,129,61,228,88,194,126,167,27,8,180,109,209,90,230,63,131,144,44,245,73,211,111,182,10,25,165,124,192,85,233,48,140,159,35,250,70,220,96,185,5,22,170,115,207,0,189,103,218,206,115,169,20,129,60,230,91,79,242,40,149,31,162,120,197,209,108,182,11,158,35,249,68,80,237,55,138,62,131,89,228,240,77,151,42,191,2,216,101,113,204,22,171,33,156,70,251,239,82,136,53,160,29,199,122,110,211,9,180,124,193,27,166,178,15,213,104,253,64,154,39,51,142,84,233,99,222,4,185,173,16,202,119,226,95,133,56,44,145,75,246,66,255,37,152,140,49,235,86,195,126,164,25,13,176,106,215,93,224,58,135,147,46,244,73,220,97,187,6,18,175,117,200,248,69,159,34,54,139,81,236,121,196,30,163,183,10,208,109,231,90,128,61,41,148,78,243,102,219,1,188,168,21,207,114,198,123,161,28,8,181,111,210,71,250,32,157,137,52,238,83,217,100,190,3,23,170,112,205,88,229,63,130,150,43,241,76,132,57,227,94,74,247,45,144,5,184,98,223,203,118,172,17,155,38,252,65,85,232,50,143,26,167,125,192,212,105,179,14,186,7,221,96,116,201,19,174,59,134,92,225,245,72,146,47,165,24,194,127,107,214,12,177,36,153,67,254,234,87,141,48,0,190,97,223,194,124,163,29,153,39,248,70,91,229,58,132,47,145,78,240,237,83,140,50,182,8,215,105,116,202,21,171,94,224,63,129,156,34,253,67,199,121,166,24,5,187,100,218,113,207,16,174,179,13,210,108,232,86,137,55,42,148,75,245,188,2,221,99,126,192,31,161,37,155,68,250,231,89,134,56,147,45,242,76,81,239,48,142,10,180,107,213,200,118,169,23,226,92,131,61,32,158,65,255,123,197,26,164,185,7,216,102,205,115,172,18,15,177,110,208,84,234,53,139,150,40,247,73,101,219,4,186,167,25,198,120,252,66,157,35,62,128,95,225,74,244,43,149,136,54,233,87,211,109,178,12,17,175,112,206,59,133,90,228,249,71,152,38,162,28,195,125,96,222,1,191,20,170,117,203,214,104,183,9,141,51,236,82,79,241,46,144,217,103,184,6,27,165,122,196,64,254,33,159,130,60,227,93,246,72,151,41,52,138,85,235,111,209,14,176,173,19,204,114,135,57,230,88,69,251,36,154,30,160,127,193,220,98,189,3,168,22,201,119,106,212,11,181,49,143,80,238,243,77,146,44,0,191,99,220,198,121,165,26,145,46,242,77,87,232,52,139,63,128,92,227,249,70,154,37,174,17,205,114,104,215,11,180,126,193,29,162,184,7,219,100,239,80,140,51,41,150,74,245,65,254,34,157,135,56,228,91,208,111,179,12,22,169,117,202,252,67,159,32,58,133,89,230,109,210,14,177,171,20,200,119,195,124,160,31,5,186,102,217,82,237,49,142,148,43,247,72,130,61,225,94,68,251,39,152,19,172,112,207,213,106,182,9,189,2,222,97,123,196,24,167,44,147,79,240,234,85,137,54,229,90,134,57,35,156,64,255,116,203,23,168,178,13,209,110,218,101,185,6,28,163,127,192,75,244,40,151,141,50,238,81,155,36,248,71,93,226,62,129,10,181,105,214,204,115,175,16,164,27,199,120,98,221,1,190,53,138,86,233,243,76,144,47,25,166,122,197,223,96,188,3,136,55,235,84,78,241,45,146,38,153,69,250,224,95,131,60,183,8,212,107,113,206,18,173,103,216,4,187,161,30,194,125,246,73,149,42,48,143,83,236,88,231,59,132,158,33,253,66,201,118,170,21,15,176,108,211,0,192,157,93,39,231,186,122,78,142,211,19,105,169,244,52,156,92,1,193,187,123,38,230,210,18,79,143,245,53,104,168,37,229,184,120,2,194,159,95,107,171,246,54,76,140,209,17,185,121,36,228,158,94,3,195,247,55,106,170,208,16,77,141,74,138,215,23,109,173,240,48,4,196,153,89,35,227,190,126,214,22,75,139,241,49,108,172,152,88,5,197,191,127,34,226,111,175,242,50,72,136,213,21,33,225,188,124,6,198,155,91,243,51,110,174,212,20,73,137,189,125,32,224,154,90,7,199,148,84,9,201,179,115,46,238,218,26,71,135,253,61,96,160,8,200,149,85,47,239,178,114,70,134,219,27,97,161,252,60,177,113,44,236,150,86,11,203,255,63,98,162,216,24,69,133,45,237,176,112,10,202,151,87,99,163,254,62,68,132,217,25,222,30,67,131,249,57,100,164,144,80,13,205,183,119,42,234,66,130,223,31,101,165,248,56,12,204,145,81,43,235,182,118,251,59,102,166,220,28,65,129,181,117,40,232,146,82,15,207,103,167,250,58,64,128,221,29,41,233,180,116,14,206,147,83,0,193,159,94,35,226,188,125,70,135,217,24,101,164,250,59,140,77,19,210,175,110,48,241,202,11,85,148,233,40,118,183,5,196,154,91,38,231,185,120,67,130,220,29,96,161,255,62,137,72,22,215,170,107,53,244,207,14,80,145,236,45,115,178,10,203,149,84,41,232,182,119,76,141,211,18,111,174,240,49,134,71,25,216,165,100,58,251,192,1,95,158,227,34,124,189,15,206,144,81,44,237,179,114,73,136,214,23,106,171,245,52,131,66,28,221,160,97,63,254,197,4,90,155,230,39,121,184,20,213,139,74,55,246,168,105,82,147,205,12,113,176,238,47,152,89,7,198,187,122,36,229,222,31,65,128,253,60,98,163,17,208,142,79,50,243,173,108,87,150,200,9,116,181,235,42,157,92,2,195,190,127,33,224,219,26,68,133,248,57,103,166,30,223,129,64,61,252,162,99,88,153,199,6,123,186,228,37,146,83,13,204,177,112,46,239,212,21,75,138,247,54,104,169,27,218,132,69,56,249,167,102,93,156,194,3,126,191,225,32,151,86,8,201,180,117,43,234,209,16,78,143,242,51,109,172,0,194,153,91,47,237,182,116,94,156,199,5,113,179,232,42,188,126,37,231,147,81,10,200,226,32,123,185,205,15,84,150,101,167,252,62,74,136,211,17,59,249,162,96,20,214,141,79,217,27,64,130,246,52,111,173,135,69,30,220,168,106,49,243,202,8,83,145,229,39,124,190,148,86,13,207,187,121,34,224,118,180,239,45,89,155,192,2,40,234,177,115,7,197,158,92,175,109,54,244,128,66,25,219,241,51,104,170,222,28,71,133,19,209,138,72,60,254,165,103,77,143,212,22,98,160,251,57,137,75,16,210,166,100,63,253,215,21,78,140,248,58,97,163,53,247,172,110,26,216,131,65,107,169,242,48,68,134,221,31,236,46,117,183,195,1,90,152,178,112,43,233,157,95,4,198,80,146,201,11,127,189,230,36,14,204,151,85,33,227,184,122,67,129,218,24,108,174,245,55,29,223,132,70,50,240,171,105,255,61,102,164,208,18,73,139,161,99,56,250,142,76,23,213,38,228,191,125,9,203,144,82,120,186,225,35,87,149,206,12,154,88,3,193,181,119,44,238,196,6,93,159,235,41,114,176,0,195,155,88,43,232,176,115,86,149,205,14,125,190,230,37,172,111,55,244,135,68,28,223,250,57,97,162,209,18,74,137,69,134,222,29,110,173,245,54,19,208,136,75,56,251,163,96,233,42,114,177,194,1,89,154,191,124,36,231,148,87,15,204,138,73,17,210,161,98,58,249,220,31,71,132,247,52,108,175,38,229,189,126,13,206,150,85,112,179,235,40,91,152,192,3,207,12,84,151,228,39,127,188,153,90,2,193,178,113,41,234,99,160,248,59,72,139,211,16,53,246,174,109,30,221,133,70,9,202,146,81,34,225,185,122,95,156,196,7,116,183,239,44,165,102,62,253,142,77,21,214,243,48,104,171,216,27,67,128,76,143,215,20,103,164,252,63,26,217,129,66,49,242,170,105,224,35,123,184,203,8,80,147,182,117,45,238,157,94,6,197,131,64,24,219,168,107,51,240,213,22,78,141,254,61,101,166,47,236,180,119,4,199,159,92,121,186,226,33,82,145,201,10,198,5,93,158,237,46,118,181,144,83,11,200,187,120,32,227,106,169,241,50,65,130,218,25,60,255,167,100,23,212,140,79,0,196,149,81,55,243,162,102,110,170,251,63,89,157,204,8,220,24,73,141,235,47,126,186,178,118,39,227,133,65,16,212,165,97,48,244,146,86,7,195,203,15,94,154,252,56,105,173,121,189,236,40,78,138,219,31,23,211,130,70,32,228,181,113,87,147,194,6,96,164,245,49,57,253,172,104,14,202,155,95,139,79,30,218,188,120,41,237,229,33,112,180,210,22,71,131,242,54,103,163,197,1,80,148,156,88,9,205,171,111,62,250,46,234,187,127,25,221,140,72,64,132,213,17,119,179,226,38,174,106,59,255,153,93,12,200,192,4,85,145,247,51,98,166,114,182,231,35,69,129,208,20,28,216,137,77,43,239,190,122,11,207,158,90,60,248,169,109,101,161,240,52,82,150,199,3,215,19,66,134,224,36,117,177,185,125,44,232,142,74,27,223,249,61,108,168,206,10,91,159,151,83,2,198,160,100,53,241,37,225,176,116,18,214,135,67,75,143,222,26,124,184,233,45,92,152,201,13,107,175,254,58,50,246,167,99,5,193,144,84,128,68,21,209,183,115,34,230,238,42,123,191,217,29,76,136,0,197,151,82,51,246,164,97,102,163,241,52,85,144,194,7,204,9,91,158,255,58,104,173,170,111,61,248,153,92,14,203,133,64,18,215,182,115,33,228,227,38,116,177,208,21,71,130,73,140,222,27,122,191,237,40,47,234,184,125,28,217,139,78,23,210,128,69,36,225,179,118,113,180,230,35,66,135,213,16,219,30,76,137,232,45,127,186,189,120,42,239,142,75,25,220,146,87,5,192,161,100,54,243,244,49,99,166,199,2,80,149,94,155,201,12,109,168,250,63,56,253,175,106,11,206,156,89,46,235,185,124,29,216,138,79,72,141,223,26,123,190,236,41,226,39,117,176,209,20,70,131,132,65,19,214,183,114,32,229,171,110,60,249,152,93,15,202,205,8,90,159,254,59,105,172,103,162,240,53,84,145,195,6,1,196,150,83,50,247,165,96,57,252,174,107,10,207,157,88,95,154,200,13,108,169,251,62,245,48,98,167,198,3,81,148,147,86,4,193,160,101,55,242,188,121,43,238,143,74,24,221,218,31,77,136,233,44,126,187,112,181,231,34,67,134,212,17,22,211,129,68,37,224,178,119,0,198,145,87,63,249,174,104,126,184,239,41,65,135,208,22,252,58,109,171,195,5,82,148,130,68,19,213,189,123,44,234,229,35,116,178,218,28,75,141,155,93,10,204,164,98,53,243,25,223,136,78,38,224,183,113,103,161,246,48,88,158,201,15,215,17,70,128,232,46,121,191,169,111,56,254,150,80,7,193,43,237,186,124,20,210,133,67,85,147,196,2,106,172,251,61,50,244,163,101,13,203,156,90,76,138,221,27,115,181,226,36,206,8,95,153,241,55,96,166,176,118,33,231,143,73,30,216,179,117,34,228,140,74,29,219,205,11,92,154,242,52,99,165,79,137,222,24,112,182,225,39,49,247,160,102,14,200,159,89,86,144,199,1,105,175,248,62,40,238,185,127,23,209,134,64,170,108,59,253,149,83,4,194,212,18,69,131,235,45,122,188,100,162,245,51,91,157,202,12,26,220,139,77,37,227,180,114,152,94,9,207,167,97,54,240,230,32,119,177,217,31,72,142,129,71,16,214,190,120,47,233,255,57,110,168,192,6,81,151,125,187,236,42,66,132,211,21,3,197,146,84,60,250,173,107,0,199,147,84,59,252,168,111,118,177,229,34,77,138,222,25,236,43,127,184,215,16,68,131,154,93,9,206,161,102,50,245,197,2,86,145,254,57,109,170,179,116,32,231,136,79,27,220,41,238,186,125,18,213,129,70,95,152,204,11,100,163,247,48,151,80,4,195,172,107,63,248,225,38,114,181,218,29,73,142,123,188,232,47,64,135,211,20,13,202,158,89,54,241,165,98,82,149,193,6,105,174,250,61,36,227,183,112,31,216,140,75,190,121,45,234,133,66,22,209,200,15,91,156,243,52,96,167,51,244,160,103,8,207,155,92,69,130,214,17,126,185,237,42,223,24,76,139,228,35,119,176,169,110,58,253,146,85,1,198,246,49,101,162,205,10,94,153,128,71,19,212,187,124,40,239,26,221,137,78,33,230,178,117,108,171,255,56,87,144,196,3,164,99,55,240,159,88,12,203,210,21,65,134,233,46,122,189,72,143,219,28,115,180,224,39,62,249,173,106,5,194,150,81,97,166,242,53,90,157,201,14,23,208,132,67,44,235,191,120,141,74,30,217,182,113,37,226,251,60,104,175,192,7,83,148,0,200,141,69,7,207,138,66,14,198,131,75,9,193,132,76,28,212,145,89,27,211,150,94,18,218,159,87,21,221,152,80,56,240,181,125,63,247,178,122,54,254,187,115,49,249,188,116,36,236,169,97,35,235,174,102,42,226,167,111,45,229,160,104,112,184,253,53,119,191,250,50,126,182,243,59,121,177,244,60,108,164,225,41,107,163,230,46,98,170,239,39,101,173,232,32,72,128,197,13,79,135,194,10,70,142,203,3,65,137,204,4,84,156,217,17,83,155,222,22,90,146,215,31,93,149,208,24,224,40,109,165,231,47,106,162,238,38,99,171,233,33,100,172,252,52,113,185,251,51,118,190,242,58,127,183,245,61,120,176,216,16,85,157,223,23,82,154,214,30,91,147,209,25,92,148,196,12,73,129,195,11,78,134,202,2,71,143,205,5,64,136,144,88,29,213,151,95,26,210,158,86,19,219,153,81,20,220,140,68,1,201,139,67,6,206,130,74,15,199,133,77,8,192,168,96,37,237,175,103,34,234,166,110,43,227,161,105,44,228,180,124,57,241,179,123,62,246,186,114,55,255,189,117,48,248,0,201,143,70,3,202,140,69,6,207,137,64,5,204,138,67,12,197,131,74,15,198,128,73,10,195,133,76,9,192,134,79,24,209,151,94,27,210,148,93,30,215,145,88,29,212,146,91,20,221,155,82,23,222,152,81,18,219,157,84,17,216,158,87,48,249,191,118,51,250,188,117,54,255,185,112,53,252,186,115,60,245,179,122,63,246,176,121,58,243,181,124,57,240,182,127,40,225,167,110,43,226,164,109,46,231,161,104,45,228,162,107,36,237,171,98,39,238,168,97,34,235,173,100,33,232,174,103,96,169,239,38,99,170,236,37,102,175,233,32,101,172,234,35,108,165,227,42,111,166,224,41,106,163,229,44,105,160,230,47,120,177,247,62,123,178,244,61,126,183,241,56,125,180,242,59,116,189,251,50,119,190,248,49,114,187,253,52,113,184,254,55,80,153,223,22,83,154,220,21,86,159,217,16,85,156,218,19,92,149,211,26,95,150,208,25,90,147,213,28,89,144,214,31,72,129,199,14,75,130,196,13,78,135,193,8,77,132,194,11,68,141,203,2,71,142,200,1,66,139,205,4,65,136,206,7,0,202,137,67,15,197,134,76,30,212,151,93,17,219,152,82,60,246,181,127,51,249,186,112,34,232,171,97,45,231,164,110,120,178,241,59,119,189,254,52,102,172,239,37,105,163,224,42,68,142,205,7,75,129,194,8,90,144,211,25,85,159,220,22,240,58,121,179,255,53,118,188,238,36,103,173,225,43,104,162,204,6,69,143,195,9,74,128,210,24,91,145,221,23,84,158,136,66,1,203,135,77,14,196,150,92,31,213,153,83,16,218,180,126,61,247,187,113,50,248,170,96,35,233,165,111,44,230,253,55,116,190,242,56,123,177,227,41,106,160,236,38,101,175,193,11,72,130,206,4,71,141,223,21,86,156,208,26,89,147,133,79,12,198,138,64,3,201,155,81,18,216,148,94,29,215,185,115,48,250,182,124,63,245,167,109,46,228,168,98,33,235,13,199,132,78,2,200,139,65,19,217,154,80,28,214,149,95,49,251,184,114,62,244,183,125,47,229,166,108,32,234,169,99,117,191,252,54,122,176,243,57,107,161,226,40,100,174,237,39,73,131,192,10,70,140,207,5,87,157,222,20,88,146,209,27,0,203,139,64,11,192,128,75,22,221,157,86,29,214,150,93,44,231,167,108,39,236,172,103,58,241,177,122,49,250,186,113,88,147,211,24,83,152,216,19,78,133,197,14,69,142,206,5,116,191,255,52,127,180,244,63,98,169,233,34,105,162,226,41,176,123,59,240,187,112,48,251,166,109,45,230,173,102,38,237,156,87,23,220,151,92,28,215,138,65,1,202,129,74,10,193,232,35,99,168,227,40,104,163,254,53,117,190,245,62,126,181,196,15,79,132,207,4,68,143,210,25,89,146,217,18,82,153,125,182,246,61,118,189,253,54,107,160,224,43,96,171,235,32,81,154,218,17,90,145,209,26,71,140,204,7,76,135,199,12,37,238,174,101,46,229,165,110,51,248,184,115,56,243,179,120,9,194,130,73,2,201,137,66,31,212,148,95,20,223,159,84,205,6,70,141,198,13,77,134,219,16,80,155,208,27,91,144,225,42,106,161,234,33,97,170,247,60,124,183,252,55,119,188,149,94,30,213,158,85,21,222,131,72,8,195,136,67,3,200,185,114,50,249,178,121,57,242,175,100,36,239,164,111,47,228,0,204,133,73,23,219,146,94,46,226,171,103,57,245,188,112,92,144,217,21,75,135,206,2,114,190,247,59,101,169,224,44,184,116,61,241,175,99,42,230,150,90,19,223,129,77,4,200,228,40,97,173,243,63,118,186,202,6,79,131,221,17,88,148,109,161,232,36,122,182,255,51,67,143,198,10,84,152,209,29,49,253,180,120,38,234,163,111,31,211,154,86,8,196,141,65,213,25,80,156,194,14,71,139,251,55,126,178,236,32,105,165,137,69,12,192,158,82,27,215,167,107,34,238,176,124,53,249,218,22,95,147,205,1,72,132,244,56,113,189,227,47,102,170,134,74,3,207,145,93,20,216,168,100,45,225,191,115,58,246,98,174,231,43,117,185,240,60,76,128,201,5,91,151,222,18,62,242,187,119,41,229,172,96,16,220,149,89,7,203,130,78,183,123,50,254,160,108,37,233,153,85,28,208,142,66,11,199,235,39,110,162,252,48,121,181,197,9,64,140,210,30,87,155,15,195,138,70,24,212,157,81,33,237,164,104,54,250,179,127,83,159,214,26,68,136,193,13,125,177,248,52,106,166,239,35,0,205,135,74,19,222,148,89,38,235,161,108,53,248,178,127,76,129,203,6,95,146,216,21,106,167,237,32,121,180,254,51,152,85,31,210,139,70,12,193,190,115,57,244,173,96,42,231,212,25,83,158,199,10,64,141,242,63,117,184,225,44,102,171,45,224,170,103,62,243,185,116,11,198,140,65,24,213,159,82,97,172,230,43,114,191,245,56,71,138,192,13,84,153,211,30,181,120,50,255,166,107,33,236,147,94,20,217,128,77,7,202,249,52,126,179,234,39,109,160,223,18,88,149,204,1,75,134,90,151,221,16,73,132,206,3,124,177,251,54,111,162,232,37,22,219,145,92,5,200,130,79,48,253,183,122,35,238,164,105,194,15,69,136,209,28,86,155,228,41,99,174,247,58,112,189,142,67,9,196,157,80,26,215,168,101,47,226,187,118,60,241,119,186,240,61,100,169,227,46,81,156,214,27,66,143,197,8,59,246,188,113,40,229,175,98,29,208,154,87,14,195,137,68,239,34,104,165,252,49,123,182,201,4,78,131,218,23,93,144,163,110,36,233,176,125,55,250,133,72,2,207,150,91,17,220,0,206,129,79,31,209,158,80,62,240,191,113,33,239,160,110,124,178,253,51,99,173,226,44,66,140,195,13,93,147,220,18,248,54,121,183,231,41,102,168,198,8,71,137,217,23,88,150,132,74,5,203,155,85,26,212,186,116,59,245,165,107,36,234,237,35,108,162,242,60,115,189,211,29,82,156,204,2,77,131,145,95,16,222,142,64,15,193,175,97,46,224,176,126,49,255,21,219,148,90,10,196,139,69,43,229,170,100,52,250,181,123,105,167,232,38,118,184,247,57,87,153,214,24,72,134,201,7,199,9,70,136,216,22,89,151,249,55,120,182,230,40,103,169,187,117,58,244,164,106,37,235,133,75,4,202,154,84,27,213,63,241,190,112,32,238,161,111,1,207,128,78,30,208,159,81,67,141,194,12,92,146,221,19,125,179,252,50,98,172,227,45,42,228,171,101,53,251,180,122,20,218,149,91,11,197,138,68,86,152,215,25,73,135,200,6,104,166,233,39,119,185,246,56,210,28,83,157,205,3,76,130,236,34,109,163,243,61,114,188,174,96,47,225,177,127,48,254,144,94,17,223,143,65,14,192,0,207,131,76,27,212,152,87,54,249,181,122,45,226,174,97,108,163,239,32,119,184,244,59,90,149,217,22,65,142,194,13,216,23,91,148,195,12,64,143,238,33,109,162,245,58,118,185,180,123,55,248,175,96,44,227,130,77,1,206,153,86,26,213,173,98,46,225,182,121,53,250,155,84,24,215,128,79,3,204,193,14,66,141,218,21,89,150,247,56,116,187,236,35,111,160,117,186,246,57,110,161,237,34,67,140,192,15,88,151,219,20,25,214,154,85,2,205,129,78,47,224,172,99,52,251,183,120,71,136,196,11,92,147,223,16,113,190,242,61,106,165,233,38,43,228,168,103,48,255,179,124,29,210,158,81,6,201,133,74,159,80,28,211,132,75,7,200,169,102,42,229,178,125,49,254,243,60,112,191,232,39,107,164,197,10,70,137,222,17,93,146,234,37,105,166,241,62,114,189,220,19,95,144,199,8,68,139,134,73,5,202,157,82,30,209,176,127,51,252,171,100,40,231,50,253,177,126,41,230,170,101,4,203,135,72,31,208,156,83,94,145,221,18,69,138,198,9,104,167,235,36,115,188,240,63,0,208,189,109,103,183,218,10,206,30,115,163,169,121,20,196,129,81,60,236,230,54,91,139,79,159,242,34,40,248,149,69,31,207,162,114,120,168,197,21,209,1,108,188,182,102,11,219,158,78,35,243,249,41,68,148,80,128,237,61,55,231,138,90,62,238,131,83,89,137,228,52,240,32,77,157,151,71,42,250,191,111,2,210,216,8,101,181,113,161,204,28,22,198,171,123,33,241,156,76,70,150,251,43,239,63,82,130,136,88,53,229,160,112,29,205,199,23,122,170,110,190,211,3,9,217,180,100,124,172,193,17,27,203,166,118,178,98,15,223,213,5,104,184,253,45,64,144,154,74,39,247,51,227,142,94,84,132,233,57,99,179,222,14,4,212,185,105,173,125,16,192,202,26,119,167,226,50,95,143,133,85,56,232,44,252,145,65,75,155,246,38,66,146,255,47,37,245,152,72,140,92,49,225,235,59,86,134,195,19,126,174,164,116,25,201,13,221,176,96,106,186,215,7,93,141,224,48,58,234,135,87,147,67,46,254,244,36,73,153,220,12,97,177,187,107,6,214,18,194,175,127,117,165,200,24,0,209,191,110,99,178,220,13,198,23,121,168,165,116,26,203,145,64,46,255,242,35,77,156,87,134,232,57,52,229,139,90,63,238,128,81,92,141,227,50,249,40,70,151,154,75,37,244,174,127,17,192,205,28,114,163,104,185,215,6,11,218,180,101,126,175,193,16,29,204,162,115,184,105,7,214,219,10,100,181,239,62,80,129,140,93,51,226,41,248,150,71,74,155,245,36,65,144,254,47,34,243,157,76,135,86,56,233,228,53,91,138,208,1,111,190,179,98,12,221,22,199,169,120,117,164,202,27,252,45,67,146,159,78,32,241,58,235,133,84,89,136,230,55,109,188,210,3,14,223,177,96,171,122,20,197,200,25,119,166,195,18,124,173,160,113,31,206,5,212,186,107,102,183,217,8,82,131,237,60,49,224,142,95,148,69,43,250,247,38,72,153,130,83,61,236,225,48,94,143,68,149,251,42,39,246,152,73,19,194,172,125,112,161,207,30,213,4,106,187,182,103,9,216,189,108,2,211,222,15,97,176,123,170,196,21,24,201,167,118,44,253,147,66,79,158,240,33,234,59,85,132,137,88,54,231,0,210,185,107,111,189,214,4,222,12,103,181,177,99,8,218,161,115,24,202,206,28,119,165,127,173,198,20,16,194,169,123,95,141,230,52,48,226,137,91,129,83,56,234,238,60,87,133,254,44,71,149,145,67,40,250,32,242,153,75,79,157,246,36,190,108,7,213,209,3,104,186,96,178,217,11,15,221,182,100,31,205,166,116,112,162,201,27,193,19,120,170,174,124,23,197,225,51,88,138,142,92,55,229,63,237,134,84,80,130,233,59,64,146,249,43,47,253,150,68,158,76,39,245,241,35,72,154,97,179,216,10,14,220,183,101,191,109,6,212,208,2,105,187,192,18,121,171,175,125,22,196,30,204,167,117,113,163,200,26,62,236,135,85,81,131,232,58,224,50,89,139,143,93,54,228,159,77,38,244,240,34,73,155,65,147,248,42,46,252,151,69,223,13,102,180,176,98,9,219,1,211,184,106,110,188,215,5,126,172,199,21,17,195,168,122,160,114,25,203,207,29,118,164,128,82,57,235,239,61,86,132,94,140,231,53,49,227,136,90,33,243,152,74,78,156,247,37,255,45,70,148,144,66,41,251,0,211,187,104,107,184,208,3,214,5,109,190,189,110,6,213,177,98,10,217,218,9,97,178,103,180,220,15,12,223,183,100,127,172,196,23,20,199,175,124,169,122,18,193,194,17,121,170,206,29,117,166,165,118,30,205,24,203,163,112,115,160,200,27,254,45,69,150,149,70,46,253,40,251,147,64,67,144,248,43,79,156,244,39,36,247,159,76,153,74,34,241,242,33,73,154,129,82,58,233,234,57,81,130,87,132,236,63,60,239,135,84,48,227,139,88,91,136,224,51,230,53,93,142,141,94,54,229,225,50,90,137,138,89,49,226,55,228,140,95,92,143,231,52,80,131,235,56,59,232,128,83,134,85,61,238,237,62,86,133,158,77,37,246,245,38,78,157,72,155,243,32,35,240,152,75,47,252,148,71,68,151,255,44,249,42,66,145,146,65,41,250,31,204,164,119,116,167,207,28,201,26,114,161,162,113,25,202,174,125,21,198,197,22,126,173,120,171,195,16,19,192,168,123,96,179,219,8,11,216,176,99,182,101,13,222,221,14,102,181,209,2,106,185,186,105,1,210,7,212,188,111,108,191,215,4,0,212,181,97,119,163,194,22,238,58,91,143,153,77,44,248,193,21,116,160,182,98,3,215,47,251,154,78,88,140,237,57,159,75,42,254,232,60,93,137,113,165,196,16,6,210,179,103,94,138,235,63,41,253,156,72,176,100,5,209,199,19,114,166,35,247,150,66,84,128,225,53,205,25,120,172,186,110,15,219,226,54,87,131,149,65,32,244,12,216,185,109,123,175,206,26,188,104,9,221,203,31,126,170,82,134,231,51,37,241,144,68,125,169,200,28,10,222,191,107,147,71,38,242,228,48,81,133,70,146,243,39,49,229,132,80,168,124,29,201,223,11,106,190,135,83,50,230,240,36,69,145,105,189,220,8,30,202,171,127,217,13,108,184,174,122,27,207,55,227,130,86,64,148,245,33,24,204,173,121,111,187,218,14,246,34,67,151,129,85,52,224,101,177,208,4,18,198,167,115,139,95,62,234,252,40,73,157,164,112,17,197,211,7,102,178,74,158,255,43,61,233,136,92,250,46,79,155,141,89,56,236,20,192,161,117,99,183,214,2,59,239,142,90,76,152,249,45,213,1,96,180,162,118,23,195,0,213,183,98,115,166,196,17,230,51,81,132,149,64,34,247,209,4,102,179,162,119,21,192,55,226,128,85,68,145,243,38,191,106,8,221,204,25,123,174,89,140,238,59,42,255,157,72,110,187,217,12,29,200,170,127,136,93,63,234,251,46,76,153,99,182,212,1,16,197,167,114,133,80,50,231,246,35,65,148,178,103,5,208,193,20,118,163,84,129,227,54,39,242,144,69,220,9,107,190,175,122,24,205,58,239,141,88,73,156,254,43,13,216,186,111,126,171,201,28,235,62,92,137,152,77,47,250,198,19,113,164,181,96,2,215,32,245,151,66,83,134,228,49,23,194,160,117,100,177,211,6,241,36,70,147,130,87,53,224,121,172,206,27,10,223,189,104,159,74,40,253,236,57,91,142,168,125,31,202,219,14,108,185,78,155,249,44,61,232,138,95,165,112,18,199,214,3,97,180,67,150,244,33,48,229,135,82,116,161,195,22,7,210,176,101,146,71,37,240,225,52,86,131,26,207,173,120,105,188,222,11,252,41,75,158,143,90,56,237,203,30,124,169,184,109,15,218,45,248,154,79,94,139,233,60,0,214,177,103,127,169,206,24,254,40,79,153,129,87,48,230,225,55,80,134,158,72,47,249,31,201,174,120,96,182,209,7,223,9,110,184,160,118,17,199,33,247,144,70,94,136,239,57,62,232,143,89,65,151,240,38,192,22,113,167,191,105,14,216,163,117,18,196,220,10,109,187,93,139,236,58,34,244,147,69,66,148,243,37,61,235,140,90,188,106,13,219,195,21,114,164,124,170,205,27,3,213,178,100,130,84,51,229,253,43,76,154,157,75,44,250,226,52,83,133,99,181,210,4,28,202,173,123,91,141,234,60,36,242,149,67,165,115,20,194,218,12,107,189,186,108,11,221,197,19,116,162,68,146,245,35,59,237,138,92,132,82,53,227,251,45,74,156,122,172,203,29,5,211,180,98,101,179,212,2,26,204,171,125,155,77,42,252,228,50,85,131,248,46,73,159,135,81,54,224,6,208,183,97,121,175,200,30,25,207,168,126,102,176,215,1,231,49,86,128,152,78,41,255,39,241,150,64,88,142,233,63,217,15,104,190,166,112,23,193,198,16,119,161,185,111,8,222,56,238,137,95,71,145,246,32,0,215,179,100,123,172,200,31,246,33,69,146,141,90,62,233,241,38,66,149,138,93,57,238,7,208,180,99,124,171,207,24,255,40,76,155,132,83,55,224,9,222,186,109,114,165,193,22,14,217,189,106,117,162,198,17,248,47,75,156,131,84,48,231,227,52,80,135,152,79,43,252,21,194,166,113,110,185,221,10,18,197,161,118,105,190,218,13,228,51,87,128,159,72,44,251,28,203,175,120,103,176,212,3,234,61,89,142,145,70,34,245,237,58,94,137,150,65,37,242,27,204,168,127,96,183,211,4,219,12,104,191,160,119,19,196,45,250,158,73,86,129,229,50,42,253,153,78,81,134,226,53,220,11,111,184,167,112,20,195,36,243,151,64,95,136,236,59,210,5,97,182,169,126,26,205,213,2,102,177,174,121,29,202,35,244,144,71,88,143,235,60,56,239,139,92,67,148,240,39,206,25,125,170,181,98,6,209,201,30,122,173,178,101,1,214,63,232,140,91,68,147,247,32,199,16,116,163,188,107,15,216,49,230,130,85,74,157,249,46,54,225,133,82,77,154,254,41,192,23,115,164,187,108,8,223,0,216,173,117,71,159,234,50,142,86,35,251,201,17,100,188,1,217,172,116,70,158,235,51,143,87,34,250,200,16,101,189,2,218,175,119,69,157,232,48,140,84,33,249,203,19,102,190,3,219,174,118,68,156,233,49,141,85,32,248,202,18,103,191,4,220,169,113,67,155,238,54,138,82,39,255,205,21,96,184,5,221,168,112,66,154,239,55,139,83,38,254,204,20,97,185,6,222,171,115,65,153,236,52,136,80,37,253,207,23,98,186,7,223,170,114,64,152,237,53,137,81,36,252,206,22,99,187,8,208,165,125,79,151,226,58,134,94,43,243,193,25,108,180,9,209,164,124,78,150,227,59,135,95,42,242,192,24,109,181,10,210,167,127,77,149,224,56,132,92,41,241,195,27,110,182,11,211,166,126,76,148,225,57,133,93,40,240,194,26,111,183,12,212,161,121,75,147,230,62,130,90,47,247,197,29,104,176,13,213,160,120,74,146,231,63,131,91,46,246,196,28,105,177,14,214,163,123,73,145,228,60,128,88,45,245,199,31,106,178,15,215,162,122,72,144,229,61,129,89,44,244,198,30,107,179,0,217,175,118,67,154,236,53,134,95,41,240,197,28,106,179,17,200,190,103,82,139,253,36,151,78,56,225,212,13,123,162,34,251,141,84,97,184,206,23,164,125,11,210,231,62,72,145,51,234,156,69,112,169,223,6,181,108,26,195,246,47,89,128,68,157,235,50,7,222,168,113,194,27,109,180,129,88,46,247,85,140,250,35,22,207,185,96,211,10,124,165,144,73,63,230,102,191,201,16,37,252,138,83,224,57,79,150,163,122,12,213,119,174,216,1,52,237,155,66,241,40,94,135,178,107,29,196,136,81,39,254,203,18,100,189,14,215,161,120,77,148,226,59,153,64,54,239,218,3,117,172,31,198,176,105,92,133,243,42,170,115,5,220,233,48,70,159,44,245,131,90,111,182,192,25,187,98,20,205,248,33,87,142,61,228,146,75,126,167,209,8,204,21,99,186,143,86,32,249,74,147,229,60,9,208,166,127,221,4,114,171,158,71,49,232,91,130,244,45,24,193,183,110,238,55,65,152,173,116,2,219,104,177,199,30,43,242,132,93,255,38,80,137,188,101,19,202,121,160,214,15,58,227,149,76,0,218,169,115,79,149,230,60,158,68,55,237,209,11,120,162,33,251,136,82,110,180,199,29,191,101,22,204,240,42,89,131,66,152,235,49,13,215,164,126,220,6,117,175,147,73,58,224,99,185,202,16,44,246,133,95,253,39,84,142,178,104,27,193,132,94,45,247,203,17,98,184,26,192,179,105,85,143,252,38,165,127,12,214,234,48,67,153,59,225,146,72,116,174,221,7,198,28,111,181,137,83,32,250,88,130,241,43,23,205,190,100,231,61,78,148,168,114,1,219,121,163,208,10,54,236,159,69,21,207,188,102,90,128,243,41,139,81,34,248,196,30,109,183,52,238,157,71,123,161,210,8,170,112,3,217,229,63,76,150,87,141,254,36,24,194,177,107,201,19,96,186,134,92,47,245,118,172,223,5,57,227,144,74,232,50,65,155,167,125,14,212,145,75,56,226,222,4,119,173,15,213,166,124,64,154,233,51,176,106,25,195,255,37,86,140,46,244,135,93,97,187,200,18,211,9,122,160,156,70,53,239,77,151,228,62,2,216,171,113,242,40,91,129,189,103,20,206,108,182,197,31,35,249,138,80,0,219,171,112,75,144,224,59,150,77,61,230,221,6,118,173,49,234,154,65,122,161,209,10,167,124,12,215,236,55,71,156,98,185,201,18,41,242,130,89,244,47,95,132,191,100,20,207,83,136,248,35,24,195,179,104,197,30,110,181,142,85,37,254,196,31,111,180,143,84,36,255,82,137,249,34,25,194,178,105,245,46,94,133,190,101,21,206,99,184,200,19,40,243,131,88,166,125,13,214,237,54,70,157,48,235,155,64,123,160,208,11,151,76,60,231,220,7,119,172,1,218,170,113,74,145,225,58,149,78,62,229,222,5,117,174,3,216,168,115,72,147,227,56,164,127,15,212,239,52,68,159,50,233,153,66,121,162,210,9,247,44,92,135,188,103,23,204,97,186,202,17,42,241,129,90,198,29,109,182,141,86,38,253,80,139,251,32,27,192,176,107,81,138,250,33,26,193,177,106,199,28,108,183,140,87,39,252,96,187,203,16,43,240,128,91,246,45,93,134,189,102,22,205,51,232,152,67,120,163,211,8,165,126,14,213,238,53,69,158,2,217,169,114,73,146,226,57,148,79,63,228,223,4,116,175,0,220,165,121,87,139,242,46,174,114,11,215,249,37,92,128,65,157,228,56,22,202,179,111,239,51,74,150,184,100,29,193,130,94,39,251,213,9,112,172,44,240,137,85,123,167,222,2,195,31,102,186,148,72,49,237,109,177,200,20,58,230,159,67,25,197,188,96,78,146,235,55,183,107,18,206,224,60,69,153,88,132,253,33,15,211,170,118,246,42,83,143,161,125,4,216,155,71,62,226,204,16,105,181,53,233,144,76,98,190,199,27,218,6,127,163,141,81,40,244,116,168,209,13,35,255,134,90,50,238,151,75,101,185,192,28,156,64,57,229,203,23,110,178,115,175,214,10,36,248,129,93,221,1,120,164,138,86,47,243,176,108,21,201,231,59,66,158,30,194,187,103,73,149,236,48,241,45,84,136,166,122,3,223,95,131,250,38,8,212,173,113,43,247,142,82,124,160,217,5,133,89,32,252,210,14,119,171,106,182,207,19,61,225,152,68,196,24,97,189,147,79,54,234,169,117,12,208,254,34,91,135,7,219,162,126,80,140,245,41,232,52,77,145,191,99,26,198,70,154,227,63,17,205,180,104,0,221,167,122,83,142,244,41,166,123,1,220,245,40,82,143,81,140,246,43,2,223,165,120,247,42,80,141,164,121,3,222,162,127,5,216,241,44,86,139,4,217,163,126,87,138,240,45,243,46,84,137,160,125,7,218,85,136,242,47,6,219,161,124,89,132,254,35,10,215,173,112,255,34,88,133,172,113,11,214,8,213,175,114,91,134,252,33,174,115,9,212,253,32,90,135,251,38,92,129,168,117,15,210,93,128,250,39,14,211,169,116,170,119,13,208,249,36,94,131,12,209,171,118,95,130,248,37,178,111,21,200,225,60,70,155,20,201,179,110,71,154,224,61,227,62,68,153,176,109,23,202,69,152,226,63,22,203,177,108,16,205,183,106,67,158,228,57,182,107,17,204,229,56,66,159,65,156,230,59,18,207,181,104,231,58,64,157,180,105,19,206,235,54,76,145,184,101,31,194,77,144,234,55,30,195,185,100,186,103,29,192,233,52,78,147,28,193,187,102,79,146,232,53,73,148,238,51,26,199,189,96,239,50,72,149,188,97,27,198,24,197,191,98,75,150,236,49,190,99,25,196,237,48,74,151,0,222,161,127,95,129,254,32,190,96,31,193,225,63,64,158,97,191,192,30,62,224,159,65,223,1,126,160,128,94,33,255,194,28,99,189,157,67,60,226,124,162,221,3,35,253,130,92,163,125,2,220,252,34,93,131,29,195,188,98,66,156,227,61,153,71,56,230,198,24,103,185,39,249,134,88,120,166,217,7,248,38,89,135,167,121,6,216,70,152,231,57,25,199,184,102,91,133,250,36,4,218,165,123,229,59,68,154,186,100,27,197,58,228,155,69,101,187,196,26,132,90,37,251,219,5,122,164,47,241,142,80,112,174,209,15,145,79,48,238,206,16,111,177,78,144,239,49,17,207,176,110,240,46,81,143,175,113,14,208,237,51,76,146,178,108,19,205,83,141,242,44,12,210,173,115,140,82,45,243,211,13,114,172,50,236,147,77,109,179,204,18,182,104,23,201,233,55,72,150,8,214,169,119,87,137,246,40,215,9,118,168,136,86,41,247,105,183,200,22,54,232,151,73,116,170,213,11,43,245,138,84,202,20,107,181,149,75,52,234,21,203,180,106,74,148,235,53,171,117,10,212,244,42,85,139,0,223,163,124,91,132,248,39,182,105,21,202,237,50,78,145,113,174,210,13,42,245,137,86,199,24,100,187,156,67,63,224,226,61,65,158,185,102,26,197,84,139,247,40,15,208,172,115,147,76,48,239,200,23,107,180,37,250,134,89,126,161,221,2,217,6,122,165,130,93,33,254,111,176,204,19,52,235,151,72,168,119,11,212,243,44,80,143,30,193,189,98,69,154,230,57,59,228,152,71,96,191,195,28,141,82,46,241,214,9,117,170,74,149,233,54,17,206,178,109,252,35,95,128,167,120,4,219,175,112,12,211,244,43,87,136,25,198,186,101,66,157,225,62,222,1,125,162,133,90,38,249,104,183,203,20,51,236,144,79,77,146,238,49,22,201,181,106,251,36,88,135,160,127,3,220,60,227,159,64,103,184,196,27,138,85,41,246,209,14,114,173,118,169,213,10,45,242,142,81,192,31,99,188,155,68,56,231,7,216,164,123,92,131,255,32,177,110,18,205,234,53,73,150,148,75,55,232,207,16,108,179,34,253,129,94,121,166,218,5,229,58,70,153,190,97,29,194,83,140,240,47,8,215,171,116,0,224,221,61,167,71,122,154,83,179,142,110,244,20,41,201,166,70,123,155,1,225,220,60,245,21,40,200,82,178,143,111,81,177,140,108,246,22,43,203,2,226,223,63,165,69,120,152,247,23,42,202,80,176,141,109,164,68,121,153,3,227,222,62,162,66,127,159,5,229,216,56,241,17,44,204,86,182,139,107,4,228,217,57,163,67,126,158,87,183,138,106,240,16,45,205,243,19,46,206,84,180,137,105,160,64,125,157,7,231,218,58,85,181,136,104,242,18,47,207,6,230,219,59,161,65,124,156,89,185,132,100,254,30,35,195,10,234,215,55,173,77,112,144,255,31,34,194,88,184,133,101,172,76,113,145,11,235,214,54,8,232,213,53,175,79,114,146,91,187,134,102,252,28,33,193,174,78,115,147,9,233,212,52,253,29,32,192,90,186,135,103,251,27,38,198,92,188,129,97,168,72,117,149,15,239,210,50,93,189,128,96,250,26,39,199,14,238,211,51,169,73,116,148,170,74,119,151,13,237,208,48,249,25,36,196,94,190,131,99,12,236,209,49,171,75,118,150,95,191,130,98,248,24,37,197,0,225,223,62,163,66,124,157,91,186,132,101,248,25,39,198,182,87,105,136,21,244,202,43,237,12,50,211,78,175,145,112,113,144,174,79,210,51,13,236,42,203,245,20,137,104,86,183,199,38,24,249,100,133,187,90,156,125,67,162,63,222,224,1,226,3,61,220,65,160,158,127,185,88,102,135,26,251,197,36,84,181,139,106,247,22,40,201,15,238,208,49,172,77,115,146,147,114,76,173,48,209,239,14,200,41,23,246,107,138,180,85,37,196,250,27,134,103,89,184,126,159,161,64,221,60,2,227,217,56,6,231,122,155,165,68,130,99,93,188,33,192,254,31,111,142,176,81,204,45,19,242,52,213,235,10,151,118,72,169,168,73,119,150,11,234,212,53,243,18,44,205,80,177,143,110,30,255,193,32,189,92,98,131,69,164,154,123,230,7,57,216,59,218,228,5,152,121,71,166,96,129,191,94,195,34,28,253,141,108,82,179,46,207,241,16,214,55,9,232,117,148,170,75,74,171,149,116,233,8,54,215,17,240,206,47,178,83,109,140,252,29,35,194,95,190,128,97,167,70,120,153,4,229,219,58,0,226,217,59,175,77,118,148,67,161,154,120,236,14,53,215,134,100,95,189,41,203,240,18,197,39,28,254,106,136,179,81,17,243,200,42,190,92,103,133,82,176,139,105,253,31,36,198,151,117,78,172,56,218,225,3,212,54,13,239,123,153,162,64,34,192,251,25,141,111,84,182,97,131,184,90,206,44,23,245,164,70,125,159,11,233,210,48,231,5,62,220,72,170,145,115,51,209,234,8,156,126,69,167,112,146,169,75,223,61,6,228,181,87,108,142,26,248,195,33,246,20,47,205,89,187,128,98,68,166,157,127,235,9,50,208,7,229,222,60,168,74,113,147,194,32,27,249,109,143,180,86,129,99,88,186,46,204,247,21,85,183,140,110,250,24,35,193,22,244,207,45,185,91,96,130,211,49,10,232,124,158,165,71,144,114,73,171,63,221,230,4,102,132,191,93,201,43,16,242,37,199,252,30,138,104,83,177,224,2,57,219,79,173,150,116,163,65,122,152,12,238,213,55,119,149,174,76,216,58,1,227,52,214,237,15,155,121,66,160,241,19,40,202,94,188,135,101,178,80,107,137,29,255,196,38,0,227,219,56,171,72,112,147,75,168,144,115,224,3,59,216,150,117,77,174,61,222,230,5,221,62,6,229,118,149,173,78,49,210,234,9,154,121,65,162,122,153,161,66,209,50,10,233,167,68,124,159,12,239,215,52,236,15,55,212,71,164,156,127,98,129,185,90,201,42,18,241,41,202,242,17,130,97,89,186,244,23,47,204,95,188,132,103,191,92,100,135,20,247,207,44,83,176,136,107,248,27,35,192,24,251,195,32,179,80,104,139,197,38,30,253,110,141,181,86,142,109,85,182,37,198,254,29,196,39,31,252,111,140,180,87,143,108,84,183,36,199,255,28,82,177,137,106,249,26,34,193,25,250,194,33,178,81,105,138,245,22,46,205,94,189,133,102,190,93,101,134,21,246,206,45,99,128,184,91,200,43,19,240,40,203,243,16,131,96,88,187,166,69,125,158,13,238,214,53,237,14,54,213,70,165,157,126,48,211,235,8,155,120,64,163,123,152,160,67,208,51,11,232,151,116,76,175,60,223,231,4,220,63,7,228,119,148,172,79,1,226,218,57,170,73,113,146,74,169,145,114,225,2,58,217,0,228,213,49,183,83,98,134,115,151,166,66,196,32,17,245,230,2,51,215,81,181,132,96,149,113,64,164,34,198,247,19,209,53,4,224,102,130,179,87,162,70,119,147,21,241,192,36,55,211,226,6,128,100,85,177,68,160,145,117,243,23,38,194,191,91,106,142,8,236,221,57,204,40,25,253,123,159,174,74,89,189,140,104,238,10,59,223,42,206,255,27,157,121,72,172,110,138,187,95,217,61,12,232,29,249,200,44,170,78,127,155,136,108,93,185,63,219,234,14,251,31,46,202,76,168,153,125,99,135,182,82,212,48,1,229,16,244,197,33,167,67,114,150,133,97,80,180,50,214,231,3,246,18,35,199,65,165,148,112,178,86,103,131,5,225,208,52,193,37,20,240,118,146,163,71,84,176,129,101,227,7,54,210,39,195,242,22,144,116,69,161,220,56,9,237,107,143,190,90,175,75,122,158,24,252,205,41,58,222,239,11,141,105,88,188,73,173,156,120,254,26,43,207,13,233,216,60,186,94,111,139,126,154,171,79,201,45,28,248,235,15,62,218,92,184,137,109,152,124,77,169,47,203,250,30,0,229,215,50,179,86,100,129,123,158,172,73,200,45,31,250,246,19,33,196,69,160,146,119,141,104,90,191,62,219,233,12,241,20,38,195,66,167,149,112,138,111,93,184,57,220,238,11,7,226,208,53,180,81,99,134,124,153,171,78,207,42,24,253,255,26,40,205,76,169,155,126,132,97,83,182,55,210,224,5,9,236,222,59,186,95,109,136,114,151,165,64,193,36,22,243,14,235,217,60,189,88,106,143,117,144,162,71,198,35,17,244,248,29,47,202,75,174,156,121,131,102,84,177,48,213,231,2,227,6,52,209,80,181,135,98,152,125,79,170,43,206,252,25,21,240,194,39,166,67,113,148,110,139,185,92,221,56,10,239,18,247,197,32,161,68,118,147,105,140,190,91,218,63,13,232,228,1,51,214,87,178,128,101,159,122,72,173,44,201,251,30,28,249,203,46,175,74,120,157,103,130,176,85,212,49,3,230,234,15,61,216,89,188,142,107,145,116,70,163,34,199,245,16,237,8,58,223,94,187,137,108,150,115,65,164,37,192,242,23,27,254,204,41,168,77,127,154,96,133,183,82,211,54,4,225,0,230,209,55,191,89,110,136,99,133,178,84,220,58,13,235,198,32,23,241,121,159,168,78,165,67,116,146,26,252,203,45,145,119,64,166,46,200,255,25,242,20,35,197,77,171,156,122,87,177,134,96,232,14,57,223,52,210,229,3,139,109,90,188,63,217,238,8,128,102,81,183,92,186,141,107,227,5,50,212,249,31,40,206,70,160,151,113,154,124,75,173,37,195,244,18,174,72,127,153,17,247,192,38,205,43,28,250,114,148,163,69,104,142,185,95,215,49,6,224,11,237,218,60,180,82,101,131,126,152,175,73,193,39,16,246,29,251,204,42,162,68,115,149,184,94,105,143,7,225,214,48,219,61,10,236,100,130,181,83,239,9,62,216,80,182,129,103,140,106,93,187,51,213,226,4,41,207,248,30,150,112,71,161,74,172,155,125,245,19,36,194,65,167,144,118,254,24,47,201,34,196,243,21,157,123,76,170,135,97,86,176,56,222,233,15,228,2,53,211,91,189,138,108,208,54,1,231,111,137,190,88,179,85,98,132,12,234,221,59,22,240,199,33,169,79,120,158,117,147,164,66,202,44,27,253,0,231,211,52,187,92,104,143,107,140,184,95,208,55,3,228,214,49,5,226,109,138,190,89,189,90,110,137,6,225,213,50,177,86,98,133,10,237,217,62,218,61,9,238,97,134,178,85,103,128,180,83,220,59,15,232,12,235,223,56,183,80,100,131,127,152,172,75,196,35,23,240,20,243,199,32,175,72,124,155,169,78,122,157,18,245,193,38,194,37,17,246,121,158,170,77,206,41,29,250,117,146,166,65,165,66,118,145,30,249,205,42,24,255,203,44,163,68,112,151,115,148,160,71,200,47,27,252,254,25,45,202,69,162,150,113,149,114,70,161,46,201,253,26,40,207,251,28,147,116,64,167,67,164,144,119,248,31,43,204,79,168,156,123,244,19,39,192,36,195,247,16,159,120,76,171,153,126,74,173,34,197,241,22,242,21,33,198,73,174,154,125,129,102,82,181,58,221,233,14,234,13,57,222,81,182,130,101,87,176,132,99,236,11,63,216,60,219,239,8,135,96,84,179,48,215,227,4,139,108,88,191,91,188,136,111,224,7,51,212,230,1,53,210,93,186,142,105,141,106,94,185,54,209,229,2,0,232,205,37,135,111,74,162,19,251,222,54,148,124,89,177,38,206,235,3,161,73,108,132,53,221,248,16,178,90,127,151,76,164,129,105,203,35,6,238,95,183,146,122,216,48,21,253,106,130,167,79,237,5,32,200,121,145,180,92,254,22,51,219,152,112,85,189,31,247,210,58,139,99,70,174,12,228,193,41,190,86,115,155,57,209,244,28,173,69,96,136,42,194,231,15,212,60,25,241,83,187,158,118,199,47,10,226,64,168,141,101,242,26,63,215,117,157,184,80,225,9,44,196,102,142,171,67,45,197,224,8,170,66,103,143,62,214,243,27,185,81,116,156,11,227,198,46,140,100,65,169,24,240,213,61,159,119,82,186,97,137,172,68,230,14,43,195,114,154,191,87,245,29,56,208,71,175,138,98,192,40,13,229,84,188,153,113,211,59,30,246,181,93,120,144,50,218,255,23,166,78,107,131,33,201,236,4,147,123,94,182,20,252,217,49,128,104,77,165,7,239,202,34,249,17,52,220,126,150,179,91,234,2,39,207,109,133,160,72,223,55,18,250,88,176,149,125,204,36,1,233,75,163,134,110,0,233,207,38,131,106,76,165,27,242,212,61,152,113,87,190,54,223,249,16,181,92,122,147,45,196,226,11,174,71,97,136,108,133,163,74,239,6,32,201,119,158,184,81,244,29,59,210,90,179,149,124,217,48,22,255,65,168,142,103,194,43,13,228,216,49,23,254,91,178,148,125,195,42,12,229,64,169,143,102,238,7,33,200,109,132,162,75,245,28,58,211,118,159,185,80,180,93,123,146,55,222,248,17,175,70,96,137,44,197,227,10,130,107,77,164,1,232,206,39,153,112,86,191,26,243,213,60,173,68,98,139,46,199,225,8,182,95,121,144,53,220,250,19,155,114,84,189,24,241,215,62,128,105,79,166,3,234,204,37,193,40,14,231,66,171,141,100,218,51,21,252,89,176,150,127,247,30,56,209,116,157,187,82,236,5,35,202,111,134,160,73,117,156,186,83,246,31,57,208,110,135,161,72,237,4,34,203,67,170,140,101,192,41,15,230,88,177,151,126,219,50,20,253,25,240,214,63,154,115,85,188,2,235,205,36,129,104,78,167,47,198,224,9,172,69,99,138,52,221,251,18,183,94,120,145,0,234,201,35,143,101,70,172,3,233,202,32,140,102,69,175,6,236,207,37,137,99,64,170,5,239,204,38,138,96,67,169,12,230,197,47,131,105,74,160,15,229,198,44,128,106,73,163,10,224,195,41,133,111,76,166,9,227,192,42,134,108,79,165,24,242,209,59,151,125,94,180,27,241,210,56,148,126,93,183,30,244,215,61,145,123,88,178,29,247,212,62,146,120,91,177,20,254,221,55,155,113,82,184,23,253,222,52,152,114,81,187,18,248,219,49,157,119,84,190,17,251,216,50,158,116,87,189,48,218,249,19,191,85,118,156,51,217,250,16,188,86,117,159,54,220,255,21,185,83,112,154,53,223,252,22,186,80,115,153,60,214,245,31,179,89,122,144,63,213,246,28,176,90,121,147,58,208,243,25,181,95,124,150,57,211,240,26,182,92,127,149,40,194,225,11,167,77,110,132,43,193,226,8,164,78,109,135,46,196,231,13,161,75,104,130,45,199,228,14,162,72,107,129,36,206,237,7,171,65,98,136,39,205,238,4,168,66,97,139,34,200,235,1,173,71,100,142,33,203,232,2,174,68,103,141,0,235,203,32,139,96,64,171,11,224,192,43,128,107,75,160,22,253,221,54,157,118,86,189,29,246,214,61,150,125,93,182,44,199,231,12,167,76,108,135,39,204,236,7,172,71,103,140,58,209,241,26,177,90,122,145,49,218,250,17,186,81,113,154,88,179,147,120,211,56,24,243,83,184,152,115,216,51,19,248,78,165,133,110,197,46,14,229,69,174,142,101,206,37,5,238,116,159,191,84,255,20,52,223,127,148,180,95,244,31,63,212,98,137,169,66,233,2,34,201,105,130,162,73,226,9,41,194,176,91,123,144,59,208,240,27,187,80,112,155,48,219,251,16,166,77,109,134,45,198,230,13,173,70,102,141,38,205,237,6,156,119,87,188,23,252,220,55,151,124,92,183,28,247,215,60,138,97,65,170,1,234,202,33,129,106,74,161,10,225,193,42,232,3,35,200,99,136,168,67,227,8,40,195,104,131,163,72,254,21,53,222,117,158,190,85,245,30,62,213,126,149,181,94,196,47,15,228,79,164,132,111,207,36,4,239,68,175,143,100,210,57,25,242,89,178,146,121,217,50,18,249,82,185,153,114,0,236,197,41,151,123,82,190,51,223,246,26,164,72,97,141,102,138,163,79,241,29,52,216,85,185,144,124,194,46,7,235,204,32,9,229,91,183,158,114,255,19,58,214,104,132,173,65,170,70,111,131,61,209,248,20,153,117,92,176,14,226,203,39,133,105,64,172,18,254,215,59,182,90,115,159,33,205,228,8,227,15,38,202,116,152,177,93,208,60,21,249,71,171,130,110,73,165,140,96,222,50,27,247,122,150,191,83,237,1,40,196,47,195,234,6,184,84,125,145,28,240,217,53,139,103,78,162,23,251,210,62,128,108,69,169,36,200,225,13,179,95,118,154,113,157,180,88,230,10,35,207,66,174,135,107,213,57,16,252,219,55,30,242,76,160,137,101,232,4,45,193,127,147,186,86,189,81,120,148,42,198,239,3,142,98,75,167,25,245,220,48,146,126,87,187,5,233,192,44,161,77,100,136,54,218,243,31,244,24,49,221,99,143,166,74,199,43,2,238,80,188,149,121,94,178,155,119,201,37,12,224,109,129,168,68,250,22,63,211,56,212,253,17,175,67,106,134,11,231,206,34,156,112,89,181,0,237,199,42,147,126,84,185,59,214,252,17,168,69,111,130,118,155,177,92,229,8,34,207,77,160,138,103,222,51,25,244,236,1,43,198,127,146,184,85,215,58,16,253,68,169,131,110,154,119,93,176,9,228,206,35,161,76,102,139,50,223,245,24,197,40,2,239,86,187,145,124,254,19,57,212,109,128,170,71,179,94,116,153,32,205,231,10,136,101,79,162,27,246,220,49,41,196,238,3,186,87,125,144,18,255,213,56,129,108,70,171,95,178,152,117,204,33,11,230,100,137,163,78,247,26,48,221,151,122,80,189,4,233,195,46,172,65,107,134,63,210,248,21,225,12,38,203,114,159,181,88,218,55,29,240,73,164,142,99,123,150,188,81,232,5,47,194,64,173,135,106,211,62,20,249,13,224,202,39,158,115,89,180,54,219,241,28,165,72,98,143,82,191,149,120,193,44,6,235,105,132,174,67,250,23,61,208,36,201,227,14,183,90,112,157,31,242,216,53,140,97,75,166,190,83,121,148,45,192,234,7,133,104,66,175,22,251,209,60,200,37,15,226,91,182,156,113,243,30,52,217,96,141,167,74,0,238,193,47,159,113,94,176,35,205,226,12,188,82,125,147,70,168,135,105,217,55,24,246,101,139,164,74,250,20,59,213,140,98,77,163,19,253,210,60,175,65,110,128,48,222,241,31,202,36,11,229,85,187,148,122,233,7,40,198,118,152,183,89,5,235,196,42,154,116,91,181,38,200,231,9,185,87,120,150,67,173,130,108,220,50,29,243,96,142,161,79,255,17,62,208,137,103,72,166,22,248,215,57,170,68,107,133,53,219,244,26,207,33,14,224,80,190,145,127,236,2,45,195,115,157,178,92,10,228,203,37,149,123,84,186,41,199,232,6,182,88,119,153,76,162,141,99,211,61,18,252,111,129,174,64,240,30,49,223,134,104,71,169,25,247,216,54,165,75,100,138,58,212,251,21,192,46,1,239,95,177,158,112,227,13,34,204,124,146,189,83,15,225,206,32,144,126,81,191,44,194,237,3,179,93,114,156,73,167,136,102,214,56,23,249,106,132,171,69,245,27,52,218,131,109,66,172,28,242,221,51,160,78,97,143,63,209,254,16,197,43,4,234,90,180,155,117,230,8,39,201,121,151,184,86,0,239,195,44,155,116,88,183,43,196,232,7,176,95,115,156,86,185,149,122,205,34,14,225,125,146,190,81,230,9,37,202,172,67,111,128,55,216,244,27,135,104,68,171,28,243,223,48,250,21,57,214,97,142,162,77,209,62,18,253,74,165,137,102,69,170,134,105,222,49,29,242,110,129,173,66,245,26,54,217,19,252,208,63,136,103,75,164,56,215,251,20,163,76,96,143,233,6,42,197,114,157,177,94,194,45,1,238,89,182,154,117,191,80,124,147,36,203,231,8,148,123,87,184,15,224,204,35,138,101,73,166,17,254,210,61,161,78,98,141,58,213,249,22,220,51,31,240,71,168,132,107,247,24,52,219,108,131,175,64,38,201,229,10,189,82,126,145,13,226,206,33,150,121,85,186,112,159,179,92,235,4,40,199,91,180,152,119,192,47,3,236,207,32,12,227,84,187,151,120,228,11,39,200,127,144,188,83,153,118,90,181,2,237,193,46,178,93,113,158,41,198,234,5,99,140,160,79,248,23,59,212,72,167,139,100,211,60,16,255,53,218,246,25,174,65,109,130,30,241,221,50,133,106,70,169,0,240,253,13,231,23,26,234,211,35,46,222,52,196,201,57,187,75,70,182,92,172,161,81,104,152,149,101,143,127,114,130,107,155,150,102,140,124,113,129,184,72,69,181,95,175,162,82,208,32,45,221,55,199,202,58,3,243,254,14,228,20,25,233,214,38,43,219,49,193,204,60,5,245,248,8,226,18,31,239,109,157,144,96,138,122,119,135,190,78,67,179,89,169,164,84,189,77,64,176,90,170,167,87,110,158,147,99,137,121,116,132,6,246,251,11,225,17,28,236,213,37,40,216,50,194,207,63,177,65,76,188,86,166,171,91,98,146,159,111,133,117,120,136,10,250,247,7,237,29,16,224,217,41,36,212,62,206,195,51,218,42,39,215,61,205,192,48,9,249,244,4,238,30,19,227,97,145,156,108,134,118,123,139,178,66,79,191,85,165,168,88,103,151,154,106,128,112,125,141,180,68,73,185,83,163,174,94,220,44,33,209,59,203,198,54,15,255,242,2,232,24,21,229,12,252,241,1,235,27,22,230,223,47,34,210,56,200,197,53,183,71,74,186,80,160,173,93,100,148,153,105,131,115,126,142,0,241,255,14,227,18,28,237,219,42,36,213,56,201,199,54,171,90,84,165,72,185,183,70,112,129,143,126,147,98,108,157,75,186,180,69,168,89,87,166,144,97,111,158,115,130,140,125,224,17,31,238,3,242,252,13,59,202,196,53,216,41,39,214,150,103,105,152,117,132,138,123,77,188,178,67,174,95,81,160,61,204,194,51,222,47,33,208,230,23,25,232,5,244,250,11,221,44,34,211,62,207,193,48,6,247,249,8,229,20,26,235,118,135,137,120,149,100,106,155,173,92,82,163,78,191,177,64,49,192,206,63,210,35,45,220,234,27,21,228,9,248,246,7,154,107,101,148,121,136,134,119,65,176,190,79,162,83,93,172,122,139,133,116,153,104,102,151,161,80,94,175,66,179,189,76,209,32,46,223,50,195,205,60,10,251,245,4,233,24,22,231,167,86,88,169,68,181,187,74,124,141,131,114,159,110,96,145,12,253,243,2,239,30,16,225,215,38,40,217,52,197,203,58,236,29,19,226,15,254,240,1,55,198,200,57,212,37,43,218,71,182,184,73,164,85,91,170,156,109,99,146,127,142,128,113,0,242,249,11,239,29,22,228,195,49,58,200,44,222,213,39,155,105,98,144,116,134,141,127,88,170,161,83,183,69,78,188,43,217,210,32,196,54,61,207,232,26,17,227,7,245,254,12,176,66,73,187,95,173,166,84,115,129,138,120,156,110,101,151,86,164,175,93,185,75,64,178,149,103,108,158,122,136,131,113,205,63,52,198,34,208,219,41,14,252,247,5,225,19,24,234,125,143,132,118,146,96,107,153,190,76,71,181,81,163,168,90,230,20,31,237,9,251,240,2,37,215,220,46,202,56,51,193,172,94,85,167,67,177,186,72,111,157,150,100,128,114,121,139,55,197,206,60,216,42,33,211,244,6,13,255,27,233,226,16,135,117,126,140,104,154,145,99,68,182,189,79,171,89,82,160,28,238,229,23,243,1,10,248,223,45,38,212,48,194,201,59,250,8,3,241,21,231,236,30,57,203,192,50,214,36,47,221,97,147,152,106,142,124,119,133,162,80,91,169,77,191,180,70,209,35,40,218,62,204,199,53,18,224,235,25,253,15,4,246,74,184,179,65,165,87,92,174,137,123,112,130,102,148,159,109,0,243,251,8,235,24,16,227,203,56,48,195,32,211,219,40,139,120,112,131,96,147,155,104,64,179,187,72,171,88,80,163,11,248,240,3,224,19,27,232,192,51,59,200,43,216,208,35,128,115,123,136,107,152,144,99,75,184,176,67,160,83,91,168,22,229,237,30,253,14,6,245,221,46,38,213,54,197,205,62,157,110,102,149,118,133,141,126,86,165,173,94,189,78,70,181,29,238,230,21,246,5,13,254,214,37,45,222,61,206,198,53,150,101,109,158,125,142,134,117,93,174,166,85,182,69,77,190,44,223,215,36,199,52,60,207,231,20,28,239,12,255,247,4,167,84,92,175,76,191,183,68,108,159,151,100,135,116,124,143,39,212,220,47,204,63,55,196,236,31,23,228,7,244,252,15,172,95,87,164,71,180,188,79,103,148,156,111,140,127,119,132,58,201,193,50,209,34,42,217,241,2,10,249,26,233,225,18,177,66,74,185,90,169,161,82,122,137,129,114,145,98,106,153,49,194,202,57,218,41,33,210,250,9,1,242,17,226,234,25,186,73,65,178,81,162,170,89,113,130,138,121,154,105,97,146,0,244,245,1,247,3,2,246,243,7,6,242,4,240,241,5,251,15,14,250,12,248,249,13,8,252,253,9,255,11,10,254,235,31,30,234,28,232,233,29,24,236,237,25,239,27,26,238,16,228,229,17,231,19,18,230,227,23,22,226,20,224,225,21,203,63,62,202,60,200,201,61,56,204,205,57,207,59,58,206,48,196,197,49,199,51,50,198,195,55,54,194,52,192,193,53,32,212,213,33,215,35,34,214,211,39,38,210,36,208,209,37,219,47,46,218,44,216,217,45,40,220,221,41,223,43,42,222,139,127,126,138,124,136,137,125,120,140,141,121,143,123,122,142,112,132,133,113,135,115,114,134,131,119,118,130,116,128,129,117,96,148,149,97,151,99,98,150,147,103,102,146,100,144,145,101,155,111,110,154,108,152,153,109,104,156,157,105,159,107,106,158,64,180,181,65,183,67,66,182,179,71,70,178,68,176,177,69,187,79,78,186,76,184,185,77,72,188,189,73,191,75,74,190,171,95,94,170,92,168,169,93,88,172,173,89,175,91,90,174,80,164,165,81,167,83,82,166,163,87,86,162,84,160,161,85,0,245,247,2,243,6,4,241,251,14,12,249,8,253,255,10,235,30,28,233,24,237,239,26,16,229,231,18,227,22,20,225,203,62,60,201,56,205,207,58,48,197,199,50,195,54,52,193,32,213,215,34,211,38,36,209,219,46,44,217,40,221,223,42,139,126,124,137,120,141,143,122,112,133,135,114,131,118,116,129,96,149,151,98,147,102,100,145,155,110,108,153,104,157,159,106,64,181,183,66,179,70,68,177,187,78,76,185,72,189,191,74,171,94,92,169,88,173,175,90,80,165,167,82,163,86,84,161,11,254,252,9,248,13,15,250,240,5,7,242,3,246,244,1,224,21,23,226,19,230,228,17,27,238,236,25,232,29,31,234,192,53,55,194,51,198,196,49,59,206,204,57,200,61,63,202,43,222,220,41,216,45,47,218,208,37,39,210,35,214,212,33,128,117,119,130,115,134,132,113,123,142,140,121,136,125,127,138,107,158,156,105,152,109,111,154,144,101,103,146,99,150,148,97,75,190,188,73,184,77,79,186,176,69,71,178,67,182,180,65,160,85,87,162,83,166,164,81,91,174,172,89,168,93,95,170,0,246,241,7,255,9,14,248,227,21,18,228,28,234,237,27,219,45,42,220,36,210,213,35,56,206,201,63,199,49,54,192,171,93,90,172,84,162,165,83,72,190,185,79,183,65,70,176,112,134,129,119,143,121,126,136,147,101,98,148,108,154,157,107,75,189,186,76,180,66,69,179,168,94,89,175,87,161,166,80,144,102,97,151,111,153,158,104,115,133,130,116,140,122,125,139,224,22,17,231,31,233,238,24,3,245,242,4,252,10,13,251,59,205,202,60,196,50,53,195,216,46,41,223,39,209,214,32,150,96,103,145,105,159,152,110,117,131,132,114,138,124,123,141,77,187,188,74,178,68,67,181,174,88,95,169,81,167,160,86,61,203,204,58,194,52,51,197,222,40,47,217,33,215,208,38,230,16,23,225,25,239,232,30,5,243,244,2,250,12,11,253,221,43,44,218,34,212,211,37,62,200,207,57,193,55,48,198,6,240,247,1,249,15,8,254,229,19,20,226,26,236,235,29,118,128,135,113,137,127,120,142,149,99,100,146,106,156,155,109,173,91,92,170,82,164,163,85,78,184,191,73,177,71,64,182,0,247,243,4,251,12,8,255,235,28,24,239,16,231,227,20,203,60,56,207,48,199,195,52,32,215,211,36,219,44,40,223,139,124,120,143,112,135,131,116,96,151,147,100,155,108,104,159,64,183,179,68,187,76,72,191,171,92,88,175,80,167,163,84,11,252,248,15,240,7,3,244,224,23,19,228,27,236,232,31,192,55,51,196,59,204,200,63,43,220,216,47,208,39,35,212,128,119,115,132,123,140,136,127,107,156,152,111,144,103,99,148,75,188,184,79,176,71,67,180,160,87,83,164,91,172,168,95,22,225,229,18,237,26,30,233,253,10,14,249,6,241,245,2,221,42,46,217,38,209,213,34,54,193,197,50,205,58,62,201,157,106,110,153,102,145,149,98,118,129,133,114,141,122,126,137,86,161,165,82,173,90,94,169,189,74,78,185,70,177,181,66,29,234,238,25,230,17,21,226,246,1,5,242,13,250,254,9,214,33,37,210,45,218,222,41,61,202,206,57,198,49,53,194,150,97,101,146,109,154,158,105,125,138,142,121,134,113,117,130,93,170,174,89,166,81,85,162,182,65,69,178,77,186,190,73,0,248,237,21,199,63,42,210,147,107,126,134,84,172,185,65,59,195,214,46,252,4,17,233,168,80,69,189,111,151,130,122,118,142,155,99,177,73,92,164,229,29,8,240,34,218,207,55,77,181,160,88,138,114,103,159,222,38,51,203,25,225,244,12,236,20,1,249,43,211,198,62,127,135,146,106,184,64,85,173,215,47,58,194,16,232,253,5,68,188,169,81,131,123,110,150,154,98,119,143,93,165,176,72,9,241,228,28,206,54,35,219,161,89,76,180,102,158,139,115,50,202,223,39,245,13,24,224,197,61,40,208,2,250,239,23,86,174,187,67,145,105,124,132,254,6,19,235,57,193,212,44,109,149,128,120,170,82,71,191,179,75,94,166,116,140,153,97,32,216,205,53,231,31,10,242,136,112,101,157,79,183,162,90,27,227,246,14,220,36,49,201,41,209,196,60,238,22,3,251,186,66,87,175,125,133,144,104,18,234,255,7,213,45,56,192,129,121,108,148,70,190,171,83,95,167,178,74,152,96,117,141,204,52,33,217,11,243,230,30,100,156,137,113,163,91,78,182,247,15,26,226,48,200,221,37,0,249,239,22,195,58,44,213,155,98,116,141,88,161,183,78,43,210,196,61,232,17,7,254,176,73,95,166,115,138,156,101,86,175,185,64,149,108,122,131,205,52,34,219,14,247,225,24,125,132,146,107,190,71,81,168,230,31,9,240,37,220,202,51,172,85,67,186,111,150,128,121,55,206,216,33,244,13,27,226,135,126,104,145,68,189,171,82,28,229,243,10,223,38,48,201,250,3,21,236,57,192,214,47,97,152,142,119,162,91,77,180,209,40,62,199,18,235,253,4,74,179,165,92,137,112,102,159,69,188,170,83,134,127,105,144,222,39,49,200,29,228,242,11,110,151,129,120,173,84,66,187,245,12,26,227,54,207,217,32,19,234,252,5,208,41,63,198,136,113,103,158,75,178,164,93,56,193,215,46,251,2,20,237,163,90,76,181,96,153,143,118,233,16,6,255,42,211,197,60,114,139,157,100,177,72,94,167,194,59,45,212,1,248,238,23,89,160,182,79,154,99,117,140,191,70,80,169,124,133,147,106,36,221,203,50,231,30,8,241,148,109,123,130,87,174,184,65,15,246,224,25,204,53,35,218,0,250,233,19,207,53,38,220,131,121,106,144,76,182,165,95,27,225,242,8,212,46,61,199,152,98,113,139,87,173,190,68,54,204,223,37,249,3,16,234,181,79,92,166,122,128,147,105,45,215,196,62,226,24,11,241,174,84,71,189,97,155,136,114,108,150,133,127,163,89,74,176,239,21,6,252,32,218,201,51,119,141,158,100,184,66,81,171,244,14,29,231,59,193,210,40,90,160,179,73,149,111,124,134,217,35,48,202,22,236,255,5,65,187,168,82,142,116,103,157,194,56,43,209,13,247,228,30,216,34,49,203,23,237,254,4,91,161,178,72,148,110,125,135,195,57,42,208,12,246,229,31,64,186,169,83,143,117,102,156,238,20,7,253,33,219,200,50,109,151,132,126,162,88,75,177,245,15,28,230,58,192,211,41,118,140,159,101,185,67,80,170,180,78,93,167,123,129,146,104,55,205,222,36,248,2,17,235,175,85,70,188,96,154,137,115,44,214,197,63,227,25,10,240,130,120,107,145,77,183,164,94,1,251,232,18,206,52,39,221,153,99,112,138,86,172,191,69,26,224,243,9,213,47,60,198,0,251,235,16,203,48,32,219,139,112,96,155,64,187,171,80,11,240,224,27,192,59,43,208,128,123,107,144,75,176,160,91,22,237,253,6,221,38,54,205,157,102,118,141,86,173,189,70,29,230,246,13,214,45,61,198,150,109,125,134,93,166,182,77,44,215,199,60,231,28,12,247,167,92,76,183,108,151,135,124,39,220,204,55,236,23,7,252,172,87,71,188,103,156,140,119,58,193,209,42,241,10,26,225,177,74,90,161,122,129,145,106,49,202,218,33,250,1,17,234,186,65,81,170,113,138,154,97,88,163,179,72,147,104,120,131,211,40,56,195,24,227,243,8,83,168,184,67,152,99,115,136,216,35,51,200,19,232,248,3,78,181,165,94,133,126,110,149,197,62,46,213,14,245,229,30,69,190,174,85,142,117,101,158,206,53,37,222,5,254,238,21,116,143,159,100,191,68,84,175,255,4,20,239,52,207,223,36,127,132,148,111,180,79,95,164,244,15,31,228,63,196,212,47,98,153,137,114,169,82,66,185,233,18,2,249,34,217,201,50,105,146,130,121,162,89,73,178,226,25,9,242,41,210,194,57,0,252,229,25,215,43,50,206,179,79,86,170,100,152,129,125,123,135,158,98,172,80,73,181,200,52,45,209,31,227,250,6,246,10,19,239,33,221,196,56,69,185,160,92,146,110,119,139,141,113,104,148,90,166,191,67,62,194,219,39,233,21,12,240,241,13,20,232,38,218,195,63,66,190,167,91,149,105,112,140,138,118,111,147,93,161,184,68,57,197,220,32,238,18,11,247,7,251,226,30,208,44,53,201,180,72,81,173,99,159,134,122,124,128,153,101,171,87,78,178,207,51,42,214,24,228,253,1,255,3,26,230,40,212,205,49,76,176,169,85,155,103,126,130,132,120,97,157,83,175,182,74,55,203,210,46,224,28,5,249,9,245,236,16,222,34,59,199,186,70,95,163,109,145,136,116,114,142,151,107,165,89,64,188,193,61,36,216,22,234,243,15,14,242,235,23,217,37,60,192,189,65,88,164,106,150,143,115,117,137,144,108,162,94,71,187,198,58,35,223,17,237,244,8,248,4,29,225,47,211,202,54,75,183,174,82,156,96,121,133,131,127,102,154,84,168,177,77,48,204,213,41,231,27,2,254,0,253,231,26,211,46,52,201,187,70,92,161,104,149,143,114,107,150,140,113,184,69,95,162,208,45,55,202,3,254,228,25,214,43,49,204,5,248,226,31,109,144,138,119,190,67,89,164,189,64,90,167,110,147,137,116,6,251,225,28,213,40,50,207,177,76,86,171,98,159,133,120,10,247,237,16,217,36,62,195,218,39,61,192,9,244,238,19,97,156,134,123,178,79,85,168,103,154,128,125,180,73,83,174,220,33,59,198,15,242,232,21,12,241,235,22,223,34,56,197,183,74,80,173,100,153,131,126,127,130,152,101,172,81,75,182,196,57,35,222,23,234,240,13,20,233,243,14,199,58,32,221,175,82,72,181,124,129,155,102,169,84,78,179,122,135,157,96,18,239,245,8,193,60,38,219,194,63,37,216,17,236,246,11,121,132,158,99,170,87,77,176,206,51,41,212,29,224,250,7,117,136,146,111,166,91,65,188,165,88,66,191,118,139,145,108,30,227,249,4,205,48,42,215,24,229,255,2,203,54,44,209,163,94,68,185,112,141,151,106,115,142,148,105,160,93,71,186,200,53,47,210,27,230,252,1,0,254,225,31,223,33,62,192,163,93,66,188,124,130,157,99,91,165,186,68,132,122,101,155,248,6,25,231,39,217,198,56,182,72,87,169,105,151,136,118,21,235,244,10,202,52,43,213,237,19,12,242,50,204,211,45,78,176,175,81,145,111,112,142,113,143,144,110,174,80,79,177,210,44,51,205,13,243,236,18,42,212,203,53,245,11,20,234,137,119,104,150,86,168,183,73,199,57,38,216,24,230,249,7,100,154,133,123,187,69,90,164,156,98,125,131,67,189,162,92,63,193,222,32,224,30,1,255,226,28,3,253,61,195,220,34,65,191,160,94,158,96,127,129,185,71,88,166,102,152,135,121,26,228,251,5,197,59,36,218,84,170,181,75,139,117,106,148,247,9,22,232,40,214,201,55,15,241,238,16,208,46,49,207,172,82,77,179,115,141,146,108,147,109,114,140,76,178,173,83,48,206,209,47,239,17,14,240,200,54,41,215,23,233,246,8,107,149,138,116,180,74,85,171,37,219,196,58,250,4,27,229,134,120,103,153,89,167,184,70,126,128,159,97,161,95,64,190,221,35,60,194,2,252,227,29,0,255,227,28,219,36,56,199,171,84,72,183,112,143,147,108,75,180,168,87,144,111,115,140,224,31,3,252,59,196,216,39,150,105,117,138,77,178,174,81,61,194,222,33,230,25,5,250,221,34,62,193,6,249,229,26,118,137,149,106,173,82,78,177,49,206,210,45,234,21,9,246,154,101,121,134,65,190,162,93,122,133,153,102,161,94,66,189,209,46,50,205,10,245,233,22,167,88,68,187,124,131,159,96,12,243,239,16,215,40,52,203,236,19,15,240,55,200,212,43,71,184,164,91,156,99,127,128,98,157,129,126,185,70,90,165,201,54,42,213,18,237,241,14,41,214,202,53,242,13,17,238,130,125,97,158,89,166,186,69,244,11,23,232,47,208,204,51,95,160,188,67,132,123,103,152,191,64,92,163,100,155,135,120,20,235,247,8,207,48,44,211,83,172,176,79,136,119,107,148,248,7,27,228,35,220,192,63,24,231,251,4,195,60,32,223,179,76,80,175,104,151,139,116,197,58,38,217,30,225,253,2,110,145,141,114,181,74,86,169,142,113,109,146,85,170,182,73,37,218,198,57,254,1,29,226}; + + +/* + ** this function is used to create galois_mult_8_table[65536] +*/ + +/*int galois_create_mult_tables(int w) + + int j, x, y, logx; + + if (w >= 14) return -1; + + if (galois_mult_tables[w] != NULL) return 0; + galois_mult_tables[w] = (int *) malloc(sizeof(int) * nw[w] * nw[w]); + if (galois_mult_tables[w] == NULL) return -1; + + galois_div_tables[w] = (int *) malloc(sizeof(int) * nw[w] * nw[w]); + if (galois_div_tables[w] == NULL) { + free(galois_mult_tables[w]); + galois_mult_tables[w] = NULL; + return -1; + } + if (galois_log_tables[w] == NULL) { + if (galois_create_log_tables(w) < 0) { + free(galois_mult_tables[w]); + free(galois_div_tables[w]); + galois_mult_tables[w] = NULL; + galois_div_tables[w] = NULL; + return -1; + } + } + + j = 0; + galois_mult_tables[w][j] = 0; + galois_div_tables[w][j] = -1; + j++; + for (y = 1; y < nw[w]; y++) { + galois_mult_tables[w][j] = 0; + galois_div_tables[w][j] = 0; + j++; + } + + for (x = 1; x < nw[w]; x++) { + galois_mult_tables[w][j] = 0; + galois_div_tables[w][j] = -1; + j++; + logx = galois_log_tables[w][x]; + for (y = 1; y < nw[w]; y++) { + galois_mult_tables[w][j] = galois_ilog_tables[w][logx+galois_log_tables[w][y]]; + galois_div_tables[w][j] = galois_ilog_tables[w][logx-galois_log_tables[w][y]]; + j++; + } + } + FILE * fp; + fp = fopen("/home/lixiang/zt_hash/table_result.txt","a"); + int i = 0; + fprintf(fp, "mult_tables:\n"); + for(i = 0; i < nw[w]*nw[w]; i++) + { + fprintf(fp, "%d,", galois_mult_tables[w][i]); + } + fprintf(fp, "\ndiv_tables:\n"); + for(i = 0; i < nw[w]*nw[w]; i++) + { + fprintf(fp, "%d,", galois_div_tables[w][i]); + } + + fprintf(fp, "\nlog_tables:\n"); + for(i = 0; i < nw[w]; i++) + { + fprintf(fp, "%d,", galois_log_tables[w][i]); + } + + fprintf(fp, "\nilog_tables:\n"); + for(i = 0; i < nw[w]*3; i++) + { + fprintf(fp, "%d,", galois_ilog_tables[w][i]); + } + fclose(fp); + return 0; +} +*/ + +#define galois_multtable_8_multiply(x,y) galois_mult_8_table[((x)<<8)|(y)] +/* +inline unsigned char galois_multtable_8_multiply(unsigned char x, unsigned char y) +{ + int index = (x<<8) | y; + return galois_mult_8_table[index]; +} +*/ + +/*int galois_destroy_mult_tables(int w) +{ + return 0; +}*/ + +static inline void zt_hash_arymul(struct zt_state_t * a, struct zt_state_t* b) +{ + struct zt_state_t tmp; + tmp.val=a->val; + a->matrix[0] = galois_multtable_8_multiply(tmp.matrix[0],b->matrix[0])^galois_multtable_8_multiply(tmp.matrix[1],b->matrix[2]); + a->matrix[1] = galois_multtable_8_multiply(tmp.matrix[0],b->matrix[1])^galois_multtable_8_multiply(tmp.matrix[1],b->matrix[3]); + a->matrix[2] = galois_multtable_8_multiply(tmp.matrix[2],b->matrix[0])^galois_multtable_8_multiply(tmp.matrix[3],b->matrix[2]); + a->matrix[3] = galois_multtable_8_multiply(tmp.matrix[2],b->matrix[1])^galois_multtable_8_multiply(tmp.matrix[3],b->matrix[3]); +} + +/* + ** this function is used to create the table[4][256] +*/ +/*void convert(int number, unsigned char * ret) +{ + int i,a[8]; + unsigned char tmp[4]; + for(i = 0; i < 8; i++) + { + a[i] = number%2; + number = number/2; + } + if(a[7] == 0) + { + ret[0] = 2; + ret[1] = 1; + ret[2] = 1; + ret[3] = 0; + } + else + { + ret[0] = 2; + ret[1] = 3; + ret[2] = 1; + ret[3] = 1; + } + for(i = 6; i >= 0; i--) + { + if(a[i] == 0) + { + tmp[0] = 2; + tmp[1] = 1; + tmp[2] = 1; + tmp[3] = 0; + + } + else + { + tmp[0] = 2; + tmp[1] = 3; + tmp[2] = 1; + tmp[3] = 1; + } + zt_hash_arymul(ret, tmp); + } +}*/ + + +/* + ** this function is used to create table[4][256] + */ +/*void zt_hash_create_table() +{ + unsigned char ret[4]={0}; + int i = 0; + FILE * fp; + fp = fopen("/home/lixiang/zt_hash/table.txt","a"); + //galois_create_mult_tables(8); //it should not be a comment + for(i = 0; i < 256; i++) + { + convert(i, ret); + table[i].matrix[0] = ret[0]; + table[i].matrix[1] = ret[1]; + table[i].matrix[2] = ret[2]; + table[i].matrix[3] = ret[3]; + fprintf(fp, "{%d,%d,%d,%d},", table[i].matrix[0], + table[i].matrix[1], + table[i].matrix[2], + table[i].matrix[3]); + } +} + +void zt_hash_destroy_table() +{ + int i = 0; + for(i = 0; i < 33; i++) + { + galois_destroy_mult_tables(i); + } +}*/ + + +inline void zt_hash(struct zt_state_t* array, unsigned char c) +{ + zt_hash_arymul(array, (struct zt_state_t *)(table[c])); +} + +unsigned char ZT_INIT_VAL[4]={1,0,0,1}; +void zt_hash_initial(struct zt_state_t* zt_val) +{ + zt_val->matrix[0] = 1; + zt_val->matrix[1] = 0; + zt_val->matrix[2] = 0; + zt_val->matrix[3] = 1; +} + +int zt_hash_code(struct zt_state_t* zt_val) +{ + int ret; + int tmp[4]; + tmp[0] = zt_val->matrix[0]; + tmp[1] = zt_val->matrix[1]<<8; + tmp[2] = zt_val->matrix[2]<<16; + tmp[3] = zt_val->matrix[3]<<24; + ret = tmp[0]^tmp[1]^tmp[2]^tmp[3]; + return ret; +} + + diff --git a/test/Makefile b/test/Makefile index 44d1c16..2cbe2e7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,6 @@ LIBS=../lib/libmaatframe.so INC=-I../inc/ -I/usr/include/MESA/ all: g++ -o maat_test -g -Wall maat_test.cpp $(INC) $(LIBS) - g++ -o digest_gen -g digest_gen.c -I../src/inc_internal/ ../lib/libmaatframe.so + g++ -o digest_gen -g digest_gen.c -I../src/entry/ ../lib/libmaatframe.so clean: rm maat_test test.log* -f diff --git a/test/digest_gen.c b/test/digest_gen.c index bd32201..a867e65 100644 --- a/test/digest_gen.c +++ b/test/digest_gen.c @@ -6,7 +6,7 @@ #include #include #include -#include "mesa_fuzzy.h" +#include "../entry/mesa_fuzzy.h" void* entropy_start(void) { diff --git a/test/maat_json.json b/test/maat_json.json index 48fff9f..b133216 100644 --- a/test/maat_json.json +++ b/test/maat_json.json @@ -181,7 +181,7 @@ "table_type": "digest", "table_content": { "raw_len": 1160164, - "digest": "FsOmaK3utZafWYt/i[7203:46299992]", + "digest": "12288:UChtbFS6pypdTy4m2[0:1160163]", "cfds_level": 3 } } From bfdefa7414bebc562960bf281ce60286be394a3d Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 6 Apr 2016 10:45:38 +0800 Subject: [PATCH 20/31] =?UTF-8?q?=E5=B0=86mesa=5Ffuzzy.h=E6=94=BE=E5=85=A5?= =?UTF-8?q?inc=E7=9B=AE=E5=BD=95=EF=BC=8C=E4=BE=BF=E4=BA=8E=E5=A4=96?= =?UTF-8?q?=E9=83=A8=E8=B0=83=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {src/entry => inc}/mesa_fuzzy.h | 0 test/Makefile | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {src/entry => inc}/mesa_fuzzy.h (100%) diff --git a/src/entry/mesa_fuzzy.h b/inc/mesa_fuzzy.h similarity index 100% rename from src/entry/mesa_fuzzy.h rename to inc/mesa_fuzzy.h diff --git a/test/Makefile b/test/Makefile index 2cbe2e7..089366a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,6 @@ LIBS=../lib/libmaatframe.so INC=-I../inc/ -I/usr/include/MESA/ all: g++ -o maat_test -g -Wall maat_test.cpp $(INC) $(LIBS) - g++ -o digest_gen -g digest_gen.c -I../src/entry/ ../lib/libmaatframe.so + g++ -o digest_gen -g digest_gen.c $(INC) $(LIBS) clean: rm maat_test test.log* -f From 89d1b2e74faa9af09b0bcfa38a511b8897fd581f Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 22 Apr 2016 18:53:33 +0800 Subject: [PATCH 21/31] =?UTF-8?q?=E6=9B=B4=E6=96=B0digest=5Fgen=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E7=9A=84=E5=BC=95=E7=94=A8=E5=A4=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/digest_gen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/digest_gen.c b/test/digest_gen.c index a867e65..bd32201 100644 --- a/test/digest_gen.c +++ b/test/digest_gen.c @@ -6,7 +6,7 @@ #include #include #include -#include "../entry/mesa_fuzzy.h" +#include "mesa_fuzzy.h" void* entropy_start(void) { From aa7a3caa517ea2cdabe446b613a60db0aca1dd91 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Mon, 25 Apr 2016 11:59:54 +0800 Subject: [PATCH 22/31] =?UTF-8?q?=E5=9C=A8=E5=88=A4=E6=96=AD=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E8=BF=94=E5=9B=9E=E5=91=BD=E4=B8=AD=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=AF=B9rulescan=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E7=B1=BB=E5=9E=8B=E5=88=A4=E6=96=AD=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 4 ++-- src/entry/Maat_rule.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 883f360..26d692e 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -794,7 +794,7 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); - if(hit_detail!=NULL||_feather->rule_scan_type==0) + if(hit_detail!=NULL&&_feather->rule_scan_type!=0) { *detail_ret=fill_region_hit_detail(data,_mid->inner, region_result,hit_region_cnt, @@ -1193,7 +1193,7 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, result,compile_result,rule_num); - if(hit_detail!=NULL||sp->feather->rule_scan_type==0) + if(hit_detail!=NULL&&sp->feather->rule_scan_type!=0) { if(sp->scan_buff!=NULL) { diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 30ba55a..401a245 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_7_20160406=1; +int MAAT_FRAME_VERSION_1_7_20160425=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", From 8e1a2edd94cd563fe1ae5798aad14588a1494484 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Tue, 3 May 2016 15:32:49 +0800 Subject: [PATCH 23/31] =?UTF-8?q?=E4=BF=AE=E6=AD=A3test=E4=B8=AD=E4=B8=80?= =?UTF-8?q?=E5=A4=84=E7=AC=94=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/maat_test.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/test/maat_test.cpp b/test/maat_test.cpp index 800320f..7f66b2c 100644 --- a/test/maat_test.cpp +++ b/test/maat_test.cpp @@ -429,15 +429,9 @@ int main(int argc,char* argv[]) scan_status_t mid=NULL; void *logger=MESA_create_runtime_log_handle(log_file,0); -/* feather=Maat_summon_feather_json(g_iThreadNum, - table_info_path, - json_path, - logger); -*/ -// feather=Maat_summon_feather(g_iThreadNum,table_info_path,ful_cfg_dir,inc_cfg_dir,logger); feather=Maat_feather(g_iThreadNum, table_info_path, logger); - Maat_set_feather_opt(feather, MAAT_OPT_JSON_FILE_PATH, json_path, sizeof(json_path)+1); - Maat_set_feather_opt(feather, MAAT_OPT_STAT_FILE_PATH, stat_file, strlen(stat_file)); + Maat_set_feather_opt(feather, MAAT_OPT_JSON_FILE_PATH, json_path, strlen(json_path)+1); + Maat_set_feather_opt(feather, MAAT_OPT_STAT_FILE_PATH, stat_file, strlen(stat_file)+1); Maat_set_feather_opt(feather, MAAT_OPT_STAT_ON, NULL, 0); Maat_set_feather_opt(feather, MAAT_OPT_PERF_ON, NULL, 0); Maat_set_feather_opt(feather, MAAT_OPT_SCAN_DETAIL, &scan_detail, sizeof(scan_detail)); From dbc7fcc3ffca394ff06beb6fd5728f433314db92 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Mon, 9 May 2016 22:02:27 +0800 Subject: [PATCH 24/31] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=80=A7=E8=83=BD?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E6=97=B6stream=5Fnum=E7=AD=89=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E8=B4=9F=E5=80=BC=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E6=96=B9=E6=B3=95=E6=98=AF=E4=BD=BF=E7=94=A8aligment?= =?UTF-8?q?=5Fint64=5Farray=E6=9B=BF=E4=BB=A3=E7=BA=BF=E7=A8=8B=E4=B8=8D?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E7=9A=84long=20long=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 83 ++++++++++++++++++---------------- src/entry/Maat_rule.cpp | 39 +++++++++++++--- src/entry/Maat_rule_internal.h | 29 ++++++------ src/entry/Maat_stat.cpp | 79 ++++++++++++++++++-------------- src/entry/aligment_int64.h | 15 ++++-- 5 files changed, 149 insertions(+), 96 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 26d692e..9ef5b47 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -98,7 +98,7 @@ int pickup_hit_region_from_compile(universal_bool_expr_t *compile_hit,const unsi } return k; } -int region_compile(_Maat_feather_t*feather,struct _INNER_scan_status_t *_mid,void* region_hit,int region_type_size,int group_offset,int region_hit_num,struct Maat_rule_t* result,_compile_result_t *rs_result, int size) +int region_compile(_Maat_feather_t*feather,struct _INNER_scan_status_t *_mid,void* region_hit,int region_type_size,int group_offset,int region_hit_num,struct Maat_rule_t* result,_compile_result_t *rs_result, int size,int thread_num) { int scan_ret=0,result_cnt=0; @@ -138,7 +138,7 @@ int region_compile(_Maat_feather_t*feather,struct _INNER_scan_status_t *_mid,voi } else { - scan_ret=boolexpr_match(bool_matcher,_mid->thread_num, + scan_ret=boolexpr_match(bool_matcher,thread_num, _mid->hitted_group_id,_mid->hit_group_cnt, (void **)array_mi_rule, MAX_SCANNER_HIT_NUM); } @@ -169,7 +169,7 @@ int region_compile(_Maat_feather_t*feather,struct _INNER_scan_status_t *_mid,voi } if(result_cnt>0) { - feather->hit_cnt++; + aligment_int64_array_add(feather->hit_cnt,thread_num,1); } return result_cnt; } @@ -344,24 +344,24 @@ int fill_region_hit_detail(const char* scan_buff,const _INNER_scan_status_t* _mi } return j; } -struct _INNER_scan_status_t* _make_inner_status(int thread_num) +struct _INNER_scan_status_t* _make_inner_status(void) { struct _INNER_scan_status_t* inner_mid=NULL; inner_mid=(struct _INNER_scan_status_t*)calloc(sizeof(struct _INNER_scan_status_t),1); - inner_mid->thread_num=thread_num; inner_mid->cur_hit_cnt=0; inner_mid->hit_group_cnt=0; inner_mid->hit_group_size=4; inner_mid->hitted_group_id=(unsigned int*)malloc(sizeof(unsigned int)*inner_mid->hit_group_size); return inner_mid; } -struct _OUTER_scan_status_t* _make_outer_status(_Maat_feather_t *feather) +struct _OUTER_scan_status_t* _make_outer_status(_Maat_feather_t *feather,int thread_num) { struct _OUTER_scan_status_t* outer_mid=NULL; outer_mid=(struct _OUTER_scan_status_t*)calloc(sizeof(struct _OUTER_scan_status_t),1); outer_mid->feather=feather; outer_mid->district_id=-1; - feather->outer_mid_cnt++; + outer_mid->thread_num=(unsigned short)thread_num; + aligment_int64_array_add(feather->outer_mid_cnt, thread_num,1); return outer_mid; } struct _OUTER_scan_status_t* grab_mid(scan_status_t* raw_mid,_Maat_feather_t* feather,int thread_num,int is_hit_region) @@ -375,13 +375,13 @@ struct _OUTER_scan_status_t* grab_mid(scan_status_t* raw_mid,_Maat_feather_t* fe { if(_mid==NULL) { - _mid=_make_outer_status(feather); + _mid=_make_outer_status(feather,thread_num); *raw_mid=_mid; } if(_mid->inner==NULL) { - _mid->inner=_make_inner_status(thread_num); - feather->inner_mid_cnt++; + _mid->inner=_make_inner_status(); + aligment_int64_array_add(feather->inner_mid_cnt,thread_num,1); } } return _mid; @@ -415,7 +415,7 @@ int detain_last_data(char* buff,int buff_size,int detained_len,const char* data, Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger) { _Maat_feather_t* feather=(_Maat_feather_t*)calloc(sizeof(struct _Maat_feather_t),1); - feather->table_cnt=read_table_info(feather->p_table_info, MAX_TABLE_NUM,table_info_path,logger); + feather->table_cnt=read_table_info(feather->p_table_info, MAX_TABLE_NUM,table_info_path,max_thread_num,logger); feather->map_tablename2id=map_create(); int i=0; for(i=0;iscan_interval_ms=1*1000; feather->rule_scan_type=2; feather->thread_call_cnt=aligment_int64_array_alloc(max_thread_num); + feather->outer_mid_cnt=aligment_int64_array_alloc(max_thread_num); + feather->inner_mid_cnt=aligment_int64_array_alloc(max_thread_num); + feather->hit_cnt=aligment_int64_array_alloc(max_thread_num); return feather; } int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size) @@ -788,12 +791,13 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id } if(hit_region_cnt>0) { - p_table->hit_cnt++; + aligment_int64_array_add(p_table->hit_cnt, thread_num,1); _mid=grab_mid(mid,_feather,thread_num, 1); compile_ret=region_compile(_feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, - result,compile_result,rule_num); + result,compile_result,rule_num, + thread_num); if(hit_detail!=NULL&&_feather->rule_scan_type!=0) { *detail_ret=fill_region_hit_detail(data,_mid->inner, @@ -806,11 +810,11 @@ int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id if(_feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&end); - maat_stat_table(p_table,data_len,&start, &end); + maat_stat_table(p_table,data_len,&start, &end,thread_num); } else { - maat_stat_table(p_table,data_len,NULL, NULL); + maat_stat_table(p_table,data_len,NULL, NULL,thread_num); } if(compile_ret==0&&hit_region_cnt>0) @@ -879,23 +883,24 @@ int Maat_scan_intval(Maat_feather_t feather,int table_id } else if(region_ret>0) { - p_table->hit_cnt++; + aligment_int64_array_add(p_table->hit_cnt, thread_num,1); _mid=grab_mid(mid, _feather, thread_num, 1); compile_ret=region_compile(_feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), region_ret, - result,compile_result,rule_num); + result,compile_result,rule_num, + thread_num); } DEC_SCANNER_REF(my_scanner,thread_num); if(_feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&end); - maat_stat_table(p_table,0,&start, &end); + maat_stat_table(p_table,0,&start, &end,thread_num); } else { - maat_stat_table(p_table,0,NULL, NULL); + maat_stat_table(p_table,0,NULL, NULL,thread_num); } if(compile_ret==0&®ion_ret>0) { @@ -985,22 +990,23 @@ int Maat_scan_proto_addr(Maat_feather_t feather,int table_id } else if(region_ret>0) { - p_table->hit_cnt++; + aligment_int64_array_add(p_table->hit_cnt, thread_num,1); _mid=grab_mid(mid, _feather, thread_num, 1); compile_ret=region_compile(_feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), region_ret, - result,compile_result,rule_num); + result,compile_result,rule_num, + thread_num); } DEC_SCANNER_REF(my_scanner,thread_num); if(_feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&end); - maat_stat_table(p_table,0,&start, &end); + maat_stat_table(p_table,0,&start, &end,thread_num); } else { - maat_stat_table(p_table,0,NULL, NULL); + maat_stat_table(p_table,0,NULL, NULL,thread_num); } if(compile_ret==0&®ion_ret>0) { @@ -1062,7 +1068,7 @@ stream_para_t Maat_stream_scan_string_start(Maat_feather_t feather,int table_id, { sp->do_regex=1; } - p_table->stream_num++; + aligment_int64_array_add(p_table->stream_num,thread_num,1); sp->rs_stream_para=rulescan_startstream(_feather->scanner->region,thread_num); return sp; } @@ -1187,12 +1193,13 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para } if(hit_region_cnt>0) { - p_table->hit_cnt++; + aligment_int64_array_add(p_table->hit_cnt, sp->thread_num,1); _mid=grab_mid(mid, sp->feather,sp->thread_num, 1); compile_ret=region_compile(sp->feather,_mid->inner, region_result,sizeof(scan_result_t),offsetof(scan_result_t, tag), hit_region_cnt, - result,compile_result,rule_num); + result,compile_result,rule_num, + sp->thread_num); if(hit_detail!=NULL&&sp->feather->rule_scan_type!=0) { if(sp->scan_buff!=NULL) @@ -1219,11 +1226,11 @@ int Maat_stream_scan_string_detail(stream_para_t* stream_para if(sp->feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&end); - maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end); + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end,sp->thread_num); } else { - maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,NULL, NULL); + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,NULL, NULL,sp->thread_num); } if(compile_ret==0&&hit_region_cnt>0) { @@ -1249,7 +1256,7 @@ void Maat_stream_scan_string_end(stream_para_t* stream_para) struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; struct _Maat_table_info_t * p_table=sp->feather->p_table_info[sp->table_id]; - p_table->stream_num--; + aligment_int64_array_add(p_table->stream_num,sp->thread_num,-1); if(scanner!=NULL) { if(sp->version==sp->feather->maat_version) @@ -1307,8 +1314,7 @@ stream_para_t Maat_stream_scan_digest_start(Maat_feather_t feather,int table_id, sp->total_len=total_len; sp->fuzzy_hash_handle=tmp_fuzzy_handle; pthread_mutex_init(&(sp->fuzzy_mutex),NULL); - p_table->stream_num++; - + aligment_int64_array_add(p_table->stream_num,thread_num,1); return sp; } @@ -1395,17 +1401,18 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int compile_ret=region_compile(sp->feather,_mid->inner, query_result,sizeof(GIE_result_t),offsetof(GIE_result_t, tag), hit_region_cnt, - result,compile_result,rule_num); + result,compile_result,rule_num, + sp->thread_num); } if(sp->feather->perf_on==1) { clock_gettime(CLOCK_MONOTONIC,&end); - maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end); + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,&start, &end,sp->thread_num); } else { - maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,NULL, NULL); + maat_stat_table(sp->feather->p_table_info[sp->table_id],data_len,NULL, NULL,sp->thread_num); } if(compile_ret==0&&hit_region_cnt>0) { @@ -1418,7 +1425,7 @@ void Maat_stream_scan_digest_end(stream_para_t* stream_para) struct _stream_para_t* sp=(struct _stream_para_t*)(*stream_para); struct _Maat_scanner_t* scanner=sp->feather->scanner; struct _Maat_table_info_t * p_table=sp->feather->p_table_info[sp->table_id]; - p_table->stream_num--; + aligment_int64_array_add(p_table->stream_num,sp->thread_num,-1); if(scanner!=NULL) { if(sp->version==sp->feather->maat_version) @@ -1443,7 +1450,7 @@ int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCA _mid=grab_mid(mid,_feather, 0, 0); if(_mid==NULL) { - _mid=_make_outer_status(_feather); + _mid=_make_outer_status(_feather,0); *mid=_mid; } switch(type) @@ -1470,12 +1477,12 @@ void Maat_clean_status(scan_status_t* mid) return; } _mid=(struct _OUTER_scan_status_t*)(*mid); - _mid->feather->outer_mid_cnt--; + aligment_int64_array_add(_mid->feather->outer_mid_cnt,_mid->thread_num,-1); if(_mid->inner!=NULL) { free(_mid->inner->hitted_group_id); free(_mid->inner); - _mid->feather->inner_mid_cnt--; + aligment_int64_array_add(_mid->feather->inner_mid_cnt,_mid->thread_num,-1); } _mid->feather=NULL; free(_mid); diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 401a245..503be8f 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_7_20160425=1; +int MAAT_FRAME_VERSION_1_7_20160509=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", @@ -377,7 +377,29 @@ int HASH_delete_by_id(MESA_htable_handle hash,int id) ret=MESA_htable_del(hash,(unsigned char*)&id, sizeof(id), NULL); return ret; } -int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* table_info_path,void* logger) +_Maat_table_info_t* create_table_info(int max_thread_num) +{ + struct _Maat_table_info_t*p=NULL; + p=(struct _Maat_table_info_t*)calloc(sizeof(struct _Maat_table_info_t),1); + p->scan_cnt=aligment_int64_array_alloc(max_thread_num); + p->scan_cpu_time=aligment_int64_array_alloc(max_thread_num); + p->input_bytes=aligment_int64_array_alloc(max_thread_num); + p->stream_num=aligment_int64_array_alloc(max_thread_num); + p->hit_cnt=aligment_int64_array_alloc(max_thread_num); + p->cross_cache_size=0; + return p; +} +void destroy_table_info(struct _Maat_table_info_t*p) +{ + aligment_int64_array_free(p->scan_cnt); + aligment_int64_array_free(p->scan_cpu_time); + aligment_int64_array_free(p->input_bytes); + aligment_int64_array_free(p->stream_num); + aligment_int64_array_free(p->hit_cnt); + free(p); + return; +} +int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* table_info_path,int max_thread_num,void* logger) { FILE*fp=NULL; char line[MAX_TABLE_LINE_SIZE]; @@ -434,8 +456,8 @@ int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* { continue; } - p=(struct _Maat_table_info_t*)calloc(sizeof(struct _Maat_table_info_t),1); - p->cross_cache_size=0; + p=create_table_info(max_thread_num); + sscanf(line,"%hu\t%s\t%s\t%s\t%s\t%s\t%d",&(p->table_id) ,p->table_name ,table_type @@ -506,7 +528,7 @@ int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* table_cnt++; continue; error_jump: - free(p); + destroy_table_info(p); p=NULL; } fclose(fp); @@ -2613,10 +2635,13 @@ void *thread_rule_monitor(void *arg) free(lines); } } - free(feather->p_table_info[i]); + destroy_table_info(feather->p_table_info[i]); feather->p_table_info[i]=NULL; } - free(feather->thread_call_cnt); + aligment_int64_array_free(feather->thread_call_cnt); + aligment_int64_array_free(feather->inner_mid_cnt); + aligment_int64_array_free(feather->outer_mid_cnt); + aligment_int64_array_free(feather->hit_cnt); free(feather); return NULL; } diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index f7f9ef0..02ce775 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -12,7 +12,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" - +#include "aligment_int64.h" #include #include @@ -31,7 +31,6 @@ typedef int atomic_t; #else #include #endif -#define CPU_CACHE_ALIGMENT 64 #define TRUE 1 #define FALSE 0 @@ -241,16 +240,15 @@ struct _Maat_table_info_t struct _plugin_table_info *cb_info; //for stat>>>>>>>> int stat_line_id; - long long scan_cnt; - long long scan_cpu_time; //nano - long long input_bytes; - long long stream_num; - long long hit_cnt; + mcore_long_t scan_cnt; + mcore_long_t scan_cpu_time; //nano + mcore_long_t input_bytes; + mcore_long_t stream_num; + mcore_long_t hit_cnt; }; struct _INNER_scan_status_t { - int thread_num; int cur_hit_cnt; int hit_group_cnt; int hit_group_size; @@ -260,7 +258,8 @@ struct _INNER_scan_status_t struct _OUTER_scan_status_t { struct _Maat_feather_t* feather; - int is_set_district; + unsigned short thread_num; + unsigned short is_set_district; int district_id; struct _INNER_scan_status_t* inner; }; @@ -345,10 +344,10 @@ struct _Maat_feather_t int total_stat_id; int fs_status_id[MAX_MAAT_STAT_NUM]; int fs_column_id[MAX_MAAT_STAT_NUM]; - long long outer_mid_cnt; - long long inner_mid_cnt; - long long hit_cnt; - long long *thread_call_cnt;//size indicate by scan_thread_num, + mcore_long_t outer_mid_cnt; + mcore_long_t inner_mid_cnt; + mcore_long_t hit_cnt; + mcore_long_t thread_call_cnt;//size indicate by scan_thread_num, }; struct _maat_garbage_t { @@ -367,7 +366,7 @@ struct _maat_garbage_t void garbage_bagging(enum maat_garbage_type type,void *p,MESA_lqueue_head garbage_q); void garbage_bury(MESA_lqueue_head garbage_q,void *logger); void make_group_set(const struct _Maat_compile_rule_t* compile_rule,universal_bool_expr_t* a_set); -int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* table_info_path,void*logger); +int read_table_info(struct _Maat_table_info_t** p_table_info,int num,const char* table_info_path,int max_thread_num,void* logger); void maat_start_cb(unsigned int new_version,int update_type,void*u_para); void maat_update_cb(const char* table_name,const char* line,void *u_para); void maat_finish_cb(void* u_para); @@ -383,7 +382,7 @@ inline void ipv6_ntoh(unsigned int *v6_addr) return; } void maat_stat_init(struct _Maat_feather_t* feather); -void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timespec* start, struct timespec* end); +void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timespec* start, struct timespec* end,int thread_num); void maat_stat_output(struct _Maat_feather_t* feather); diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index 8908363..c6910b2 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -94,37 +94,46 @@ void maat_stat_init(struct _Maat_feather_t* feather) FS_start(feather->stat_handle); return; } -void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timespec* start, struct timespec* end) +void maat_stat_table(struct _Maat_table_info_t* p_table,int scan_len,struct timespec* start, struct timespec* end,int thread_num) { - p_table->scan_cnt++; - p_table->input_bytes+=scan_len; + aligment_int64_array_add(p_table->scan_cnt,thread_num,1); + aligment_int64_array_add(p_table->input_bytes,thread_num,scan_len); if(start!=NULL&&end!=NULL) { - p_table->scan_cpu_time+=(end->tv_sec-start->tv_sec)*1000000000+end->tv_nsec-start->tv_nsec; + aligment_int64_array_add(p_table->scan_cpu_time,thread_num,(end->tv_sec-start->tv_sec)*1000000000+end->tv_nsec-start->tv_nsec); } return; } void maat_stat_output(struct _Maat_feather_t* feather) { long value=0; - long long total_cfg_num=0, total_input_bytes=0, total_regex_num=0; + long long total_cfg_num=0, total_input_bytes=0, total_regex_num=0,total_hit_cnt=0; long long total_scan_cnt=0, total_cpu_time=0,total_stream_cnt=0,active_thread_num=0; + long long table_stream_num=0,table_scan_cnt=0,table_input_bytes=0,table_scan_cpu_time=0,table_hit_cnt=0; + long long outer_mid_cnt=0,inner_mid_cnt=0; int i=0; time_t now; struct _Maat_table_info_t* p_table=NULL; time(&now); active_thread_num=aligment_int64_array_cnt(feather->thread_call_cnt, feather->scan_thread_num); + outer_mid_cnt=aligment_int64_array_cnt(feather->outer_mid_cnt,feather->scan_thread_num); + inner_mid_cnt=aligment_int64_array_cnt(feather->inner_mid_cnt,feather->scan_thread_num); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_VERSION], 0,FS_OP_SET,feather->maat_version); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_THRED_NUM], 0,FS_OP_SET,active_thread_num); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TABLE_NUM], 0,FS_OP_SET,feather->table_cnt); - FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_OUTER_MID_NUM], 0,FS_OP_SET,feather->outer_mid_cnt); - FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_INNER_MID_NUM], 0,FS_OP_SET,feather->inner_mid_cnt); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_OUTER_MID_NUM], 0,FS_OP_SET,outer_mid_cnt); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_INNER_MID_NUM], 0,FS_OP_SET,inner_mid_cnt); value=MESA_lqueue_get_count(feather->garbage_q); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_GARBAGE_QSIZE], 0,FS_OP_SET,value); for(i=0;ip_table_info[i]; if(p_table==NULL||p_table->table_type==TABLE_TYPE_PLUGIN ||p_table->table_type==TABLE_TYPE_GROUP @@ -146,45 +155,49 @@ void maat_stat_output(struct _Maat_feather_t* feather) p_table->regex_rule_cnt); total_regex_num+= p_table->regex_rule_cnt; + table_stream_num=aligment_int64_array_sum(p_table->stream_num,feather->scan_thread_num); FS_operate(feather->stat_handle, p_table->stat_line_id, feather->fs_column_id[COLUMN_TABLE_STREAM_NUM], FS_OP_SET, - p_table->stream_num); - total_stream_cnt+= p_table->stream_num; - + table_stream_num); + total_stream_cnt+= table_stream_num; + + table_scan_cnt=aligment_int64_array_sum(p_table->scan_cnt,feather->scan_thread_num); FS_operate(feather->stat_handle, p_table->stat_line_id, feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], - FS_OP_ADD, - p_table->scan_cnt); - total_scan_cnt+=p_table->scan_cnt; - p_table->scan_cnt=0; - + FS_OP_SET, + table_scan_cnt); + total_scan_cnt+=table_scan_cnt; + + table_input_bytes=aligment_int64_array_sum(p_table->input_bytes,feather->scan_thread_num); FS_operate(feather->stat_handle, p_table->stat_line_id, feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES], - FS_OP_ADD, - p_table->input_bytes); - total_input_bytes+=p_table->input_bytes; - p_table->input_bytes=0; + FS_OP_SET, + table_input_bytes); + total_input_bytes+=table_input_bytes; if(feather->perf_on==1) { + table_scan_cpu_time=aligment_int64_array_sum(p_table->scan_cpu_time,feather->scan_thread_num); + table_scan_cpu_time/=1000; FS_operate(feather->stat_handle, p_table->stat_line_id, feather->fs_column_id[COLUMN_TABLE_CPU_TIME], - FS_OP_ADD, - p_table->scan_cpu_time/1000); - total_cpu_time+=p_table->scan_cpu_time; - p_table->scan_cpu_time=0; + FS_OP_SET, + table_scan_cpu_time); + total_cpu_time+=table_scan_cpu_time; } + + table_hit_cnt=aligment_int64_array_sum(p_table->hit_cnt,feather->scan_thread_num); FS_operate(feather->stat_handle, p_table->stat_line_id, feather->fs_column_id[COLUMN_TABLE_HIT_CNT], - FS_OP_ADD, - p_table->hit_cnt); + FS_OP_SET, + table_hit_cnt); //total hit count stat in region_compile - p_table->hit_cnt=0; + } FS_operate(feather->stat_handle, feather->total_stat_id, @@ -204,27 +217,27 @@ void maat_stat_output(struct _Maat_feather_t* feather) FS_operate(feather->stat_handle, feather->total_stat_id, feather->fs_column_id[COLUMN_TABLE_SCAN_CNT], - FS_OP_ADD, + FS_OP_SET, total_scan_cnt); FS_operate(feather->stat_handle, feather->total_stat_id, feather->fs_column_id[COLUMN_TABLE_SCAN_BYTES], - FS_OP_ADD, + FS_OP_SET, total_input_bytes); if(feather->perf_on==1) { FS_operate(feather->stat_handle, feather->total_stat_id, feather->fs_column_id[COLUMN_TABLE_CPU_TIME], - FS_OP_ADD, - total_cpu_time/1000); + FS_OP_SET, + total_cpu_time); } + total_hit_cnt=aligment_int64_array_sum(feather->hit_cnt,feather->scan_thread_num); FS_operate(feather->stat_handle, feather->total_stat_id, feather->fs_column_id[COLUMN_TABLE_HIT_CNT], - FS_OP_ADD, - feather->hit_cnt); - feather->hit_cnt=0; + FS_OP_SET, + total_hit_cnt); FS_passive_output(feather->stat_handle); return; } diff --git a/src/entry/aligment_int64.h b/src/entry/aligment_int64.h index a152593..1ae4200 100644 --- a/src/entry/aligment_int64.h +++ b/src/entry/aligment_int64.h @@ -2,13 +2,17 @@ #define H_ALIGMENT_INT64_H_INCLUDE #include + +#define CPU_CACHE_ALIGMENT 64 +typedef long long* mcore_long_t; + inline long long *aligment_int64_array_alloc(int size) { long long *ret=NULL; ret=(long long*)calloc(CPU_CACHE_ALIGMENT,size); return ret; } -inline long long aligment_int64_array_sum(long long * array,int size) +inline long long aligment_int64_array_sum(mcore_long_t array,int size) { long long sum=0; int offset=0,i=0; @@ -19,13 +23,13 @@ inline long long aligment_int64_array_sum(long long * array,int size) } return sum; } -inline long long aligment_int64_array_add(long long * array,int offset,long long op_val) +inline long long aligment_int64_array_add(mcore_long_t array,int offset,long long op_val) { int idx=(CPU_CACHE_ALIGMENT/sizeof(long long))*offset; array[idx]+=op_val; return array[idx]; } -inline int aligment_int64_array_cnt(long long * array,int size) +inline long long aligment_int64_array_cnt(mcore_long_t array,int size) { int offset=0,i=0; int cnt=0; @@ -39,5 +43,10 @@ inline int aligment_int64_array_cnt(long long * array,int size) } return cnt; } +inline void aligment_int64_array_free(mcore_long_t array) +{ + free(array); +} + #endif From 7120052dca36bbebdedcafff30199aea25075436 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Tue, 10 May 2016 11:41:05 +0800 Subject: [PATCH 25/31] =?UTF-8?q?=E4=BF=AE=E5=A4=8Douter=5Fmid=E5=92=8Cinn?= =?UTF-8?q?er=5Fmid=E7=BB=9F=E8=AE=A1=E7=9A=84=E7=AC=94=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_stat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index c6910b2..4fca54e 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -116,8 +116,8 @@ void maat_stat_output(struct _Maat_feather_t* feather) struct _Maat_table_info_t* p_table=NULL; time(&now); active_thread_num=aligment_int64_array_cnt(feather->thread_call_cnt, feather->scan_thread_num); - outer_mid_cnt=aligment_int64_array_cnt(feather->outer_mid_cnt,feather->scan_thread_num); - inner_mid_cnt=aligment_int64_array_cnt(feather->inner_mid_cnt,feather->scan_thread_num); + outer_mid_cnt=aligment_int64_array_sum(feather->outer_mid_cnt,feather->scan_thread_num); + inner_mid_cnt=aligment_int64_array_sum(feather->inner_mid_cnt,feather->scan_thread_num); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_VERSION], 0,FS_OP_SET,feather->maat_version); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_THRED_NUM], 0,FS_OP_SET,active_thread_num); FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TABLE_NUM], 0,FS_OP_SET,feather->table_cnt); From a1556699c36c4e1048538a6690d4e297be7d7ee1 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 11 May 2016 09:53:00 +0800 Subject: [PATCH 26/31] =?UTF-8?q?=E5=9C=A8feather=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=B4=AF=E7=A7=AF=E6=89=AB=E6=8F=8F=E9=95=BF=E5=BA=A6=E5=92=8C?= =?UTF-8?q?=E6=AC=A1=E6=95=B0=E7=9A=84=E7=BB=9F=E8=AE=A1=EF=BC=8C=E4=BD=86?= =?UTF-8?q?=E6=9C=AA=E5=9C=A8maat=5Fstat=E4=B8=AD=E8=BE=93=E5=87=BA?= =?UTF-8?q?=EF=BC=8C=E5=8F=AA=E8=83=BD=E9=80=9A=E8=BF=87gdb=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E3=80=82=20=E5=9C=A8gdb=E4=B8=AD=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=88=B0bt=E5=90=8E=E5=8C=85=E5=90=ABthread=5Frule=5Fmonitor?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84=E7=BA=BF=E7=A8=8B=EF=BC=8C=E5=9C=A8?= =?UTF-8?q?.84=E4=B8=8A=E6=98=AFthread=204=EF=BC=8Cup=E5=88=B0thread=5Frul?= =?UTF-8?q?e=5Fmonitor=E6=A0=88=EF=BC=8C=E6=89=A7=E8=A1=8C=EF=BC=9A=20(gdb?= =?UTF-8?q?)=20p=20*feather=20$2=20=3D=20{=20=20=20scanner=20=3D=200x70654?= =?UTF-8?q?0,=20=20=20total=5Fscan=5Fbytes=20=3D=201971931012,=20=20=20tot?= =?UTF-8?q?al=5Fscan=5Fcnt=20=3D=2013269797=20}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule_internal.h | 2 ++ src/entry/Maat_stat.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index 02ce775..65d8149 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -348,6 +348,8 @@ struct _Maat_feather_t mcore_long_t inner_mid_cnt; mcore_long_t hit_cnt; mcore_long_t thread_call_cnt;//size indicate by scan_thread_num, + long long total_scan_bytes; + long long total_scan_cnt; }; struct _maat_garbage_t { diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index 4fca54e..1f4090d 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -238,6 +238,8 @@ void maat_stat_output(struct _Maat_feather_t* feather) feather->fs_column_id[COLUMN_TABLE_HIT_CNT], FS_OP_SET, total_hit_cnt); + feather->total_scan_bytes=total_input_bytes; + feather->total_scan_cnt=total_scan_cnt; FS_passive_output(feather->stat_handle); return; } From 6e9c55289a3a2ce4392253abd9798b50bfa9f291 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 11 May 2016 10:23:40 +0800 Subject: [PATCH 27/31] =?UTF-8?q?=E5=9C=A8maat=5Fstat=E4=B8=AD=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=B4=AF=E7=A7=AF=E6=89=AB=E6=8F=8F=E5=AD=97=E8=8A=82?= =?UTF-8?q?=E6=95=B0=E5=92=8C=E6=AC=A1=E6=95=B0=E7=9A=84=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 2 +- src/entry/Maat_stat.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index 503be8f..ac03bec 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_7_20160509=1; +int MAAT_FRAME_VERSION_1_7_20160510=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", diff --git a/src/entry/Maat_stat.cpp b/src/entry/Maat_stat.cpp index 1f4090d..6a32535 100644 --- a/src/entry/Maat_stat.cpp +++ b/src/entry/Maat_stat.cpp @@ -9,6 +9,8 @@ enum MAAT_FS_STATUS{ STATUS_OUTER_MID_NUM, STATUS_INNER_MID_NUM, STATUS_GARBAGE_QSIZE, + STATUS_TOTAL_SCAN_LEN, + STATUS_TOTAL_SCAN_CNT, }; enum MAAT_FS_COLUMN @@ -19,7 +21,7 @@ enum MAAT_FS_COLUMN COLUMN_TABLE_SCAN_CNT, COLUMN_TABLE_SCAN_BYTES, COLUMN_TABLE_CPU_TIME,//microseconds - COLUMN_TABLE_HIT_CNT + COLUMN_TABLE_HIT_CNT, }; void maat_stat_init(struct _Maat_feather_t* feather) { @@ -40,6 +42,9 @@ void maat_stat_init(struct _Maat_feather_t* feather) feather->fs_status_id[STATUS_OUTER_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"outer_mid"); feather->fs_status_id[STATUS_INNER_MID_NUM]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"inner_mid"); feather->fs_status_id[STATUS_GARBAGE_QSIZE]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"garbage_num"); + feather->fs_status_id[STATUS_TOTAL_SCAN_LEN]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"scan_bytes"); + feather->fs_status_id[STATUS_TOTAL_SCAN_CNT]=FS_register(feather->stat_handle, FS_STYLE_STATUS, FS_CALC_CURRENT,"scan_times"); + feather->fs_column_id[COLUMN_TABLE_RULE_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"rule"); feather->fs_column_id[COLUMN_TABLE_REGEX_NUM]=FS_register(feather->stat_handle, FS_STYLE_COLUMN, FS_CALC_CURRENT,"regex"); @@ -240,6 +245,8 @@ void maat_stat_output(struct _Maat_feather_t* feather) total_hit_cnt); feather->total_scan_bytes=total_input_bytes; feather->total_scan_cnt=total_scan_cnt; + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TOTAL_SCAN_LEN], 0,FS_OP_SET,feather->total_scan_bytes); + FS_operate(feather->stat_handle, feather->fs_status_id[STATUS_TOTAL_SCAN_CNT], 0,FS_OP_SET,feather->total_scan_cnt); FS_passive_output(feather->stat_handle); return; } From c5bea905b8252e648a372201622fa1534afa0c1a Mon Sep 17 00:00:00 2001 From: zhengchao Date: Wed, 25 May 2016 11:47:15 +0800 Subject: [PATCH 28/31] =?UTF-8?q?20160525=E7=89=88=E6=9C=AC=EF=BC=8C1?= =?UTF-8?q?=EF=BC=89=E8=BF=90=E8=A1=8C=E5=9B=9E=E8=B0=83=E8=A1=A8=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E7=9A=84start=E5=92=8Cfinish=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=EF=BC=9B2=EF=BC=89=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=97=B6=E5=8F=AA=E6=9C=89=E5=A2=9E?= =?UTF-8?q?=E9=87=8F=E5=9B=9E=E8=B0=83=E7=B1=BB=E9=85=8D=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?scanner=E6=9C=AA=E5=88=9B=E5=BB=BA=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E6=AE=B5=E9=94=99=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 10 ++++++++-- src/entry/Maat_rule.cpp | 20 ++++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index 9ef5b47..afd232b 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -690,7 +690,10 @@ int Maat_table_callback_register(Maat_feather_t feather,short table_id, p_table->cb_info->cb_plug[idx].u_para=u_para; if(p_table->cb_info->line_num>0) { - start(MAAT_RULE_UPDATE_TYPE_FULL,u_para); + if(start!=NULL) + { + start(MAAT_RULE_UPDATE_TYPE_FULL,u_para); + } for(i=0;icb_info->line_num;i++) { lines=(const char*)dynamic_array_read(p_table->cb_info->cache_lines,i); @@ -700,7 +703,10 @@ int Maat_table_callback_register(Maat_feather_t feather,short table_id, } update(table_id,lines,u_para); } - finish(u_para); + if(finish!=NULL) + { + finish(u_para); + } } pthread_mutex_unlock(&(p_table->cb_info->plugin_mutex)); return 1; diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index ac03bec..aa761ce 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_7_20160510=1; +int MAAT_FRAME_VERSION_1_7_20160525=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", @@ -2441,7 +2441,10 @@ void maat_start_cb(unsigned int new_version,int update_type,void*u_para) p_table_cb=p_table->cb_info; for(j=0;jcb_plug_cnt;j++) { - p_table_cb->cb_plug[j].start(update_type,p_table_cb->cb_plug[j].u_para); + if(p_table_cb->cb_plug[j].start!=NULL) + { + p_table_cb->cb_plug[j].start(update_type,p_table_cb->cb_plug[j].u_para); + } } } return; @@ -2471,7 +2474,10 @@ void maat_finish_cb(void* u_para) p_table_cb=p_table->cb_info; for(j=0;jcb_plug_cnt;j++) { - p_table_cb->cb_plug[j].finish(p_table_cb->cb_plug[j].u_para); + if(p_table_cb->cb_plug[j].finish!=NULL) + { + p_table_cb->cb_plug[j].finish(p_table_cb->cb_plug[j].u_para); + } } } if(feather->update_tmp_scanner!=NULL) @@ -2485,7 +2491,7 @@ void maat_finish_cb(void* u_para) "Full config version %u load %d entries complete.", feather->update_tmp_scanner->version,feather->update_tmp_scanner->cfg_num); } - else + else if(feather->scanner!=NULL) { feather->scanner->cfg_num=total; feather->scanner->version=feather->maat_version; @@ -2506,6 +2512,12 @@ void maat_finish_cb(void* u_para) feather->scanner->version,feather->scanner->cfg_num); } } + else + { + MESA_handle_runtime_log(feather->logger,RLOG_LV_INFO,maat_module, + "Version %d have no valid scan rules, plugin callback complete.", + feather->maat_version); + } return; } void maat_update_cb(const char* table_name,const char* line,void *u_para) From 6a27c0091ef29a276230a0d7238605d824b1ab9b Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 3 Jun 2016 11:02:12 +0800 Subject: [PATCH 29/31] TODO: avoid use empty scanner --- src/entry/Maat_api.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index afd232b..c963634 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -1352,6 +1352,7 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int GIE_result_t query_result[MAX_SCANNER_HIT_NUM]; int hit_region_cnt=0,compile_ret=0; _compile_result_t compile_result[rule_num];//dynamic array + //TODO: scanner ==NULL GIE_handle_t* GIE_handle=sp->feather->scanner->digest_handle[sp->table_id]; unsigned long long digest_len=0; char* digest_buff=NULL; From 9b5dd186a76336fcbfb4e39dbcb1900422541f6f Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 3 Jun 2016 15:10:49 +0800 Subject: [PATCH 30/31] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E5=8E=BB=E9=87=8D=E8=BF=87=E7=A8=8B=E4=B8=AD?= =?UTF-8?q?=E5=BC=95=E5=85=A5=E7=9A=84=E4=B8=8E=E8=A1=A8=E8=BE=BE=E5=BC=8F?= =?UTF-8?q?=E5=AD=90=E9=A1=B9=E4=B8=A2=E5=A4=B1=E7=9A=84bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_rule.cpp | 21 ++++++++++++++------- src/entry/Maat_rule_internal.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/entry/Maat_rule.cpp b/src/entry/Maat_rule.cpp index aa761ce..65c5375 100644 --- a/src/entry/Maat_rule.cpp +++ b/src/entry/Maat_rule.cpp @@ -26,7 +26,7 @@ #include "mesa_fuzzy.h" #include "great_index_engine.h" -int MAAT_FRAME_VERSION_1_7_20160525=1; +int MAAT_FRAME_VERSION_1_8_20160603=1; const char *maat_module="MAAT Frame"; const char* CHARSET_STRING[]={"NONE","gbk","big5","unicode","utf8","bin", @@ -764,6 +764,7 @@ struct op_expr_t* create_op_expr(unsigned int expr_id,int operation,void* u_para { struct op_expr_t* op_expr=NULL; op_expr=(struct op_expr_t*)calloc(sizeof(struct op_expr_t),1); + op_expr->no_effect_convert_cnt=0; op_expr->p_expr=(boolean_expr_t*)calloc(sizeof(boolean_expr_t),1); op_expr->p_expr->expr_id=expr_id; op_expr->p_expr->operation=operation; @@ -1450,13 +1451,10 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule free(region_string); continue; } - //if convert take no effect and src charset is one of the dst. if(region_str_len==(int)strlen(sub_key_array[k])&& - 0==memcmp(sub_key_array[k],region_string,region_str_len)&& - TRUE==table->src_charset_in_dst) + 0==memcmp(sub_key_array[k],region_string,region_str_len)) { - free(region_string); - continue; + op_expr->no_effect_convert_cnt++;; } } else @@ -1475,7 +1473,16 @@ int add_expr_rule(struct _Maat_table_info_t* table,struct db_str_rule_t* db_rule free(region_string); region_string=NULL; } - MESA_lqueue_join_tail(scanner->region_update_q,&op_expr, sizeof(void*)); + //if each sub string's convert take no effect and src charset is one of the dst. + if(TRUE==table->src_charset_in_dst&&op_expr->no_effect_convert_cnt==sub_expr_cnt) + { + destroy_op_expr(op_expr); + op_expr=NULL; + } + else + { + MESA_lqueue_join_tail(scanner->region_update_q,&op_expr, sizeof(void*)); + } } } diff --git a/src/entry/Maat_rule_internal.h b/src/entry/Maat_rule_internal.h index 65d8149..81d2c78 100644 --- a/src/entry/Maat_rule_internal.h +++ b/src/entry/Maat_rule_internal.h @@ -167,6 +167,7 @@ struct op_expr_t { boolean_expr_t* p_expr; scan_rule_t* p_rules[MAAT_MAX_EXPR_ITEM_NUM]; + int no_effect_convert_cnt; }; struct _Maat_region_rule_t From a591c06b2f07f4523915cf0faf2943fad6ea0e25 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Fri, 3 Jun 2016 15:11:25 +0800 Subject: [PATCH 31/31] =?UTF-8?q?=E4=BD=BF=E7=94=A8SFH=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E6=91=98=E8=A6=81=E6=89=AB=E6=8F=8F=E6=97=B6=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0scanner=E4=B8=BA=E7=A9=BA=E7=9A=84=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entry/Maat_api.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/entry/Maat_api.cpp b/src/entry/Maat_api.cpp index c963634..82e3bb5 100644 --- a/src/entry/Maat_api.cpp +++ b/src/entry/Maat_api.cpp @@ -1352,7 +1352,14 @@ int Maat_stream_scan_digest(stream_para_t * stream_para, const char * data, int GIE_result_t query_result[MAX_SCANNER_HIT_NUM]; int hit_region_cnt=0,compile_ret=0; _compile_result_t compile_result[rule_num];//dynamic array - //TODO: scanner ==NULL + if(data==NULL||data_len<=0) + { + return 0; + } + if(sp->feather->scanner==NULL) + { + return 0; + } GIE_handle_t* GIE_handle=sp->feather->scanner->digest_handle[sp->table_id]; unsigned long long digest_len=0; char* digest_buff=NULL;