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