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