00001
00002
00003
00004 #include "utils.h"
00005 #include "restructs.h"
00006 #include "parser.h"
00007 #include "arithmetics.h"
00008 #include "datetime.h"
00009 #include "index.h"
00010 #include "rules.h"
00011 #include "functions.h"
00012 #include "configuration.h"
00013
00014 #ifndef DEBUG
00015 #include "regExpMatch.h"
00016 #include "rodsErrorTable.h"
00017 typedef struct {
00018 char action[MAX_ACTION_SIZE];
00019 int numberOfStringArgs;
00020 funcPtr callAction;
00021 } microsdef_t;
00022 extern int NumOfAction;
00023 extern microsdef_t MicrosTable[];
00024 #endif
00025
00026 #define RE_ERROR(x, y) if(x) {if((y)!=NULL){(y)->type.t=RE_ERROR;*errnode=node;}return;}
00027 #define OUTOFMEMORY(x, res) if(x) {(res)->value.e = OUT_OF_MEMORY;TYPE(res) = RE_ERROR;return;}
00028
00029 #define RE_ERROR2(x,y) if(x) {localErrorMsg=(y);goto error;}
00030 extern int GlobalREDebugFlag;
00031 extern int GlobalREAuditFlag;
00032
00033
00034 int initializeEnv(Node *params, Res *args[MAX_NUM_OF_ARGS_IN_ACTION], int argc, Hashtable *env, Region *r) {
00035
00036
00037 Node** args2 = params->subtrees;
00038
00039 int i;
00040
00041 for (i = 0; i < argc ; i++) {
00042 insertIntoHashTable(env, args2[i]->text, args[i]);
00043 }
00044 return (0);
00045 }
00046
00047 char *matchWholeString(char *buf) {
00048 char *buf2 = (char *)malloc(sizeof(char)*strlen(buf)+2+1);
00049 buf2[0]='^';
00050 strcpy(buf2+1, buf);
00051 buf2[strlen(buf)+1]='$';
00052 buf2[strlen(buf)+2]='\0';
00053 return buf2;
00054 }
00055
00056 char *wildCardToRegex(char *buf) {
00057 char *buf2 = (char *)malloc(sizeof(char)*strlen(buf)*3+2+1);
00058 char *p = buf2;
00059 int i;
00060 *(p++)='^';
00061 int n = strlen(buf);
00062 for(i=0;i<n;i++) {
00063 switch(buf[i]) {
00064 case '*':
00065 *(p++) = '.';
00066 *(p++) = buf[i];
00067 break;
00068 case ']':
00069 case '[':
00070 case '^':
00071 *(p++) = '\\';
00072 *(p++) = buf[i];
00073 break;
00074 default:
00075 *(p++) = '[';
00076 *(p++) = buf[i];
00077 *(p++) = ']';
00078 break;
00079 }
00080 }
00081 *(p++)='$';
00082 *(p++)='\0';
00083 return buf2;
00084 }
00085
00086 char* getVariableName(Node *node) {
00087 return node->subtrees[0]->text;
00088 }
00089
00090
00091 Res* evaluateExpression3(Node *expr, int applyAll, int force, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t* errmsg, Region *r) {
00092
00093
00094
00095 char errbuf[ERR_MSG_LEN];
00096 Res *res = newRes(r), *funcRes = NULL, *argRes = NULL;
00097 FunctionDesc *fd = NULL;
00098 int i;
00099 Res **tupleComps = NULL;
00100
00101
00102
00103 if(force || getIOType(expr) == IO_TYPE_INPUT ) {
00104 switch(getNodeType(expr)) {
00105 case TK_BOOL:
00106 res->exprType = newSimpType(T_BOOL, r);
00107 RES_BOOL_VAL_LVAL(res) = strcmp(expr->text, "true")==0?1:0;
00108 break;
00109 case TK_INT:
00110 res->exprType = newSimpType(T_INT,r);
00111 RES_INT_VAL_LVAL(res)=atoi(expr->text);
00112 break;
00113 case TK_DOUBLE:
00114 res->exprType = newSimpType(T_DOUBLE,r);
00115 RES_DOUBLE_VAL_LVAL(res)=atof(expr->text);
00116 break;
00117 case TK_STRING:
00118 res = newStringRes(r, expr->text);
00119 break;
00120 case TK_VAR:
00121 res = evaluateVar3(expr->text, expr, rei, reiSaveFlag, env, errmsg,r);
00122 break;
00123 case TK_TEXT:
00124 fd = (FunctionDesc *)lookupFromEnv(ruleEngineConfig.extFuncDescIndex, expr->text);
00125 if(fd!=NULL && fd->exprType != NULL) {
00126 int nArgs = 0;
00127 ExprType *type = fd->exprType;
00128 while(getNodeType(type) == T_CONS && strcmp(type->text, FUNC) == 0) {
00129 type = type->subtrees[1];
00130 nArgs ++;
00131 }
00132 if(nArgs == 0) {
00133 Node *appNode = newPartialApplication(expr, newTupleRes(0,NULL,r), 0, r);
00134 res = evaluateFunction3(appNode, applyAll, expr, env, rei, reiSaveFlag, errmsg, r);
00135 } else {
00136 res = newFuncSymLink(expr->text, nArgs, r);
00137 }
00138 } else {
00139 res = newFuncSymLink(expr->text, 1, r);
00140 }
00141 break;
00142
00143
00144 case N_APPLICATION:
00145
00146
00147
00148
00149
00150 funcRes = evaluateExpression3(expr->subtrees[0], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg,r);
00151 if(getNodeType(funcRes)==N_ERROR) {
00152 res = funcRes;
00153 break;
00154 }
00155
00156 argRes = evaluateExpression3(expr->subtrees[1], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg,r);
00157 if(getNodeType(argRes)==N_ERROR) {
00158 res = argRes;
00159 break;
00160 }
00161 res = evaluateFunctionApplication(funcRes, argRes, applyAll, expr, rei, reiSaveFlag, env, errmsg,r);
00162
00163
00164
00165
00166 break;
00167 case N_TUPLE:
00168 tupleComps = (Res **) region_alloc(r, sizeof(Res *) * expr->degree);
00169 for(i=0;i<expr->degree;i++) {
00170 res = tupleComps[i] = evaluateExpression3(expr->subtrees[i], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r);
00171 if(getNodeType(res) == N_ERROR) {
00172 break;
00173 }
00174 }
00175 if(expr->degree == 0 || getNodeType(res) != N_ERROR) {
00176 if(N_TUPLE_CONSTRUCT_TUPLE(expr) || expr->degree != 1) {
00177 res = newTupleRes(expr->degree, tupleComps, r);
00178 }
00179 }
00180 break;
00181 case N_ACTIONS_RECOVERY:
00182 res = evaluateActions(expr->subtrees[0], expr->subtrees[1], applyAll, rei, reiSaveFlag, env, errmsg, r);
00183 break;
00184
00185 case N_ACTIONS:
00186 generateErrMsg("error: evaluate actions using function evaluateExpression3, use function evaluateActions instead.", NODE_EXPR_POS(expr), expr->base, errbuf);
00187 addRErrorMsg(errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf);
00188 res = newErrorRes(r, RE_UNSUPPORTED_AST_NODE_TYPE);
00189 break;
00190 default:
00191 generateErrMsg("error: unsupported ast node type.", NODE_EXPR_POS(expr), expr->base, errbuf);
00192 addRErrorMsg(errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf);
00193 res = newErrorRes(r, RE_UNSUPPORTED_AST_NODE_TYPE);
00194 break;
00195 }
00196 } else {
00197 res = expr;
00198 while(getNodeType(res) == N_TUPLE && res->degree == 1) {
00199 res = res->subtrees[0];
00200 }
00201 }
00202
00203 return res;
00204 }
00205
00206 Res* processCoercion(Node *node, Res *res, ExprType *type, Hashtable *tvarEnv, rError_t *errmsg, Region *r) {
00207 char buf[ERR_MSG_LEN>1024?ERR_MSG_LEN:1024];
00208 char *buf2;
00209 char buf3[ERR_MSG_LEN];
00210 ExprType *coercion = type;
00211 if(getNodeType(coercion) == T_FLEX) {
00212 coercion = coercion->subtrees[0];
00213 } else if(getNodeType(coercion) == T_FIXD) {
00214 coercion = coercion->subtrees[1];
00215 }
00216 coercion = instantiate(coercion, tvarEnv, 0, r);
00217 if(getNodeType(coercion) == T_VAR) {
00218 if(T_VAR_NUM_DISJUNCTS(coercion) == 0) {
00219
00220
00221
00222 return res;
00223 }
00224
00225
00226 ExprType *defaultType = T_VAR_DISJUNCT(coercion,0);
00227 updateInHashTable(tvarEnv, getTVarName(T_VAR_ID(coercion), buf), defaultType);
00228 coercion = defaultType;
00229 }
00230 if(typeEqSyntatic(coercion, res->exprType)) {
00231 return res;
00232 } else {
00233 if(TYPE(res)==T_UNSPECED) {
00234 generateErrMsg("error: dynamic coercion from an uninitialized value", NODE_EXPR_POS(node), node->base, buf);
00235 addRErrorMsg(errmsg, RE_DYNAMIC_COERCION_ERROR, buf);
00236 return newErrorRes(r, RE_DYNAMIC_COERCION_ERROR);
00237 }
00238 switch(getNodeType(coercion)) {
00239 case T_DYNAMIC:
00240 return res;
00241 case T_INT:
00242 switch(TYPE(res) ) {
00243 case T_DOUBLE:
00244 case T_BOOL:
00245 if((int)RES_DOUBLE_VAL(res)!=RES_DOUBLE_VAL(res)) {
00246 generateErrMsg("error: dynamic type conversion DOUBLE -> INTEGER: the double is not an integer", NODE_EXPR_POS(node), node->base, buf);
00247 addRErrorMsg(errmsg, RE_DYNAMIC_COERCION_ERROR, buf);
00248 return newErrorRes(r, RE_DYNAMIC_COERCION_ERROR);
00249 } else {
00250 return newIntRes(r, RES_INT_VAL(res));
00251 }
00252 case T_STRING:
00253 return newIntRes(r, atoi(res->text));
00254 default:
00255 break;
00256 }
00257 break;
00258 case T_DOUBLE:
00259 switch(TYPE(res) ) {
00260 case T_INT:
00261 case T_BOOL:
00262 return newDoubleRes(r, RES_DOUBLE_VAL(res));
00263 case T_STRING:
00264 return newDoubleRes(r, atof(res->text));
00265 default:
00266 break;
00267 }
00268 break;
00269 case T_STRING:
00270 switch(TYPE(res) ) {
00271 case T_INT:
00272 case T_DOUBLE:
00273 case T_BOOL:
00274 buf2 = convertResToString(res);
00275
00276 res = newStringRes(r, buf2);
00277 free(buf2);
00278 return res;
00279 default:
00280 break;
00281 }
00282 break;
00283 case T_BOOL:
00284 switch(TYPE(res) ) {
00285 case T_INT:
00286 case T_DOUBLE:
00287 return newBoolRes(r, RES_BOOL_VAL(res));
00288 case T_STRING:
00289 if(strcmp(res->text, "true")==0) {
00290 return newBoolRes(r, 1);
00291 } else if(strcmp(res->text, "false")==0) {
00292 return newBoolRes(r, 0);
00293 } else {
00294 generateErrMsg("error: dynamic type conversion string -> bool: the string is not in {true, false}", NODE_EXPR_POS(node), node->base, buf);
00295 addRErrorMsg(errmsg, RE_DYNAMIC_COERCION_ERROR, buf);
00296 return newErrorRes(r, RE_DYNAMIC_COERCION_ERROR);
00297 }
00298 break;
00299 default:
00300 break;
00301 }
00302 break;
00303 case T_CONS:
00304
00305 switch(TYPE(res)) {
00306 case T_CONS:
00307 return res;
00308 case T_IRODS:
00309 if(strcmp(res->exprType->text, IntArray_MS_T) == 0 ||
00310 strcmp(res->exprType->text, StrArray_MS_T) == 0 ||
00311 strcmp(res->exprType->text, GenQueryOut_MS_T) == 0) {
00312 return res;
00313 }
00314 break;
00315 default:
00316 break;
00317 }
00318 break;
00319 case T_DATETIME:
00320 switch(TYPE(res)) {
00321 case T_INT:
00322 newDatetimeRes(r, (time_t) RES_INT_VAL(res));
00323 break;
00324 default:
00325 break;
00326 }
00327 break;
00328 default:
00329 break;
00330 }
00331 char typeBuf1[128], typeBuf2[128];
00332 snprintf(buf, ERR_MSG_LEN, "error: coerce from type %s to type %s",
00333 typeToString(res->exprType, tvarEnv, typeBuf1, 128),
00334 typeToString(coercion, tvarEnv, typeBuf2, 128));
00335 generateErrMsg(buf, NODE_EXPR_POS(node), node->base, buf3);
00336 addRErrorMsg(errmsg, RE_TYPE_ERROR, buf3);
00337 return newErrorRes(r, RE_TYPE_ERROR);
00338 }
00339 }
00340
00341 Res* evaluateActions(Node *expr, Node *reco, int applyAll, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t* errmsg, Region *r) {
00342
00343
00344
00345 int i;
00346 int cutFlag = 0;
00347 Res* res = NULL;
00348 #ifndef DEBUG
00349 char tmpStr[1024];
00350 #endif
00351 switch(getNodeType(expr)) {
00352 case N_ACTIONS:
00353 for(i=0;i<expr->degree;i++) {
00354 Node *nodei = expr->subtrees[i];
00355 if(getNodeType(nodei) == N_APPLICATION && getNodeType(nodei->subtrees[0]) == TK_TEXT && strcmp(nodei->subtrees[0]->text, "cut") == 0) {
00356 cutFlag = 1;
00357 continue;
00358 }
00359 res = evaluateExpression3(nodei, applyAll, 0, rei, reiSaveFlag, env, errmsg,r);
00360 if(getNodeType(res) == N_ERROR) {
00361 #ifndef DEBUG
00362 sprintf(tmpStr,"executeRuleAction Failed for %s",N_APP_FUNC(nodei)->text);
00363 rodsLogError(LOG_ERROR,RES_ERR_CODE(res),tmpStr);
00364 rodsLog (LOG_NOTICE,"executeRuleBody: Micro-service or Action %s Failed with status %i",N_APP_FUNC(nodei)->text,RES_ERR_CODE(res));
00365 #endif
00366
00367 if(RES_ERR_CODE(res) != RETRY_WITHOUT_RECOVERY_ERR && reco!=NULL) {
00368 int i2;
00369 for(i2 = reco->degree-1<i?reco->degree-1:i;i2>=0;i2--) {
00370 #ifndef DEBUG
00371 if (reTestFlag > 0) {
00372 if (reTestFlag == COMMAND_TEST_1 || COMMAND_TEST_MSI)
00373 fprintf(stdout,"***RollingBack\n");
00374 else if (reTestFlag == HTML_TEST_1)
00375 fprintf(stdout,"<FONT COLOR=#FF0000>***RollingBack</FONT><BR>\n");
00376 else if (reTestFlag == LOG_TEST_1)
00377 if (rei != NULL && rei->rsComm != NULL && &(rei->rsComm->rError) != NULL)
00378 rodsLog (LOG_NOTICE,"***RollingBack\n");
00379 }
00380 #endif
00381
00382 Res *res2 = evaluateExpression3(reco->subtrees[i2], 0, 0, rei, reiSaveFlag, env, errmsg, r);
00383 if(getNodeType(res2) == N_ERROR) {
00384 #ifndef DEBUG
00385 sprintf(tmpStr,"executeRuleRecovery Failed for %s",N_APP_FUNC(reco->subtrees[i2])->text);
00386 rodsLogError(LOG_ERROR,RES_ERR_CODE(res2),tmpStr);
00387 #endif
00388 }
00389 }
00390 }
00391 if(cutFlag) {
00392 return newErrorRes(r, CUT_ACTION_PROCESSED_ERR);
00393 } else {
00394 return res;
00395 }
00396 }
00397 else if(TYPE(res) == T_BREAK) {
00398 return res;
00399 }
00400 else if(TYPE(res) == T_SUCCESS) {
00401 return res;
00402 }
00403
00404 }
00405 return res==NULL?newIntRes(r, 0):res;
00406 default:
00407 break;
00408 }
00409 char errbuf[ERR_MSG_LEN];
00410 generateErrMsg("error: unsupported ast node type.", NODE_EXPR_POS(expr), expr->base, errbuf);
00411 addRErrorMsg(errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf);
00412 return newErrorRes(r, RE_UNSUPPORTED_AST_NODE_TYPE);
00413 }
00414
00415 Res *evaluateFunctionApplication(Node *func, Node *arg, int applyAll, Node *node, ruleExecInfo_t* rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r) {
00416 Res *res;
00417 char errbuf[ERR_MSG_LEN];
00418 switch(getNodeType(func)) {
00419 case N_SYM_LINK:
00420 case N_PARTIAL_APPLICATION:
00421 res = newPartialApplication(func, arg, RES_FUNC_N_ARGS(func) - 1, r);
00422 if(RES_FUNC_N_ARGS(res) == 0) {
00423 res = evaluateFunction3(res, applyAll, node, env, rei, reiSaveFlag, errmsg, r);
00424 }
00425 return res;
00426 default:
00427 generateErrMsg("unsupported function node type.", NODE_EXPR_POS(node), node->base, errbuf);
00428 addRErrorMsg(errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf);
00429 return newErrorRes(r, RE_UNSUPPORTED_AST_NODE_TYPE);
00430 }
00431 }
00432
00433 void printEnvIndent(Env *env) {
00434 Env *e = env->lower;
00435 int i =0;
00436 while(e!=NULL) {
00437 i++;
00438 e=e->lower;
00439 }
00440 printIndent(i);
00441 }
00442
00443
00444
00445
00446
00447 Res* evaluateFunction3(Node *appRes, int applyAll, Node *node, Env *env, ruleExecInfo_t* rei, int reiSaveFlag, rError_t *errmsg, Region *r) {
00448 unsigned int i;
00449 unsigned int n;
00450 Node* args[MAX_FUNC_PARAMS];
00451 i = 0;
00452 Node *appFuncRes = appRes;
00453 while(getNodeType(appFuncRes) == N_PARTIAL_APPLICATION) {
00454 i++;
00455 appFuncRes = appFuncRes->subtrees[0];
00456 }
00457
00458 char* fn = appFuncRes->text;
00459 if(strcmp(fn, "nop") == 0) {
00460 return newIntRes(r, 0);
00461 }
00462
00463
00464
00465
00466
00467 Res *appArgRes = appRes->subtrees[1];
00468
00469 n = appArgRes->degree;
00470 Res** appArgs = appArgRes->subtrees;
00471 Node** nodeArgs = node->subtrees[1]->subtrees;
00472 ExprType *coercionType = NULL;
00473 #ifdef DEBUG
00474 char buf[ERR_MSG_LEN>1024?ERR_MSG_LEN:1024];
00475 sprintf(buf, "Action: %s\n", fn);
00476 writeToTmp("eval.log", buf);
00477 #endif
00478
00479
00480 Res* res;
00481 Region *newRegion = make_region(0, NULL);
00482 Env *global = globalEnv(env);
00483 Env *nEnv = newEnv(newHashTable2(10, newRegion), global, env, newRegion);
00484
00485 List *localTypingConstraints = NULL;
00486 FunctionDesc *fd = NULL;
00487
00488 fd = (FunctionDesc *)lookupFromEnv(ruleEngineConfig.extFuncDescIndex, fn);
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 localTypingConstraints = newList(r);
00504 char ioParam[MAX_FUNC_PARAMS];
00505
00506 for(i=0;i<n;i++) {
00507 switch(getIOType(nodeArgs[i])) {
00508 case IO_TYPE_INPUT | IO_TYPE_OUTPUT:
00509 ioParam[i] = 'p';
00510 args[i] = evaluateExpression3(appArgs[i], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, newRegion);
00511 if(getNodeType(args[i])==N_ERROR) {
00512 res = (Res *)args[i];
00513 RETURN;
00514 }
00515 break;
00516 case IO_TYPE_INPUT:
00517 ioParam[i] = 'i';
00518 args[i] = appArgs[i];
00519 break;
00520 case IO_TYPE_DYNAMIC:
00521 if(isVariableNode(appArgs[i])) {
00522 args[i] = attemptToEvaluateVar3(appArgs[i]->text, appArgs[i], rei, reiSaveFlag, env, errmsg, newRegion);
00523 if(TYPE(args[i]) == T_UNSPECED) {
00524 ioParam[i] = 'o';
00525 } else {
00526 ioParam[i] = 'p';
00527 if(getNodeType(args[i])==N_ERROR) {
00528 res = (Res *)args[i];
00529 RETURN;
00530 }
00531 }
00532 } else {
00533 ioParam[i] = 'i';
00534 args[i] = evaluateExpression3(appArgs[i], applyAll > 1 ? applyAll : 0, 1, rei, reiSaveFlag, env, errmsg, newRegion);
00535 if(getNodeType(args[i])==N_ERROR) {
00536 res = (Res *)args[i];
00537 RETURN;
00538 }
00539 }
00540 break;
00541 case IO_TYPE_OUTPUT:
00542 ioParam[i] = 'o';
00543 args[i] = newUnspecifiedRes(r);
00544 break;
00545 case IO_TYPE_EXPRESSION:
00546 ioParam[i] = 'e';
00547 args[i] = appArgs[i];
00548 break;
00549 case IO_TYPE_ACTIONS:
00550 ioParam[i] = 'a';
00551 args[i] = appArgs[i];
00552 break;
00553 }
00554 }
00555
00556 coercionType = node->subtrees[1]->coercionType;
00557 if(coercionType!=NULL) {
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 ExprType *argType = newTupleRes(n, args, r)->exprType;
00572 if(typeFuncParam(node->subtrees[1], argType, coercionType, env->current, localTypingConstraints, errmsg, newRegion)!=0) {
00573 res = newErrorRes(r, RE_TYPE_ERROR);
00574 RETURN;
00575 }
00576
00577
00578
00579 Node *errnode;
00580 if(!solveConstraints(localTypingConstraints, env->current, errmsg, &errnode, r)) {
00581 res = newErrorRes(r, RE_DYNAMIC_TYPE_ERROR);
00582 RETURN;
00583 }
00584
00585
00586 ExprType **coercionTypes = coercionType->subtrees;
00587 for(i=0;i<n;i++) {
00588 if((ioParam[i] == 'i' || ioParam[i] == 'p') && (nodeArgs[i]->option & OPTION_COERCE) != 0) {
00589 args[i] = processCoercion(nodeArgs[i], args[i], coercionTypes[i], env->current, errmsg, newRegion);
00590 if(getNodeType(args[i])==N_ERROR) {
00591 res = (Res *)args[i];
00592 RETURN;
00593 }
00594 }
00595 }
00596 }
00597
00598
00599 if (GlobalREAuditFlag > 0) {
00600 char tmpActStr[MAX_ACTION_SIZE];
00601 functionApplicationToString(tmpActStr,MAX_ACTION_SIZE, fn, args, n);
00602 reDebug(" ExecAction", -4, "", tmpActStr, node, env,rei);
00603 }
00604
00605 if(fd!=NULL) {
00606 switch(getNodeType(fd)) {
00607 case N_FD_DECONSTRUCTOR:
00608 res = deconstruct(fn, args, n, FD_PROJ(fd), errmsg, r);
00609 break;
00610 case N_FD_CONSTRUCTOR:
00611 res = construct(fn, args, n, instantiate(node->exprType, env->current, 1, r), r);
00612 break;
00613 case N_FD_FUNCTION:
00614 res = (Res *) FD_SMSI_FUNC_PTR(fd)(args, n, node, rei, reiSaveFlag, env, errmsg, newRegion);
00615 break;
00616 case N_FD_EXTERNAL:
00617 res = execMicroService3(fn, args, n, node, nEnv, rei, errmsg, newRegion);
00618 break;
00619 case N_FD_RULE_INDEX_LIST:
00620 res = execAction3(fn, args, n, applyAll, node, nEnv, rei, reiSaveFlag, errmsg, newRegion);
00621 break;
00622 default:
00623 res = newErrorRes(r, RE_UNSUPPORTED_AST_NODE_TYPE);
00624 generateAndAddErrMsg("unsupported function descriptor type", node, RE_UNSUPPORTED_AST_NODE_TYPE, errmsg);
00625 RETURN;
00626 }
00627 } else {
00628 res = execMicroService3(fn, args, n, node, nEnv, rei, errmsg, newRegion);
00629 }
00630
00631 if (GlobalREAuditFlag > 0) {
00632 char tmpActStr[MAX_ACTION_SIZE];
00633 functionApplicationToString(tmpActStr,MAX_ACTION_SIZE, fn, args, n);
00634 reDebug(" ExecAction", -4, "Done", tmpActStr, node, env,rei);
00635 }
00636
00637 if(getNodeType(res)==N_ERROR) {
00638 RETURN;
00639 }
00640
00641 for(i=0;i<n;i++) {
00642 Res *resp = NULL;
00643
00644 if(ioParam[i] == 'o' || ioParam[i] == 'p') {
00645 if((appArgs[i]->option & OPTION_COERCE) != 0) {
00646 args[i] = processCoercion(nodeArgs[i], args[i], appArgs[i]->exprType, env->current, errmsg, newRegion);
00647 }
00648 if(getNodeType(args[i])==N_ERROR) {
00649 res = (Res *)args[i];
00650 RETURN ;
00651 }
00652 resp = setVariableValue(appArgs[i]->text, args[i],rei,env,errmsg,r);
00653
00654
00655
00656
00657 }
00658 if(resp!=NULL && getNodeType(resp)==N_ERROR) {
00659 res = resp;
00660 RETURN;
00661 }
00662 }
00663
00664
00665
00666
00667 ret:
00668
00669 cpEnv(env,r);
00670 res = cpRes(res,r);
00671 region_free(newRegion);
00672 return res;
00673
00674 }
00675
00676 Res* attemptToEvaluateVar3(char* vn, Node *node, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r) {
00677 if(vn[0]=='*') {
00678
00679 Res* res0 = (Res *)lookupFromEnv(env, vn);
00680 if(res0==NULL) {
00681 return newUnspecifiedRes(r);
00682 } else {
00683 return res0;
00684 }
00685 } else if(vn[0]=='$') {
00686 Res *res = getSessionVar("",vn,rei, env, errmsg,r);
00687 if(res==NULL) {
00688 return newUnspecifiedRes(r);
00689 } else {
00690 return res;
00691 }
00692 } else {
00693 return NULL;
00694 }
00695 }
00696
00697 Res* evaluateVar3(char* vn, Node *node, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r) {
00698 char buf[ERR_MSG_LEN>1024?ERR_MSG_LEN:1024];
00699 char buf2[ERR_MSG_LEN];
00700 Res *res = attemptToEvaluateVar3(vn, node, rei, reiSaveFlag, env, errmsg, r);
00701 if(res == NULL || TYPE(res) == T_UNSPECED) {
00702 if(vn[0]=='*') {
00703 snprintf(buf, ERR_MSG_LEN, "error: unable to read local variable %s.", vn);
00704 generateErrMsg(buf, NODE_EXPR_POS(node), node->base, buf2);
00705 addRErrorMsg(errmsg, RE_UNABLE_TO_READ_LOCAL_VAR, buf2);
00706
00707 return newErrorRes(r, RE_UNABLE_TO_READ_LOCAL_VAR);
00708 } else if(vn[0]=='$') {
00709 snprintf(buf, ERR_MSG_LEN, "error: unable to read session variable %s.", vn);
00710 generateErrMsg(buf, NODE_EXPR_POS(node), node->base, buf2);
00711 addRErrorMsg(errmsg, RE_UNABLE_TO_READ_SESSION_VAR, buf2);
00712 return newErrorRes(r, RE_UNABLE_TO_READ_SESSION_VAR);
00713 } else {
00714 snprintf(buf, ERR_MSG_LEN, "error: unable to read variable %s.", vn);
00715 generateErrMsg(buf, NODE_EXPR_POS(node), node->base, buf2);
00716 addRErrorMsg(errmsg, RE_UNABLE_TO_READ_VAR, buf2);
00717 return newErrorRes(r, RE_UNABLE_TO_READ_VAR);
00718 }
00719 }
00720 return res;
00721 }
00722
00723
00724
00725
00726
00727 Res* getSessionVar(char *action, char *varName, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r) {
00728 char *varMap;
00729 void *varValue = NULL;
00730 int i, vinx;
00731 varValue = NULL;
00732
00733
00734
00735
00736 vinx = getVarMap(action,varName, &varMap, 0);
00737 while (vinx >= 0) {
00738
00739 i = getVarValue(varMap, rei, (char **)&varValue);
00740
00741 if (i >= 0) {
00742 if (varValue != NULL) {
00743 Res *res = NULL;
00744 FunctionDesc *fd = (FunctionDesc *) lookupFromEnv(ruleEngineConfig.extFuncDescIndex, varMap);
00745 if (fd == NULL) {
00746
00747 res = newStringRes(r, (char *) varValue);
00748 free(varValue);
00749 } else {
00750 ExprType *type = T_FUNC_RET_TYPE(fd->exprType);
00751 switch (getNodeType(type)) {
00752 case T_STRING:
00753 res = newStringRes(r, (char *) varValue);
00754 free(varValue);
00755 break;
00756 case T_INT:
00757 res = newIntRes(r, atoi((char *)varValue));
00758 free(varValue);
00759 break;
00760 case T_DOUBLE:
00761 res = newDoubleRes(r, atof((char *)varValue));
00762 free(varValue);
00763 break;
00764 case T_IRODS:
00765 res = newUninterpretedRes(r, type->text, varValue, NULL);
00766 break;
00767 default:
00768
00769 res = newErrorRes(r, RE_UNSUPPORTED_SESSION_VAR_TYPE);
00770 addRErrorMsg(errmsg, RE_UNSUPPORTED_SESSION_VAR_TYPE, "error: unsupported session variable type");
00771 break;
00772 }
00773 }
00774 free(varMap);
00775 return res;
00776 } else {
00777 return NULL;
00778 }
00779 } else if (i == NULL_VALUE_ERR) {
00780 free(varMap);
00781 vinx = getVarMap(action,varName, &varMap, vinx+1);
00782 } else {
00783 free(varMap);
00784 if (varValue != NULL) free (varValue);
00785 return NULL;
00786 }
00787 }
00788
00789 if (varValue != NULL) free (varValue);
00790 return NULL;
00791 }
00792
00793
00794
00795
00796 Res* execAction3(char *actionName, Res** args, unsigned int nargs, int applyAllRule, Node *node, Env *env, ruleExecInfo_t* rei, int reiSaveFlag, rError_t *errmsg, Region *r)
00797 {
00798 char buf[ERR_MSG_LEN>1024?ERR_MSG_LEN:1024];
00799 char buf2[ERR_MSG_LEN];
00800 char action[MAX_NAME_LEN];
00801 strcpy(action, actionName);
00802 mapExternalFuncToInternalProc2(action);
00803
00804
00805 Res *actionRet = execRule(actionName, args, nargs, applyAllRule, env, rei, reiSaveFlag, errmsg, r);
00806 if( getNodeType(actionRet) == N_ERROR && (
00807 RES_ERR_CODE(actionRet) == NO_RULE_FOUND_ERR ) ) {
00808
00809
00810
00811 eirods::ms_table_entry ms_entry;
00812 int actionInx = actionTableLookUp( ms_entry, action );
00813 if ( actionInx > 0 ) {
00814 snprintf( buf, ERR_MSG_LEN, "error: cannot find rule for action \"%s\" available: %d.", action, availableRules());
00815 generateErrMsg(buf, NODE_EXPR_POS(node), node->base, buf2);
00816 addRErrorMsg(errmsg, NO_RULE_OR_MSI_FUNCTION_FOUND_ERR, buf2);
00817
00818 return execMicroService3(action, args, nargs, node, env, rei, errmsg, r);
00819 } else {
00820 return newErrorRes( r, NO_RULE_OR_MSI_FUNCTION_FOUND_ERR );
00821 }
00822 }
00823 else {
00824 return actionRet;
00825 }
00826 }
00827
00828
00829
00830
00831 Res* execMicroService3 (char *msName, Res **args, unsigned int nargs, Node *node, Env *env, ruleExecInfo_t *rei, rError_t *errmsg, Region *r) {
00832 msParamArray_t *origMsParamArray = rei->msParamArray;
00833 funcPtr myFunc = NULL;
00834 int actionInx;
00835 unsigned int numOfStrArgs;
00836 unsigned int i;
00837 int ii;
00838 msParam_t *myArgv[MAX_PARAMS_LEN];
00839 Res *res;
00840
00841
00842 eirods::ms_table_entry ms_entry;
00843 actionInx = actionTableLookUp( ms_entry, msName );
00844
00845 char errbuf[ERR_MSG_LEN];
00846 if (actionInx < 0) {
00847 int ret = NO_MICROSERVICE_FOUND_ERR;
00848 generateErrMsg("execMicroService3: no micro service found", NODE_EXPR_POS(node), node->base, errbuf);
00849 addRErrorMsg(errmsg, ret, errbuf);
00850 return newErrorRes(r, ret);
00851
00852 }
00853
00854 myFunc = ms_entry.call_action_;
00855 numOfStrArgs = ms_entry.num_args_;
00856 if (nargs != numOfStrArgs) {
00857 int ret = ACTION_ARG_COUNT_MISMATCH;
00858 generateErrMsg("execMicroService3: wrong number of arguments", NODE_EXPR_POS(node), node->base, errbuf);
00859 addRErrorMsg(errmsg, ret, errbuf);
00860 return newErrorRes(r, ret);
00861 }
00862
00863
00864
00865 int fillInParamLabel = node->degree == 2 && node->subtrees[1]->degree == (int) numOfStrArgs;
00866 for (i = 0; i < numOfStrArgs; i++) {
00867 myArgv[i] = (msParam_t *)malloc(sizeof(msParam_t));
00868 Res *res = args[i];
00869 if(res != NULL) {
00870 int ret =
00871 convertResToMsParam(myArgv[i], res, errmsg);
00872 myArgv[i]->label = fillInParamLabel && isVariableNode(node->subtrees[1]->subtrees[i]) ? strdup(node->subtrees[1]->subtrees[i]->text) : NULL;
00873 if(ret!=0) {
00874 generateErrMsg("execMicroService3: error converting arguments to MsParam", NODE_EXPR_POS(node->subtrees[i]), node->subtrees[i]->base, errbuf);
00875 addRErrorMsg(errmsg, ret, errbuf);
00876 int j = i;
00877 for(;j>=0;j--) {
00878 if(TYPE(args[j])!=T_IRODS) {
00879 free(myArgv[j]->inOutStruct);
00880 myArgv[j]->inOutStruct = NULL;
00881 }
00882 free(myArgv[j]->label);
00883 free(myArgv[j]->type);
00884 free(myArgv[j]);
00885 }
00886 return newErrorRes(r, ret);
00887 }
00888 } else {
00889 myArgv[i]->inOutStruct = NULL;
00890 myArgv[i]->inpOutBuf = NULL;
00891 myArgv[i]->type = strdup(STR_MS_T);
00892 }
00893
00894
00895 }
00896
00897 rei->msParamArray = newMsParamArray();
00898 int ret = convertEnvToMsParamArray(rei->msParamArray, env, errmsg, r);
00899 if(ret!=0) {
00900 generateErrMsg("execMicroService3: error converting env to MsParamArray", NODE_EXPR_POS(node), node->base, errbuf);
00901 addRErrorMsg(errmsg, ret, errbuf);
00902 res = newErrorRes(r,ret);
00903 RETURN;
00904 }
00905
00906 if (GlobalREAuditFlag > 0) {
00907 char tmpActStr[MAX_ACTION_SIZE];
00908 functionApplicationToString(tmpActStr,MAX_ACTION_SIZE, msName, args, nargs);
00909 reDebug(" ExecMicroSrvc", -4, "", tmpActStr, node, env,rei);
00910 }
00911
00912 if (numOfStrArgs == 0)
00913 ii = (*(int (*)(ruleExecInfo_t *))myFunc) (rei) ;
00914 else if (numOfStrArgs == 1)
00915 ii = (*(int (*)(msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],rei);
00916 else if (numOfStrArgs == 2)
00917 ii = (*(int (*)(msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],rei);
00918 else if (numOfStrArgs == 3)
00919 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],rei);
00920 else if (numOfStrArgs == 4)
00921 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],rei);
00922 else if (numOfStrArgs == 5)
00923 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],myArgv[4],rei);
00924 else if (numOfStrArgs == 6)
00925 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],myArgv[4],myArgv[5],rei);
00926 else if (numOfStrArgs == 7)
00927 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],myArgv[4],myArgv[5],myArgv[6],rei);
00928 else if (numOfStrArgs == 8)
00929 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],myArgv[4],myArgv[5],myArgv[6],myArgv[7],rei);
00930 else if (numOfStrArgs == 9)
00931 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],myArgv[4],myArgv[5],myArgv[6],myArgv[7],myArgv[8],rei);
00932 else if (numOfStrArgs == 10)
00933 ii = (*(int (*)(msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, msParam_t *, ruleExecInfo_t *))myFunc) (myArgv[0],myArgv[1],myArgv[2],myArgv[3],myArgv[4],myArgv[5],myArgv[6],myArgv[7],
00934 myArgv[8],myArgv [9],rei);
00935 if(ii<0) {
00936 res = newErrorRes(r, ii);
00937 RETURN;
00938 }
00939
00940 ret = updateMsParamArrayToEnvAndFreeNonIRODSType(rei->msParamArray, env, errmsg, r);
00941 if(ret!=0) {
00942 generateErrMsg("execMicroService3: error env from MsParamArray", NODE_EXPR_POS(node), node->base, errbuf);
00943 addRErrorMsg(errmsg, ret, errbuf);
00944 res = newErrorRes(r, ret);
00945 RETURN;
00946 }
00947
00948 for (i = 0; i < numOfStrArgs; i++) {
00949 if(myArgv[i] != NULL) {
00950 int ret =
00951 convertMsParamToResAndFreeNonIRODSType(myArgv[i], args[i], errmsg, r);
00952 if(ret!=0) {
00953 generateErrMsg("execMicroService3: error converting arguments from MsParam", NODE_EXPR_POS(node), node->base, errbuf);
00954 addRErrorMsg(errmsg, ret, errbuf);
00955 res= newErrorRes(r, ret);
00956 RETURN;
00957 }
00958 } else {
00959 args[i] = NULL;
00960 }
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970 res = newIntRes(r, ii);
00971 ret:
00972 if(rei->msParamArray!=NULL) {
00973 deleteMsParamArray(rei->msParamArray);
00974 }
00975 rei->msParamArray = origMsParamArray;
00976 for(i=0;i<numOfStrArgs;i++) {
00977 if(TYPE(args[i])!=T_IRODS && myArgv[i]->inOutStruct!=NULL) {
00978 free(myArgv[i]->inOutStruct);
00979 }
00980 free(myArgv[i]->label);
00981 free(myArgv[i]->type);
00982 free(myArgv[i]);
00983 }
00984 if(getNodeType(res)==N_ERROR) {
00985 generateErrMsg("execMicroService3: error when executing microservice", NODE_EXPR_POS(node), node->base, errbuf);
00986 addRErrorMsg(errmsg, RES_ERR_CODE(res), errbuf);
00987 }
00988 return res;
00989 }
00990
00991 Res* execRuleFromCondIndex(char *ruleName, Res **args, int argc, CondIndexVal *civ, int applyAll, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r) {
00992
00993 Res *status;
00994 Env *envNew = newEnv(newHashTable2(10, r), globalEnv(env), env, r);
00995 RuleDesc *rd;
00996 Node* rule = NULL;
00997 RuleIndexListNode *indexNode = NULL;
00998 Res* res = NULL;
00999
01000
01001 if(civ->params->degree != argc) {
01002 char buf[ERR_MSG_LEN];
01003 snprintf(buf, ERR_MSG_LEN, "error: cannot apply rule %s from rule conditional index because of wrong number of arguments, declared %d, supplied %d.", ruleName, civ->params->degree, argc);
01004 addRErrorMsg(errmsg, ACTION_ARG_COUNT_MISMATCH, buf);
01005 return newErrorRes(r, ACTION_ARG_COUNT_MISMATCH);
01006 }
01007
01008 int i = initializeEnv(civ->params,args,argc, envNew->current,r);
01009 if (i != 0) {
01010 status = newErrorRes(r, i);
01011 RETURN;
01012 }
01013
01014 res = evaluateExpression3(civ->condExp, 0, 0, rei, reiSaveFlag, envNew, errmsg, r);
01015 if(getNodeType(res) == N_ERROR) {
01016 status = res;
01017 RETURN;
01018 }
01019 if(TYPE(res) != T_STRING) {
01020
01021 addRErrorMsg(errmsg, RE_DYNAMIC_TYPE_ERROR, "error: the lhs of indexed rule condition does not evaluate to a string");
01022 status = newErrorRes(r, RE_DYNAMIC_TYPE_ERROR);
01023 RETURN;
01024 }
01025
01026 indexNode = (RuleIndexListNode *)lookupFromHashTable(civ->valIndex, res->text);
01027 if(indexNode == NULL) {
01028 #ifndef DEBUG
01029 rodsLog (LOG_NOTICE,"applyRule Failed for action 1: %s with status %i",ruleName, NO_MORE_RULES_ERR);
01030 #endif
01031 status = newErrorRes(r, NO_MORE_RULES_ERR);
01032 RETURN;
01033 }
01034
01035 rd = getRuleDesc(indexNode->ruleIndex);
01036
01037 if(rd->ruleType != RK_REL && rd->ruleType != RK_FUNC) {
01038 #ifndef DEBUG
01039 rodsLog (LOG_NOTICE,"applyRule Failed for action 1: %s with status %i",ruleName, NO_MORE_RULES_ERR);
01040 #endif
01041 status = newErrorRes(r, NO_MORE_RULES_ERR);
01042 RETURN;
01043 }
01044
01045 rule = rd->node;
01046
01047 status = execRuleNodeRes(rule, args, argc, applyAll > 1? applyAll : 0, env, rei, reiSaveFlag, errmsg, r);
01048
01049 if (getNodeType(status) == N_ERROR) {
01050 rodsLog (LOG_NOTICE,"applyRule Failed for action : %s with status %i",ruleName, RES_ERR_CODE(status));
01051 }
01052
01053 ret:
01054
01055 return status;
01056
01057
01058 }
01059
01060
01061
01062
01063
01064 Res *execRule(char *ruleNameInp, Res** args, unsigned int argc, int applyAllRuleInp, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
01065 {
01066 int ruleInx = 0, statusI;
01067 Res *statusRes = NULL;
01068 int inited = 0;
01069 ruleExecInfo_t *saveRei;
01070 int reTryWithoutRecovery = 0;
01071 char ruleName[MAX_NAME_LEN];
01072 int applyAllRule = applyAllRuleInp;
01073
01074 #ifdef DEBUG
01075 char buf[1024];
01076 snprintf(buf, 1024, "execRule: %s\n", ruleNameInp);
01077 writeToTmp("entry.log", buf);
01078 #endif
01079
01080 ruleInx = 0;
01081 strcpy(ruleName, ruleNameInp);
01082 mapExternalFuncToInternalProc2(ruleName);
01083
01084 RuleIndexListNode *ruleIndexListNode;
01085 int success = 0;
01086 int first = 1;
01087 while (1) {
01088 statusI = findNextRule2(ruleName, ruleInx, &ruleIndexListNode);
01089
01090 if (statusI != 0) {
01091 if(applyAllRule == 0) {
01092 #ifndef DEBUG
01093 rodsLog (LOG_NOTICE,"applyRule Failed for action 1: %s with status %i",ruleName, statusI);
01094 #endif
01095 statusRes = statusRes == NULL ? newErrorRes(r, NO_RULE_FOUND_ERR) : statusRes;
01096 } else {
01097 success = 1;
01098 }
01099 break;
01100 }
01101 if (reiSaveFlag == SAVE_REI) {
01102 int statusCopy = 0;
01103 if (inited == 0) {
01104 saveRei = (ruleExecInfo_t *) mallocAndZero(sizeof (ruleExecInfo_t));
01105 statusCopy = copyRuleExecInfo(rei, saveRei);
01106 inited = 1;
01107 } else if (reTryWithoutRecovery == 0) {
01108 statusCopy = copyRuleExecInfo(saveRei, rei);
01109 }
01110 if(statusCopy != 0) {
01111 statusRes = newErrorRes(r, statusCopy);
01112 break;
01113 }
01114 }
01115
01116 if(!first) {
01117 addRErrorMsg(errmsg, statusI, ERR_MSG_SEP);
01118 } else {
01119 first = 0;
01120 }
01121
01122 if(ruleIndexListNode->secondaryIndex) {
01123 statusRes = execRuleFromCondIndex(ruleName, args, argc, ruleIndexListNode->condIndex, applyAllRule, env, rei, reiSaveFlag, errmsg, r);
01124 } else {
01125
01126 RuleDesc *rd = getRuleDesc(ruleIndexListNode->ruleIndex);
01127 if(rd->ruleType == RK_REL || rd->ruleType == RK_FUNC) {
01128
01129 Node* rule = rd->node;
01130 unsigned int inParamsCount = RULE_NODE_NUM_PARAMS(rule);
01131 if (inParamsCount != argc) {
01132 ruleInx++;
01133 continue;
01134 }
01135
01136 if (GlobalREAuditFlag > 0)
01137 reDebug(" GotRule", ruleInx, "", ruleName, NULL, env, rei);
01138 #ifndef DEBUG
01139 if (reTestFlag > 0) {
01140 if (reTestFlag == COMMAND_TEST_1)
01141 fprintf(stdout, "+Testing Rule Number:%i for Action:%s\n", ruleInx, ruleName);
01142 else if (reTestFlag == HTML_TEST_1)
01143 fprintf(stdout, "+Testing Rule Number:<FONT COLOR=#FF0000>%i</FONT> for Action:<FONT COLOR=#0000FF>%s</FONT><BR>\n", ruleInx, ruleName);
01144 else if (rei != 0 && rei->rsComm != 0 && &(rei->rsComm->rError) != 0)
01145 rodsLog(LOG_NOTICE, "+Testing Rule Number:%i for Action:%s\n", ruleInx, ruleName);
01146 }
01147 #endif
01148
01149
01150 statusRes = execRuleNodeRes(rule, args, argc, applyAllRule > 1? applyAllRule : 0, env, rei, reiSaveFlag, errmsg, r);
01151
01152 }
01153 }
01154 if(getNodeType(statusRes)!=N_ERROR) {
01155 success = 1;
01156 if (applyAllRule == 0) {
01157 break;
01158 } else {
01159 if (reiSaveFlag == SAVE_REI) {
01160 freeRuleExecInfoStruct(saveRei, 0);
01161 inited = 0;
01162 }
01163 }
01164 } else if(RES_ERR_CODE(statusRes)== RETRY_WITHOUT_RECOVERY_ERR) {
01165 reTryWithoutRecovery = 1;
01166 } else if(RES_ERR_CODE(statusRes)== CUT_ACTION_PROCESSED_ERR) {
01167 break;
01168 }
01169
01170 ruleInx++;
01171 }
01172
01173 if (inited == 1) {
01174 freeRuleExecInfoStruct(saveRei, 0);
01175 }
01176
01177 if(success) {
01178 if(applyAllRule) {
01179
01180 return newIntRes(r, 0);
01181 } else if(TYPE(statusRes) == T_SUCCESS) {
01182 return newIntRes(r, 0);
01183 } else {
01184 return statusRes;
01185 }
01186 } else {
01187 #ifndef DEBUG
01188 rodsLog (LOG_NOTICE,"applyRule Failed for action 2: %s with status %i",ruleName, RES_ERR_CODE(statusRes));
01189 #endif
01190 return statusRes;
01191 }
01192 }
01193 void copyFromEnv(Res **args, char **inParams, int inParamsCount, Hashtable *env, Region *r) {
01194 int i;
01195 for(i=0;i<inParamsCount;i++) {
01196 args[i]= cpRes((Res *)lookupFromHashTable(env, inParams[i]),r);
01197 }
01198 }
01199
01200
01201
01202
01203 Res* execRuleNodeRes(Node *rule, Res** args, unsigned int argc, int applyAll, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
01204 {
01205 if (GlobalREAuditFlag > 0)
01206 reDebug(" ExecRule", -4, "", RULE_NAME(rule), NULL, env, rei);
01207 Node* ruleCondition = rule->subtrees[1];
01208 Node* ruleAction = rule->subtrees[2];
01209 Node* ruleRecovery = rule->subtrees[3];
01210 Node* ruleHead = rule->subtrees[0];
01211 Node** paramsNodes = ruleHead->subtrees[0]->subtrees;
01212 char* paramsNames[MAX_NUM_OF_ARGS_IN_ACTION];
01213 unsigned int inParamsCount = RULE_NODE_NUM_PARAMS(rule);
01214 Res *statusRes;
01215
01216 if(inParamsCount != argc) {
01217 generateAndAddErrMsg("error: action argument count mismatch", rule, ACTION_ARG_COUNT_MISMATCH, errmsg);
01218 return newErrorRes(r, ACTION_ARG_COUNT_MISMATCH);
01219
01220 }
01221 unsigned int k;
01222 for (k = 0; k < inParamsCount ; k++) {
01223 paramsNames[k] = paramsNodes[k]->text;
01224 }
01225
01226 Env *global = globalEnv(env);
01227 Region *rNew = make_region(0, NULL);
01228 Env *envNew = newEnv(newHashTable2(10, rNew), global, env, rNew);
01229
01230 int statusInitEnv;
01231
01232 statusInitEnv = initializeEnv(ruleHead->subtrees[0],args,argc, envNew->current,rNew);
01233 if (statusInitEnv != 0)
01234 return newErrorRes(r, statusInitEnv);
01235
01236 Res *res = evaluateExpression3(ruleCondition, 0, 0, rei, reiSaveFlag, envNew, errmsg, rNew);
01237
01238 if (getNodeType(res) != N_ERROR && TYPE(res)==T_BOOL && RES_BOOL_VAL(res)!=0) {
01239 #ifndef DEBUG
01240 #if 0
01241 if (reTestFlag > 0) {
01242 if (reTestFlag == COMMAND_TEST_1)
01243 fprintf(stdout,"+Executing Rule Number:%i for Action:%s\n",ruleInx,ruleName);
01244 else if (reTestFlag == HTML_TEST_1)
01245 fprintf(stdout,"+Executing Rule Number:<FONT COLOR=#FF0000>%i</FONT> for Action:<FONT COLOR=#0000FF>%s</FONT><BR>\n",ruleInx,ruleName);
01246 else
01247 rodsLog (LOG_NOTICE,"+Executing Rule Number:%i for Action:%s\n",ruleInx,ruleName);
01248 }
01249 #endif
01250 #endif
01251 if(getNodeType(ruleAction) == N_ACTIONS) {
01252 statusRes = evaluateActions(ruleAction, ruleRecovery, applyAll, rei, reiSaveFlag, envNew, errmsg,rNew);
01253 } else {
01254 statusRes = evaluateExpression3(ruleAction, applyAll, 0, rei, reiSaveFlag, envNew, errmsg, rNew);
01255 }
01256
01257 copyFromEnv(args, paramsNames, inParamsCount, envNew->current, r);
01258
01259 statusRes = cpRes(statusRes, r);
01260
01261 if (getNodeType(statusRes) == N_ERROR) {
01262 #ifndef DEBUG
01263 rodsLog (LOG_NOTICE,"applyRule Failed for action 2: %s with status %i",ruleHead->text, RES_ERR_CODE(statusRes));
01264 #endif
01265 }
01266 } else {
01267 if(getNodeType(res)!=N_ERROR && TYPE(res)!=T_BOOL) {
01268 char buf[ERR_MSG_LEN];
01269 generateErrMsg("error: the rule condition does not evaluate to a boolean value", NODE_EXPR_POS(ruleCondition), ruleCondition->base, buf);
01270 addRErrorMsg(errmsg, RE_TYPE_ERROR, buf);
01271 }
01272 statusRes = newErrorRes(r, RULE_FAILED_ERR);
01273 }
01274
01275 cpEnv(global, r);
01276
01277 region_free(rNew);
01278 if (GlobalREAuditFlag > 0)
01279 reDebug(" ExecRule", -4, "Done", RULE_NAME(rule), NULL, env, rei);
01280 return statusRes;
01281
01282 }
01283
01284 Res* matchPattern(Node *pattern, Node *val, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r) {
01285 char errbuf[ERR_MSG_LEN];
01286 char *localErrorMsg = NULL;
01287 Node *p = pattern, *v = val;
01288 Res *res;
01289 char *varName;
01290 char matcherName[MAX_NAME_LEN];
01291 switch (getNodeType(pattern)) {
01292 case N_APPLICATION:
01293 matcherName[0]='~';
01294 strcpy(matcherName+1, pattern->subtrees[0]->text);
01295 RuleIndexListNode *node;
01296 if(findNextRule2(matcherName, 0, &node) == 0) {
01297 v = execRule(matcherName, &val, 1, 0, env, rei, reiSaveFlag, errmsg, r);
01298 RE_ERROR2(getNodeType(v) == N_ERROR, "user defined pattern function error");
01299 if(getNodeType(v)!=N_TUPLE) {
01300 Res **tupleComp = (Res **)region_alloc(r, sizeof(Res *));
01301 *tupleComp = v;
01302 v = newTupleRes(1, tupleComp ,r);
01303 }
01304 } else {
01305 RE_ERROR2(v->text == NULL || strcmp(pattern->subtrees[0]->text, v->text)!=0, "pattern mismatch constructor");
01306 Res **tupleComp = (Res **)region_alloc(r, sizeof(Res *) * v->degree);
01307 memcpy(tupleComp, v->subtrees, sizeof(Res *) * v->degree);
01308 v = newTupleRes(v->degree, tupleComp ,r);
01309 }
01310 res = matchPattern(p->subtrees[1], v, env, rei, reiSaveFlag, errmsg, r);
01311 return res;
01312 case TK_VAR:
01313 varName = pattern->text;
01314 if(varName[0] == '*') {
01315 if(lookupFromEnv(env, varName)==NULL) {
01316
01317 if(insertIntoHashTable(env->current, varName, val) == 0) {
01318 snprintf(errbuf, ERR_MSG_LEN, "error: unable to write to local variable \"%s\".",varName);
01319 addRErrorMsg(errmsg, RE_UNABLE_TO_WRITE_LOCAL_VAR, errbuf);
01320 return newErrorRes(r, RE_UNABLE_TO_WRITE_LOCAL_VAR);
01321 }
01322 } else {
01323 updateInEnv(env, varName, val);
01324 }
01325 } else if(varName[0] == '$') {
01326 return setVariableValue(varName, val, rei, env, errmsg, r);
01327 }
01328 return newIntRes(r, 0);
01329
01330 case N_TUPLE:
01331 RE_ERROR2(getNodeType(v) != N_TUPLE, "pattern mismatch value is not a tuple.");
01332 RE_ERROR2(p->degree != v->degree, "pattern mismatch arity");
01333 int i;
01334 for(i=0;i<p->degree;i++) {
01335 Res *res = matchPattern(p->subtrees[i], v->subtrees[i], env, rei, reiSaveFlag, errmsg, r);
01336 if(getNodeType(res) == N_ERROR) {
01337 return res;
01338 }
01339 }
01340 return newIntRes(r, 0);
01341 case TK_STRING:
01342 RE_ERROR2(getNodeType(v) != N_VAL || TYPE(v) != T_STRING, "pattern mismatch value is not a string.");
01343 RE_ERROR2(strcmp(pattern->text, v->text)!=0 , "pattern mismatch string.");
01344 return newIntRes(r, 0);
01345 case TK_BOOL:
01346 RE_ERROR2(getNodeType(v) != N_VAL || TYPE(v) != T_BOOL, "pattern mismatch value is not a boolean.");
01347 res = evaluateExpression3(pattern, 0, 0, rei, reiSaveFlag, env, errmsg, r);
01348 CASCADE_N_ERROR(res);
01349 RE_ERROR2(RES_BOOL_VAL(res) != RES_BOOL_VAL(v) , "pattern mismatch boolean.");
01350 return newIntRes(r, 0);
01351 case TK_INT:
01352 RE_ERROR2(getNodeType(v) != N_VAL || (TYPE(v) != T_INT && TYPE(v) != T_DOUBLE), "pattern mismatch value is not an integer.");
01353 res = evaluateExpression3(pattern, 0, 0, rei, reiSaveFlag, env, errmsg, r);
01354 CASCADE_N_ERROR(res);
01355 RE_ERROR2(atoi(res->text) != (TYPE(v) == T_INT ? RES_INT_VAL(v) : RES_DOUBLE_VAL(v)) , "pattern mismatch integer.");
01356 return newIntRes(r, 0);
01357 case TK_DOUBLE:
01358 RE_ERROR2(getNodeType(v) != N_VAL || (TYPE(v) != T_DOUBLE && TYPE(v) != T_INT), "pattern mismatch value is not a double.");
01359 res = evaluateExpression3(pattern, 0, 0, rei, reiSaveFlag, env, errmsg, r);
01360 CASCADE_N_ERROR(res);
01361 RE_ERROR2(atof(res->text) != (TYPE(v) == T_DOUBLE ? RES_DOUBLE_VAL(v) : RES_INT_VAL(v)), "pattern mismatch integer.");
01362 return newIntRes(r, 0);
01363 default:
01364 RE_ERROR2(1, "malformatted pattern error");
01365 break;
01366 }
01367 error:
01368 generateErrMsg(localErrorMsg,NODE_EXPR_POS(pattern), pattern->base, errbuf);
01369 addRErrorMsg(errmsg, RE_PATTERN_NOT_MATCHED, errbuf);
01370 return newErrorRes(r, RE_PATTERN_NOT_MATCHED);
01371
01372 }
01373
01374
01375
01376
01377
01378
01379