00001
00002
00003 #include <sys/stat.h>
00004 #include <time.h>
00005 #include "configuration.h"
00006 #include "utils.h"
00007 #include "rules.h"
00008 #include "index.h"
00009 #include "cache.h"
00010 #include "region.h"
00011 #include "functions.h"
00012 #include "filesystem.h"
00013 #include "sharedmemory.h"
00014 #include "icatHighLevelRoutines.h"
00015 #include "modAVUMetadata.h"
00016 #ifdef DEBUG
00017 #include "re.h"
00018 #endif
00019 Cache ruleEngineConfig = {
00020 NULL,
00021 NULL,
00022 0,
00023 0,
00024 UNINITIALIZED,
00025 UNINITIALIZED,
00026 UNINITIALIZED,
00027 UNINITIALIZED,
00028 UNINITIALIZED,
00029 UNINITIALIZED,
00030 UNINITIALIZED,
00031 UNINITIALIZED,
00032 UNINITIALIZED,
00033 UNINITIALIZED,
00034 UNINITIALIZED,
00035 UNINITIALIZED,
00036 UNINITIALIZED,
00037 NULL,
00038 NULL,
00039 NULL,
00040 NULL,
00041 NULL,
00042 NULL,
00043 NULL,
00044 NULL,
00045 NULL,
00046 NULL,
00047 NULL,
00048 0,
00049 0,
00050 time_type_initializer,
00051 time_type_initializer,
00052 0,
00053 0,
00054 "",
00055 };
00056
00057 void removeRuleFromExtIndex(char *ruleName, int i) {
00058 if(isComponentInitialized(ruleEngineConfig.extFuncDescIndexStatus)) {
00059 FunctionDesc *fd = (FunctionDesc *)lookupFromHashTable(ruleEngineConfig.extFuncDescIndex->current, ruleName);
00060 RuleIndexList *rd = FD_RULE_INDEX_LIST(fd);
00061 removeNodeFromRuleIndexList2(rd, i);
00062 if(rd->head == NULL) {
00063 deleteFromHashTable(ruleEngineConfig.extFuncDescIndex->current, ruleName);
00064 }
00065 }
00066
00067 }
00068 void appendRuleIntoExtIndex(RuleDesc *rule, int i, Region *r) {
00069 FunctionDesc *fd = (FunctionDesc *)lookupFromHashTable(ruleEngineConfig.extFuncDescIndex->current, RULE_NAME(rule->node));
00070 RuleIndexList *rd;
00071 if(fd == NULL) {
00072 rd = newRuleIndexList(RULE_NAME(rule->node), i, r);
00073 fd = newRuleIndexListFD(rd, NULL, r);
00074
00075 insertIntoHashTable(ruleEngineConfig.extFuncDescIndex->current, RULE_NAME(rule->node), fd);
00076 } else {
00077 if(getNodeType(fd)==N_FD_RULE_INDEX_LIST) {
00078 rd = FD_RULE_INDEX_LIST(fd);
00079 appendRuleNodeToRuleIndexList(rd, i ,r);
00080 } else if(getNodeType(fd) == N_FD_EXTERNAL) {
00081
00082 updateInHashTable(ruleEngineConfig.extFuncDescIndex->current, RULE_NAME(rule->node), newRuleIndexListFD(newRuleIndexList(RULE_NAME(rule->node), i, r),fd->exprType, r));
00083 } else {
00084
00085 }
00086 }
00087 }
00088
00089 void prependRuleIntoAppIndex(RuleDesc *rule, int i, Region *r) {
00090 RuleIndexList *rd;
00091 FunctionDesc *fd = (FunctionDesc *)lookupFromHashTable(ruleEngineConfig.appFuncDescIndex->current, RULE_NAME(rule->node));
00092 if(fd == NULL) {
00093 rd = newRuleIndexList(RULE_NAME(rule->node), i, r);
00094 fd = newRuleIndexListFD(rd, NULL, r);
00095 insertIntoHashTable(ruleEngineConfig.appFuncDescIndex->current, RULE_NAME(rule->node), fd);
00096 } else {
00097 rd = FD_RULE_INDEX_LIST(fd);
00098 prependRuleNodeToRuleIndexList(rd, i ,r);
00099 }
00100 }
00101 int checkPointExtRuleSet(Region *r) {
00102 ruleEngineConfig.extFuncDescIndex = newEnv(newHashTable2(100, r), ruleEngineConfig.extFuncDescIndex, NULL, r);
00103 return ruleEngineConfig.extRuleSet->len;
00104 }
00105
00106
00107
00108
00109
00110 void prependAppRule(RuleDesc *rd, Region *r) {
00111 int i = ruleEngineConfig.appRuleSet->len++;
00112 ruleEngineConfig.appRuleSet->rules[i] = rd;
00113 prependRuleIntoAppIndex(rd, i, r);
00114 }
00115 void popExtRuleSet(int checkPoint) {
00116
00117
00118
00119
00120 Env *temp = ruleEngineConfig.extFuncDescIndex;
00121 ruleEngineConfig.extFuncDescIndex = temp->previous;
00122
00123 ruleEngineConfig.extRuleSet->len = checkPoint;
00124 }
00125 RuleEngineStatus getRuleEngineStatus() {
00126 return ruleEngineConfig.ruleEngineStatus;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 int clearResources(int resources) {
00141 clearFuncDescIndex(APP, app);
00142 clearFuncDescIndex(SYS, sys);
00143 clearFuncDescIndex(CORE, core);
00144 clearFuncDescIndex(EXT, ext);
00145 clearRegion(APP, app);
00146 clearRegion(SYS, sys);
00147 clearRegion(CORE, core);
00148 clearRegion(EXT, ext);
00149 clearRuleSet(APP, app);
00150 clearRuleSet(CORE, core);
00151 clearRuleSet(EXT, ext);
00152
00153 if((resources & RESC_CACHE) && isComponentAllocated(ruleEngineConfig.cacheStatus)) {
00154 free(ruleEngineConfig.address);
00155 ruleEngineConfig.address = NULL;
00156 ruleEngineConfig.cacheStatus = UNINITIALIZED;
00157 }
00158 return 0;
00159 }
00160 List hashtablesToClear = {0, NULL, NULL};
00161 List envToClear = {0, NULL, NULL};
00162 List regionsToClear = {0, NULL, NULL};
00163 List memoryToFree = {0, NULL, NULL};
00164
00165 void delayClearResources(int resources) {
00166
00167
00168
00169
00170
00171
00172
00173
00174 delayClearRegion(APP, app);
00175 delayClearRegion(SYS, sys);
00176 delayClearRegion(CORE, core);
00177 delayClearRegion(EXT, ext);
00178 delayClearRuleSet(APP, app);
00179 delayClearRuleSet(CORE, core);
00180 delayClearRuleSet(EXT, ext);
00181 delayClearFuncDescIndex(APP, app);
00182 delayClearFuncDescIndex(SYS, sys);
00183 delayClearFuncDescIndex(CORE, core);
00184 delayClearFuncDescIndex(EXT, ext);
00185
00186 if((resources & RESC_CACHE) && ruleEngineConfig.cacheStatus == INITIALIZED) {
00187 listAppendNoRegion(&memoryToFree, ruleEngineConfig.address);
00188 ruleEngineConfig.cacheStatus = UNINITIALIZED;
00189 }
00190 }
00191
00192 void clearDelayed() {
00193 ListNode *n = envToClear.head;
00194 while(n!=NULL) {
00195
00196 listRemoveNoRegion(&envToClear, n);
00197 n = envToClear.head;
00198 }
00199 n = hashtablesToClear.head;
00200 while(n!=NULL) {
00201 deleteHashTable((Hashtable *) n->value, nop);
00202 listRemoveNoRegion(&hashtablesToClear, n);
00203 n = hashtablesToClear.head;
00204 }
00205 n = regionsToClear.head;
00206 while(n!=NULL) {
00207 region_free((Region *) n->value);
00208 listRemoveNoRegion(®ionsToClear, n);
00209 n = regionsToClear.head;
00210 }
00211 n = memoryToFree.head;
00212 while(n!=NULL) {
00213 free(n->value);
00214 listRemoveNoRegion(&memoryToFree, n);
00215 n = memoryToFree.head;
00216 }
00217 }
00218
00219 void setCacheAddress(unsigned char *addr, RuleEngineStatus status, long size) {
00220 ruleEngineConfig.address = addr;
00221 ruleEngineConfig.cacheStatus = status;
00222 ruleEngineConfig.cacheSize = size;
00223
00224 }
00225
00226 int generateLocalCache() {
00227 unsigned char *buf = NULL;
00228 if(ruleEngineConfig.cacheStatus == INITIALIZED) {
00229 free(ruleEngineConfig.address);
00230 }
00231 buf = (unsigned char *)malloc(SHMMAX);
00232 if(buf == NULL) {
00233 return RE_OUT_OF_MEMORY;
00234 }
00235 setCacheAddress(buf, INITIALIZED, SHMMAX);
00236 return 0;
00237 }
00238 int generateFunctionDescriptionTables() {
00239 createFuncDescIndex(SYS, sys);
00240 createFuncDescIndex(CORE, core);
00241 createFuncDescIndex(APP, app);
00242 if(!isComponentInitialized(ruleEngineConfig.extFuncDescIndexStatus)) {
00243 createFuncDescIndex(EXT, ext);
00244 ruleEngineConfig.extFuncDescIndex->previous = ruleEngineConfig.appFuncDescIndex;
00245 } else {
00246 Env *extEnv = ruleEngineConfig.extFuncDescIndex;
00247 while(extEnv->previous!= NULL) {
00248 extEnv = extEnv->previous;
00249 }
00250 extEnv->previous = ruleEngineConfig.appFuncDescIndex;
00251 }
00252 ruleEngineConfig.appFuncDescIndex->previous = ruleEngineConfig.coreFuncDescIndex;
00253 ruleEngineConfig.coreFuncDescIndex->previous = ruleEngineConfig.sysFuncDescIndex;
00254
00255 return 0;
00256 }
00257 void generateRuleSets() {
00258 createRuleSet(APP, app);
00259 createRuleSet(CORE, core);
00260 createRuleSet(EXT, ext);
00261 }
00262 void generateRegions() {
00263 createRegion(APP, app);
00264 createRegion(CORE, core);
00265 createRegion(SYS, sys);
00266 createRegion(EXT, ext);
00267 }
00268 int unlinkFuncDescIndex() {
00269 Env *extEnv = ruleEngineConfig.extFuncDescIndex;
00270 while(extEnv->previous != ruleEngineConfig.appFuncDescIndex) {
00271 extEnv = extEnv->previous;
00272 }
00273 extEnv->previous = NULL;
00274 ruleEngineConfig.appFuncDescIndex->previous = NULL;
00275 ruleEngineConfig.coreFuncDescIndex->previous = NULL;
00276 return 0;
00277 }
00278 int clearRuleIndex(ruleStruct_t *inRuleStruct) {
00279 if(inRuleStruct == &coreRuleStrct) {
00280 clearResources(RESC_CORE_FUNC_DESC_INDEX);
00281 } else if(inRuleStruct == &appRuleStrct) {
00282 clearResources(RESC_APP_FUNC_DESC_INDEX);
00283 }
00284 return 0;
00285 }
00286
00287
00288 int createRuleIndex(ruleStruct_t *inRuleStruct) {
00289 if(inRuleStruct == &coreRuleStrct) {
00290 createRuleNodeIndex(ruleEngineConfig.coreRuleSet, ruleEngineConfig.coreFuncDescIndex->current, CORE_RULE_INDEX_OFF, ruleEngineConfig.coreRegion);
00291 createCondIndex(ruleEngineConfig.coreRegion);
00292 } else if(inRuleStruct == &appRuleStrct) {
00293 createRuleNodeIndex(ruleEngineConfig.appRuleSet, ruleEngineConfig.appFuncDescIndex->current, APP_RULE_INDEX_OFF, ruleEngineConfig.appRegion);
00294 }
00295 return 0;
00296
00297 }
00298
00299 int loadRuleFromCacheOrFile(int processType, char *irbSet, ruleStruct_t *inRuleStruct) {
00300 char r1[NAME_LEN], r2[RULE_SET_DEF_LENGTH], r3[RULE_SET_DEF_LENGTH];
00301 rstrcpy(r2, irbSet, RULE_SET_DEF_LENGTH);
00302 int res = 0;
00303
00304 #ifdef DEBUG
00305
00306 #endif
00307
00308
00309 char fn[MAX_NAME_LEN];
00310 time_type timestamp = time_type_initializer, mtim;
00311 while (strlen(r2) > 0) {
00312 rSplitStr(r2,r1,NAME_LEN,r3,RULE_SET_DEF_LENGTH,',');
00313 getRuleBasePath(r1, fn);
00314 if((res = getModifiedTime(fn, &mtim))!=0) {
00315 return res;
00316 }
00317 if(time_type_gt(mtim, timestamp)) {
00318 time_type_set(timestamp, mtim);
00319 }
00320 #if defined(DEBUG) && !defined(USE_BOOST)
00321 printf("last modified time, %ld\n", timestamp);
00322 #endif
00323 strcpy(r2,r3);
00324 }
00325 strcpy(r2,irbSet);
00326
00327 #ifdef CACHE_ENABLE
00328
00329 Cache *cache;
00330 int update = 0;
00331 unsigned char *buf = NULL;
00332
00333 if(processType == RULE_ENGINE_TRY_CACHE && inRuleStruct == &coreRuleStrct) {
00334 buf = prepareNonServerSharedMemory();
00335 if(buf != NULL) {
00336 cache = restoreCache(buf);
00337 detachSharedMemory();
00338
00339 if(cache == NULL) {
00340 rodsLog(LOG_ERROR, "Failed to restore cache.");
00341 } else {
00342 int diffIrbSet = strcmp(cache->ruleBase, irbSet) != 0;
00343 if(diffIrbSet) {
00344 rodsLog(LOG_DEBUG, "Rule base set changed, old value is %s", cache->ruleBase);
00345 }
00346
00347 if(diffIrbSet || time_type_gt(timestamp, cache->timestamp)) {
00348 update = 1;
00349 free(cache->address);
00350 rodsLog(LOG_DEBUG, "Rule base set or rule files modified, force refresh.");
00351 } else {
00352
00353 cache->cacheStatus = INITIALIZED;
00354 ruleEngineConfig = *cache;
00355
00356 generateRegions();
00357 generateRuleSets();
00358 generateFunctionDescriptionTables();
00359 if(inRuleStruct == &coreRuleStrct && ruleEngineConfig.ruleEngineStatus == UNINITIALIZED) {
00360 getSystemFunctions(ruleEngineConfig.sysFuncDescIndex->current, ruleEngineConfig.sysRegion);
00361 }
00362
00363
00364
00365 RETURN;
00366 }
00367 }
00368 } else {
00369 rodsLog(LOG_DEBUG, "Cannot open shared memory.");
00370 }
00371 }
00372 #endif
00373
00374 if(ruleEngineConfig.ruleEngineStatus == INITIALIZED) {
00375
00376 unlinkFuncDescIndex();
00377 clearRuleIndex(inRuleStruct);
00378 }
00379
00380 generateRegions();
00381 generateRuleSets();
00382 generateFunctionDescriptionTables();
00383 if(inRuleStruct == &coreRuleStrct && ruleEngineConfig.ruleEngineStatus == UNINITIALIZED) {
00384 getSystemFunctions(ruleEngineConfig.sysFuncDescIndex->current, ruleEngineConfig.sysRegion);
00385 }
00386
00387
00388 while (strlen(r2) > 0) {
00389 int i = rSplitStr(r2,r1,NAME_LEN,r3,RULE_SET_DEF_LENGTH,',');
00390 if (i == 0)
00391 i = readRuleStructAndRuleSetFromFile(r1, inRuleStruct);
00392 #ifdef DEBUG
00393 printf("%d rules in core rule set\n", ruleEngineConfig.coreRuleSet->len);
00394 #endif
00395 if (i != 0) {
00396 res = i;
00397 RETURN;
00398 }
00399 strcpy(r2,r3);
00400 }
00401
00402 createRuleIndex(inRuleStruct);
00403
00404 time_type_set(ruleEngineConfig.timestamp, timestamp);
00405 rstrcpy(ruleEngineConfig.ruleBase, irbSet, RULE_SET_DEF_LENGTH);
00406
00407 #ifdef CACHE_ENABLE
00408 if((processType == RULE_ENGINE_INIT_CACHE || update) && inRuleStruct == &coreRuleStrct) {
00409 unsigned char *shared = prepareServerSharedMemory();
00410
00411 if(shared != NULL) {
00412 int ret = updateCache(shared, SHMMAX, &ruleEngineConfig, processType);
00413 detachSharedMemory();
00414 if(ret != 0) {
00415 removeSharedMemory();
00416 }
00417 } else {
00418 rodsLog(LOG_ERROR, "Cannot open shared memory.");
00419 }
00420 }
00421 #endif
00422
00423 ret:
00424 ruleEngineConfig.ruleEngineStatus = INITIALIZED;
00425
00426 return res;
00427 }
00428 int readRuleStructAndRuleSetFromFile(char *ruleBaseName, ruleStruct_t *inRuleStrct)
00429 {
00430
00431
00432
00433
00434
00435 char rulesFileName[MAX_NAME_LEN];
00436
00437
00438 char *configDir;
00439
00440
00441
00442 if (ruleBaseName[0] == '/' || ruleBaseName[0] == '\\' ||
00443 ruleBaseName[1] == ':') {
00444 snprintf (rulesFileName,MAX_NAME_LEN, "%s",ruleBaseName);
00445 }
00446 else {
00447 configDir = getConfigDir ();
00448 snprintf (rulesFileName,MAX_NAME_LEN, "%s/reConfigs/%s.re", configDir,ruleBaseName);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 int errloc;
00485 rError_t errmsgBuf;
00486 errmsgBuf.errMsg = NULL;
00487 errmsgBuf.len = 0;
00488
00489 char *buf = (char *) malloc(ERR_MSG_LEN*1024*sizeof(char));
00490 int res = 0;
00491 if(inRuleStrct == &coreRuleStrct) {
00492 if((res = readRuleSetFromFile(ruleBaseName,ruleEngineConfig.coreRuleSet,ruleEngineConfig.coreFuncDescIndex,&errloc,&errmsgBuf, ruleEngineConfig.coreRegion))==0) {
00493 } else {
00494 errMsgToString(&errmsgBuf, buf, ERR_MSG_LEN*1024);
00495 rodsLog(LOG_ERROR, "%s", buf);
00496 }
00497 } else if(inRuleStrct == &appRuleStrct) {
00498 if((res = readRuleSetFromFile(ruleBaseName,ruleEngineConfig.appRuleSet, ruleEngineConfig.appFuncDescIndex,&errloc,&errmsgBuf, ruleEngineConfig.appRegion))==0) {
00499 } else {
00500 errMsgToString(&errmsgBuf, buf, ERR_MSG_LEN*1024);
00501 rodsLog(LOG_ERROR, "%s", buf);
00502 }
00503 }
00504 free(buf);
00505 freeRErrorContent(&errmsgBuf);
00506 return res;
00507 }
00508
00509 int availableRules() {
00510 return (isComponentInitialized(ruleEngineConfig.appRuleSetStatus) ? ruleEngineConfig.coreRuleSet->len : 0) + (isComponentInitialized(ruleEngineConfig.appRuleSetStatus) == INITIALIZED? ruleEngineConfig.appRuleSet->len : 0);
00511 }
00512
00513
00514 int readICatUserInfo(char *userName, char *attr, char userInfo[MAX_NAME_LEN], rsComm_t *rsComm) {
00515 int status;
00516 genQueryInp_t genQueryInp;
00517 genQueryOut_t *genQueryOut = NULL;
00518 char condstr[MAX_NAME_LEN];
00519 sqlResult_t *r;
00520 memset(&genQueryInp, 0, sizeof(genQueryInp));
00521 genQueryInp.maxRows = MAX_SQL_ROWS;
00522
00523 snprintf(condstr, MAX_NAME_LEN, "= '%s'", userName);
00524 addInxVal(&genQueryInp.sqlCondInp, COL_USER_NAME, condstr);
00525 snprintf(condstr, MAX_NAME_LEN, "= '%s'", attr);
00526 addInxVal(&genQueryInp.sqlCondInp, COL_META_USER_ATTR_NAME, condstr);
00527
00528 addInxIval(&genQueryInp.selectInp, COL_META_USER_ATTR_VALUE, 1);
00529
00530 status = rsGenQuery(rsComm, &genQueryInp, &genQueryOut);
00531 if ( status >= 0 && genQueryOut->rowCnt > 0 ) {
00532 r = getSqlResultByInx (genQueryOut, COL_META_USER_ATTR_VALUE);
00533 rstrcpy(userInfo, &r->value[0], MAX_NAME_LEN);
00534 genQueryInp.continueInx = genQueryOut->continueInx;
00535 } else {
00536 userInfo[0] = '\0';
00537 }
00538 clearGenQueryInp (&genQueryInp);
00539 freeGenQueryOut (&genQueryOut);
00540 return status;
00541
00542 }
00543
00544 int writeICatUserInfo(char *userName, char *attr, char *value, rsComm_t *rsComm) {
00545 modAVUMetadataInp_t modAVUMetadataInp;
00546
00547 modAVUMetadataInp.arg0 = "set";
00548 modAVUMetadataInp.arg1 = "-u";
00549 modAVUMetadataInp.arg2 = userName;
00550 modAVUMetadataInp.arg3 = attr;
00551 modAVUMetadataInp.arg4 = value;
00552 modAVUMetadataInp.arg5 = "";
00553
00554 return rsModAVUMetadata(rsComm, &modAVUMetadataInp);
00555 }
00556
00557 int readICatUserLogging(char *userName, int *logging, rsComm_t *rsComm) {
00558 char userInfo[MAX_NAME_LEN];
00559 int i = readICatUserInfo(userName, RE_LOGGING_ATTR, userInfo, rsComm);
00560 if(i<0) {
00561 return i;
00562 }
00563 if(strcmp(userInfo, "true") == 0) {
00564 *logging = 1;
00565 } else if (strcmp(userInfo, "false") == 0){
00566 *logging = 0;
00567 } else {
00568 return RE_RUNTIME_ERROR;
00569 }
00570 return 0;
00571 }
00572 int writeICatUserLogging(char *userName, int logging, rsComm_t *rsComm) {
00573 char value[MAX_NAME_LEN];
00574 rstrcpy(value, (char *)(logging?"true":"false"), MAX_NAME_LEN);
00575 return writeICatUserInfo(userName, RE_LOGGING_ATTR, value, rsComm);
00576 }
00577
00578