diff options
| author | alex <alex@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2007-06-21 08:15:30 +0000 |
|---|---|---|
| committer | alex <alex@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2007-06-21 08:15:30 +0000 |
| commit | 1d8f7caaea682af7b584ee4debd3a137d23158bd (patch) | |
| tree | ec31b26efa42d01aa0ef2b9a0987b709d874a18a /src | |
| parent | b9132460a4d5e0ea61e324cd8ea814aedd0a55f5 (diff) | |
- support of negative numbers in trigger expressions (Alexei)
- more formal logic of execution of trigger expressions (Alexei)
- server-side support of quotes in item parameters (num_param, get_param) (Alexei)
git-svn-id: svn://svn.zabbix.com/trunk@4318 97f52cf1-0a1b-0410-bd0e-c28be96e8082
Diffstat (limited to 'src')
| -rw-r--r-- | src/libs/zbxcommon/str.c | 385 | ||||
| -rw-r--r-- | src/zabbix_server/expression.c | 148 | ||||
| -rw-r--r-- | src/zabbix_server/server.c | 207 |
3 files changed, 543 insertions, 197 deletions
diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c index 035835c3..bad56e57 100644 --- a/src/libs/zbxcommon/str.c +++ b/src/libs/zbxcommon/str.c @@ -358,103 +358,6 @@ void del_zeroes(char *s) } } - -/****************************************************************************** - * * - * Function: get_param * - * * - * Purpose: return parameter by index (num) from parameter list (param) * - * * - * Parameters: * - * param - parameter list * - * num - requested parameter index * - * buf - pointer of output buffer * - * maxlem - size of output buffer * - * * - * Return value: * - * 1 - requested parameter missed * - * 0 - requested parameter founded (value - 'buf' can be empty string) * - * * - * Author: Eugene Grigorjev * - * * - * Comments: delimeter vor parameters is ',' * - * * - ******************************************************************************/ -int get_param(const char *param, int num, char *buf, int maxlen) -{ - char tmp[MAX_STRING_LEN]; - char *s; - int ret = 1; - int i = 0; - int idx = 0; - - strscpy(tmp,param); - - s = &tmp[0]; - - for(i=0; tmp[i] != '\0'; i++) - { - if(tmp[i] == ',') - { - idx++; - if(idx == num) - { - tmp[i]='\0'; - zbx_strlcpy(buf, s, maxlen); - tmp[i]=','; /* restore source string */ - ret = 0; - break; - - } - s = &tmp[i+1]; - } - } - - if(ret != 0) - { - idx++; - if(idx == num) - { - zbx_strlcpy(buf, s, maxlen); - ret = 0; - } - } - - return ret; -} - -/****************************************************************************** - * * - * Function: num_param * - * * - * Purpose: calculate count of parameters from parameter list (param) * - * * - * Parameters: * - * param - parameter list * - * * - * Return value: count of parameters * - * * - * Author: Eugene Grigorjev * - * * - * Comments: delimeter vor parameters is ',' * - * * - ******************************************************************************/ -int num_param(const char *param) -{ - int i; - int ret = 1; - - if(param == NULL) - return 0; - - for(i=0;param[i]!=0;i++) - { - if(param[i]==',') ret++; - } - - return ret; -} - /****************************************************************************** * * * Function: delete_reol * @@ -548,6 +451,106 @@ void zbx_ltrim(register char *str, const char *charlist) /****************************************************************************** * * + * Function: compress_signs * + * * + * Purpose: convert all repeating pluses and minuses * + * * + * Parameters: c - string to convert * + * * + * Return value: string without minuses * + * * + * Author: Alexei Vladishev * + * * + * Comments: -3*--8+5-7*-4+++5 -> N3*8+5+N7*N4+5 * + * * + ******************************************************************************/ +void compress_signs(char *str) +{ + int i,j,len; + char cur, next, prev; + int loop = 1; + +/* printf("In compress_signs [%s]\n", str);*/ + + /* Compress '--' '+-' '++' '-+' */ + while(loop == 1) + { + loop=0; + for(i=0;str[i]!='\0';i++) + { + cur=str[i]; + next=str[i+1]; + if( (cur=='-' && next=='-') || + (cur=='+' && next=='+')) + { + str[i]='+'; + for(j=i+1;str[j]!='\0';j++) str[j]=str[j+1]; + loop=1; + } + if( (cur=='-' && next=='+') || + (cur=='+' && next=='-')) + { + str[i]='-'; + for(j=i+1;str[j]!='\0';j++) str[j]=str[j+1]; + loop=1; + } + } + } +/* printf("After removing duplicates [%s]\n", str);*/ + + /* Remove '-', '+' where needed, Convert -123 to +D123 */ + for(i=0;str[i]!='\0';i++) + { + cur=str[i]; + next=str[i+1]; + if(cur == '+') + { + /* Plus is the first sign in the expression */ + if(i==0) + { + for(j=i;str[j]!='\0';j++) str[j]=str[j+1]; + } + else + { + prev=str[i-1]; + if(!isdigit(prev) && prev!='.') + { + for(j=i;str[j]!='\0';j++) str[j]=str[j+1]; + } + } + } + else if(cur == '-') + { + /* Minus is the first sign in the expression */ + if(i==0) + { + str[i]='N'; + } + else + { + prev=str[i-1]; + if(!isdigit(prev) && prev!='.') + { + str[i]='N'; + } + else + { + len=strlen(str); + for(j=len;j>i;j--) str[j]=str[j-1]; + str[i]='+'; + str[i+1]='N'; + str[len+1]='\0'; + i++; + } + } + } + } +/* printf("After removing unnecessary + and - [%s]\n", str);*/ +} + + +/****************************************************************************** + * * * Function: rtrim_spaces * * * * Purpose: delete all right spaces for the string * @@ -921,3 +924,191 @@ char* zbx_strdcatf(char *dest, const char *f, ...) return result; } + +/****************************************************************************** + * * + * Function: num_param * + * * + * Purpose: calculate count of parameters from parameter list (param) * + * * + * Parameters: * + * param - parameter list * + * * + * Return value: count of parameters * + * * + * Author: Alexei Vladishev * + * * + * Comments: delimeter vor parameters is ',' * + * * + ******************************************************************************/ +int num_param(const char *param) +{ + int i; + int ret = 1; + +/* 0 - init, 1 - inside quoted param, 2 - inside unquoted param */ + int state = 0; + char c; + + if(param == NULL) + return 0; + + for(i=0;param[i]!='\0';i++) + { + c=param[i]; + switch(state) + { + case 0: + if(c==',') + { + ret++; + } + else if(c=='"') + { + state=1; + } + else if(c=='\\' && param[i+1]=='"') + { + state=2; + } + else if(c!=' ') + { + state=2; + } + break; + case 1: + if(c=='"') + { + state=0; + } + else if(c=='\\' && param[i+1]=='"') + { + i++; + state=2; + } + break; + case 2: + if(c==',') + { + ret++; + state=0; + } + break; + } + } + + return ret; +} + +/****************************************************************************** + * * + * Function: get_param * + * * + * Purpose: return parameter by index (num) from parameter list (param) * + * * + * Parameters: * + * param - parameter list * + * num - requested parameter index * + * buf - pointer of output buffer * + * maxlem - size of output buffer * + * * + * Return value: * + * 1 - requested parameter missed * + * 0 - requested parameter founded (value - 'buf' can be empty string) * + * * + * Author: Eugene Grigorjev, rewritten by Alexei * + * * + * Comments: delimeter vor parameters is ',' * + * * + ******************************************************************************/ +int get_param(const char *param, int num, char *buf, int maxlen) +{ + int ret = 1; + int i = 0; + int idx = 1; + int buf_i = 0; + + char test[MAX_STRING_LEN]; + +/* 0 - init, 1 - inside quoted param, 2 - inside unquoted param */ + int state = 0; + char c; + + buf[0]='\0'; + test[0]='\0'; + + for(i=0; param[i] != '\0' && idx<=num && buf_i<maxlen; i++) + { + if(idx == num) ret = 0; + c=param[i]; + switch(state) + { + /* Init state */ + case 0: + if(c==',') + { + idx++; + } + else if(c=='"') + { + state=1; + } + else if(idx == num) + { + if(c=='\\' && param[i+1]=='"') + { + buf[buf_i++]=c; + i++; + buf[buf_i++]=param[i]; + } + else if(c!=' ') + { + buf[buf_i++]=c; + } + state=2; + } + break; + /* Quoted */ + case 1: + if(c=='"') + { + state=0; + } + else if(idx == num) + { + if(c=='\\' && param[i+1]=='"') + { + i++; + buf[buf_i++]=param[i]; + } + else + { + buf[buf_i++]=c; + } + } + break; + /* Unquoted */ + case 2: + if(c==',') + { + idx++; + state=0; + } + else if(idx == num) + { + buf[buf_i++]=c; + } + break; + } + } + + buf[buf_i]='\0'; + + /* Missing first parameter will return OK */ + if(num == 1) + { + ret = 0; + } + + return ret; +} diff --git a/src/zabbix_server/expression.c b/src/zabbix_server/expression.c index fdd2ce81..d8f13343 100644 --- a/src/zabbix_server/expression.c +++ b/src/zabbix_server/expression.c @@ -130,67 +130,80 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) /* Remove left and right spaces */ lrtrim_spaces(exp); - if( is_double_prefix(exp) == SUCCEED ) +/* Compress repeating - and +. Add prefix N to negative numebrs. */ + compress_signs(exp); + + /* We should process negative prefix, i.e. N123 == -123 */ + if( exp[0]=='N' && is_double_prefix(exp+1) == SUCCEED ) + { +/* str2double support prefixes */ + *result=-str2double(exp+1); + return SUCCEED; + } + else if( exp[0]!='N' && is_double_prefix(exp) == SUCCEED ) { /* str2double support prefixes */ *result=str2double(exp); return SUCCEED; } - if( (p = strstr(exp,"|")) != NULL ) + if((p = strstr(exp,"=")) != NULL) { *p=0; strscpy( first, exp); *p='|'; p++; strscpy( second, p); - if( evaluate_simple(&value1,first,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", error); - zabbix_syslog("%s", error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", + error); + zabbix_syslog("%s", + error); return FAIL; } - if( value1 == 1) - { - *result=value1; - return SUCCEED; - } if( evaluate_simple(&value2,second,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", error); - zabbix_syslog("%s", error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", + error); + zabbix_syslog("%s", + error); return FAIL; } - if( value2 == 1) + if( cmp_double(value1,value2) ==0 ) { - *result=value2; - return SUCCEED; + *result=1; + } + else + { + *result=0; } - *result=0; return SUCCEED; } - if( (p = strstr(exp,"&")) != NULL ) + if((p = strstr(exp,"#")) != NULL) { *p=0; strscpy( first, exp); *p='|'; p++; strscpy( second, p); - if( evaluate_simple(&value1,first,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", error); - zabbix_syslog("%s", error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", + error); + zabbix_syslog("%s", + error); return FAIL; } if( evaluate_simple(&value2,second,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", error); - zabbix_syslog("%s", error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", + error); + zabbix_syslog("%s", + error); return FAIL; } - if( (value1 == 1) && (value2 == 1) ) + if( cmp_double(value1,value2) != 0 ) { *result=1; } @@ -200,7 +213,7 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) } return SUCCEED; } - if( (p = strstr(exp,">")) != NULL ) + if((p = strstr(exp,">")) != NULL) { *p=0; strscpy( first, exp); @@ -229,7 +242,7 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) } return SUCCEED; } - if( (p = strstr(exp,"<")) != NULL ) + if((p = strstr(exp,"<")) != NULL) { *p=0; strscpy( first, exp); @@ -263,73 +276,70 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) zabbix_log(LOG_LEVEL_DEBUG, "Result [" ZBX_FS_DBL "]",*result ); return SUCCEED; } - if( (p = strstr(exp,"*")) != NULL ) + if( (p = strstr(exp,"|")) != NULL ) { *p=0; strscpy( first, exp); *p='|'; p++; strscpy( second, p); + if( evaluate_simple(&value1,first,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", - error); - zabbix_syslog("%s", - error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", error); + zabbix_syslog("%s", error); return FAIL; } + if( value1 == 1) + { + *result=value1; + return SUCCEED; + } if( evaluate_simple(&value2,second,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", - error); - zabbix_syslog("%s", - error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", error); + zabbix_syslog("%s", error); return FAIL; } - *result=value1*value2; + if( value2 == 1) + { + *result=value2; + return SUCCEED; + } + *result=0; return SUCCEED; } - if( (p = strstr(exp,"/")) != NULL ) + if( (p = strstr(exp,"&")) != NULL ) { *p=0; strscpy( first, exp); *p='|'; p++; strscpy( second, p); + if( evaluate_simple(&value1,first,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", - error); - zabbix_syslog("%s", - error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", error); + zabbix_syslog("%s", error); return FAIL; } if( evaluate_simple(&value2,second,error,maxerrlen) == FAIL ) { - zabbix_log(LOG_LEVEL_DEBUG, "%s", - error); - zabbix_syslog("%s", - error); + zabbix_log(LOG_LEVEL_DEBUG, "%s", error); + zabbix_syslog("%s", error); return FAIL; } - if(cmp_double(value2,0) == 0) + if( (value1 == 1) && (value2 == 1) ) { - zbx_snprintf(error,maxerrlen,"Division by zero. Cannot evaluate expression [%s/%s]", - first, - second); - zabbix_log(LOG_LEVEL_WARNING, "%s", - error); - zabbix_syslog("%s", - error); - return FAIL; + *result=1; } else { - *result=value1/value2; + *result=0; } return SUCCEED; } - if( (p = strstr(exp,"+")) != NULL ) + if((p = strstr(exp,"+")) != NULL) { *p=0; strscpy( first, exp); @@ -355,7 +365,7 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) *result=value1+value2; return SUCCEED; } - if( (p = strstr(exp,"-")) != NULL ) + if((p = strstr(exp,"-")) != NULL) { *p=0; strscpy( first, exp); @@ -381,7 +391,7 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) *result=value1-value2; return SUCCEED; } - if( (p = strstr(exp,"=")) != NULL ) + if((p = strstr(exp,"*")) != NULL) { *p=0; strscpy( first, exp); @@ -404,17 +414,10 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) error); return FAIL; } - if( cmp_double(value1,value2) ==0 ) - { - *result=1; - } - else - { - *result=0; - } + *result=value1*value2; return SUCCEED; } - if( (p = strstr(exp,"#")) != NULL ) + if((p = strrchr(exp,'/')) != NULL) { *p=0; strscpy( first, exp); @@ -437,13 +440,20 @@ int evaluate_simple(double *result,char *exp,char *error,int maxerrlen) error); return FAIL; } - if( cmp_double(value1,value2) != 0 ) + if(cmp_double(value2,0) == 0) { - *result=1; + zbx_snprintf(error,maxerrlen,"Division by zero. Cannot evaluate expression [%s/%s]", + first, + second); + zabbix_log(LOG_LEVEL_WARNING, "%s", + error); + zabbix_syslog("%s", + error); + return FAIL; } else { - *result=0; + *result=value1/value2; } return SUCCEED; } diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c index b24e3161..8879553a 100644 --- a/src/zabbix_server/server.c +++ b/src/zabbix_server/server.c @@ -17,6 +17,8 @@ ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **/ +/* #define ZABBIX_TEST */ + #include "common.h" #include "cfg.h" @@ -257,59 +259,202 @@ void init_config(void) #ifdef ZABBIX_TEST -void test() +void test_params() { - zabbix_set_log_level(LOG_LEVEL_DEBUG); - DB_ITEM item; - AGENT_RESULT result; +#define ZBX_PARAM struct zbx_param_t - DB_ROW row; - DB_RESULT db_result; +ZBX_PARAM +{ + char *exp; + int num; + int test_num; + int expected_ret; + char *expected_result; +}; - - printf("-= Test Started =-\n\n"); +ZBX_PARAM expressions[]= +{ + {"1,0", 2, 1, 0, "1"}, + {"0", 1, 1, 0, "0"}, + {"0", 1, 2, 1, ""}, + {"\"0\",\"1\"", 2, 2, 0, "1"}, + {"\"0\",1\"", 2, 2, 0, "1\""}, + {"\"0\"", 1, 1, 0, "0"}, + {"\\\"", 1, 1, 0, "\\\""}, + {"\"0\",\\\"", 2, 2, 0, "\\\""}, + {NULL} +}; - DBconnect(ZBX_DB_CONNECT_EXIT); + int result; + int i; - db_result = DBselect("select %s where h.hostid=i.hostid and i.hostid=10017", ZBX_SQL_ITEM_SELECT); + char *exp=NULL; + char str[MAX_STRING_LEN]; - while( (row = DBfetch(db_result)) ) + printf("-= Test parameters =-\n\n"); + + for(i=0;expressions[i].exp!=NULL;i++) { - DBget_item_from_db(&item,row); - - init_result(&result); + printf("Testing get_patam(%d,\"%s\")\n", expressions[i].test_num, expressions[i].exp); + + exp=zbx_malloc(exp,1024); + zbx_snprintf(exp,1024,"%s",expressions[i].exp); + str[0]='\0'; - get_value(&item, &result); - - printf("'%15s'", item.key); - if(result.type & AR_DOUBLE) + if(num_param(exp) != expressions[i].num) { - printf(" [d|" ZBX_FS_DBL "]", result.dbl); + printf("Wrong num_param(%s) Got %d Expected %d\n", exp, num_param(exp), expressions[i].num); } - if(result.type & AR_UINT64) + result = get_param(exp, expressions[i].test_num, str, sizeof(str)); + if(result != expressions[i].expected_ret) { - printf(" [u|" ZBX_FS_UI64 "]", result.ui64); + printf("Wrong result of get_param(%s) Got %d Expected %d\n", exp, result, expressions[i].expected_ret); } - if(result.type & AR_STRING) + else if(strcmp(str, expressions[i].expected_result)!=0) { - printf(" [s|%s]", result.str); + printf("Wrong result string of get_param(%d,\"%s\") Got [%s] Expected [%s]\n", + expressions[i].test_num, + exp, + str, + expressions[i].expected_result); } - if(result.type & AR_TEXT) + zbx_free(exp); + } + exit(-1); +} + +void test_expressions() +{ + +#define ZBX_EXP struct zbx_exp_t + +ZBX_EXP +{ + char *exp; + int expected_result; +}; + +ZBX_EXP expressions[]= +{ +/* Supported operators /+-*|&#<>= */ + {"1+2", 3}, + {"1-2", -1}, + {"6/2", 3}, + {"1", 1}, + {"0", 0}, + {"1*1", 1}, + {"2*1-2", 0}, + {"-2*1-2", -4}, + {"-8*-2-10*3", -14}, + {"(1+5)*(1+2)", 18}, + {"8/2*2", 8}, + {"8*2/2*2", 16}, + {NULL} +}; + + int result; + int i; + + char *exp=NULL; + char error[MAX_STRING_LEN]; + + printf("-= Test expressions =-\n\n"); + + for(i=0;expressions[i].exp!=NULL;i++) + { + exp=zbx_malloc(exp,1024); + zbx_snprintf(exp,1024,"%s",expressions[i].exp); + if(SUCCEED != evaluate_expression(&result,&exp, 0, error, sizeof(error)-1)) { - printf(" [t|%s]", result.text); + zabbix_log(LOG_LEVEL_DEBUG, "Evaluation of expression [%s] failed [%s]", + &exp, + error); } - if(result.type & AR_MESSAGE) + printf("Testing \"%s\" Expected result %d Got %d Result: %s\n", + expressions[i].exp, + expressions[i].expected_result, + result, + (expressions[i].expected_result==result)?"OK":"NOT OK"); + zbx_free(exp); + } + exit(-1); +} + + +void test_compress_signs() +{ + +#define ZBX_SIGN struct zbx_sign_t + +ZBX_SIGN +{ + char *str; + char *expected; +}; + +ZBX_SIGN expressions[]= +{ + {"1", "1"}, + {"0", "0"}, + {"1*1", "1*1"}, + {"2*1-2", "2*1+N2"}, + {"-2*1-2", "N2*1+N2"}, + {"--2--3", "2+3"}, + {"-+2+-3", "N2+N3"}, + {"++2--3", "2+3"}, + {"+-+2", "N2"}, + {"+++2", "2"}, + {"2/+2", "2/2"}, + {"2+2", "2+2"}, + {"-2", "N2"}, + {"1/-2", "1/N2"}, + {"2-3+5", "2+N3+5"}, + {"2-3", "2+N3"}, + {"+-+123", "N123"}, + {NULL} +}; + + int result; + int i; + + char *exp=NULL; + + printf("-= Test compress signs =-\n"); + + for(i=0;expressions[i].str!=NULL;i++) + { + exp=zbx_malloc(exp,1024); + zbx_snprintf(exp,1024,"%s",expressions[i].str); + compress_signs(exp); + if(strcmp(expressions[i].expected, exp)!=0) { - printf(" [m|%s]", result.msg); + printf("FAILED \"%s\" Expected result %s Got %s\n", + expressions[i].str, + expressions[i].expected, + exp); } - - free_result(&result); + zbx_free(exp); } + printf("Passed OK\n"); +} - DBfree_result(db_result); +void test() +{ + zabbix_set_log_level(LOG_LEVEL_DEBUG); - DBclose(); + DB_ITEM item; + AGENT_RESULT result; + + DB_ROW row; + DB_RESULT db_result; + + + printf("-= Test Started =-\n\n"); + +/* test_params();*/ + test_compress_signs(); + test_expressions(); printf("\n-= Test completed =-\n"); } |
