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 Cache ruleEngineConfig = {
00015 NULL,
00016 NULL,
00017 0,
00018 0,
00019 UNINITIALIZED,
00020 UNINITIALIZED,
00021 UNINITIALIZED,
00022 UNINITIALIZED,
00023 UNINITIALIZED,
00024 UNINITIALIZED,
00025 UNINITIALIZED,
00026 UNINITIALIZED,
00027 UNINITIALIZED,
00028 UNINITIALIZED,
00029 UNINITIALIZED,
00030 UNINITIALIZED,
00031 UNINITIALIZED,
00032 NULL,
00033 NULL,
00034 NULL,
00035 NULL,
00036 NULL,
00037 NULL,
00038 NULL,
00039 NULL,
00040 NULL,
00041 NULL,
00042 NULL,
00043 0,
00044 0,
00045 time_type_initializer,
00046 time_type_initializer,
00047 0,
00048 };
00049
00050 #ifdef DEBUG
00051
00052 int rSplitStr(char *all, char *head, int headLen, char *tail, int tailLen, char sep) {
00053 char *i = strchr(all, sep);
00054 if(i==NULL) {
00055 tail[0] = '\0';
00056 strcpy(head, all);
00057 } else {
00058 strcpy(tail, i+1);
00059 strncpy(head, all, i-all);
00060 head[i-all] = '\0';
00061 }
00062 return 0;
00063 }
00064 #endif
00065
00066 void removeRuleFromExtIndex(char *ruleName, int i) {
00067 if(isComponentInitialized(ruleEngineConfig.extFuncDescIndexStatus)) {
00068 FunctionDesc *fd = (FunctionDesc *)lookupFromHashTable(ruleEngineConfig.extFuncDescIndex->current, ruleName);
00069 RuleIndexList *rd = FD_RULE_INDEX_LIST(fd);
00070 removeNodeFromRuleIndexList2(rd, i);
00071 if(rd->head == NULL) {
00072 deleteFromHashTable(ruleEngineConfig.extFuncDescIndex->current, ruleName);
00073 }
00074 }
00075
00076 }
00077 void appendRuleIntoExtIndex(RuleDesc *rule, int i, Region *r) {
00078 FunctionDesc *fd = (FunctionDesc *)lookupFromHashTable(ruleEngineConfig.extFuncDescIndex->current, RULE_NAME(rule->node));
00079 RuleIndexList *rd;
00080 if(fd == NULL) {
00081 rd = newRuleIndexList(RULE_NAME(rule->node), i, r);
00082 fd = newRuleIndexListFD(rd, NULL, r);
00083
00084 insertIntoHashTable(ruleEngineConfig.extFuncDescIndex->current, RULE_NAME(rule->node), fd);
00085 } else {
00086 if(getNodeType(fd)==N_FD_RULE_INDEX_LIST) {
00087 rd = FD_RULE_INDEX_LIST(fd);
00088 appendRuleNodeToRuleIndexList(rd, i ,r);
00089 } else if(getNodeType(fd) == N_FD_EXTERNAL) {
00090
00091 updateInHashTable(ruleEngineConfig.extFuncDescIndex->current, RULE_NAME(rule->node), newRuleIndexListFD(newRuleIndexList(RULE_NAME(rule->node), i, r),fd->exprType, r));
00092 } else {
00093
00094 }
00095 }
00096 }
00097
00098 void prependRuleIntoAppIndex(RuleDesc *rule, int i, Region *r) {
00099 RuleIndexList *rd;
00100 FunctionDesc *fd = (FunctionDesc *)lookupFromHashTable(ruleEngineConfig.appFuncDescIndex->current, RULE_NAME(rule->node));
00101 if(fd == NULL) {
00102 rd = newRuleIndexList(RULE_NAME(rule->node), i, r);
00103 fd = newRuleIndexListFD(rd, NULL, r);
00104 insertIntoHashTable(ruleEngineConfig.appFuncDescIndex->current, RULE_NAME(rule->node), fd);
00105 } else {
00106 rd = FD_RULE_INDEX_LIST(fd);
00107 prependRuleNodeToRuleIndexList(rd, i ,r);
00108 }
00109 }
00110 int checkPointExtRuleSet(Region *r) {
00111 ruleEngineConfig.extFuncDescIndex = newEnv(newHashTable2(100, r), ruleEngineConfig.extFuncDescIndex, NULL, r);
00112 return ruleEngineConfig.extRuleSet->len;
00113 }
00114
00115
00116
00117
00118
00119 void prependAppRule(RuleDesc *rd, Region *r) {
00120 int i = ruleEngineConfig.appRuleSet->len++;
00121 ruleEngineConfig.appRuleSet->rules[i] = rd;
00122 prependRuleIntoAppIndex(rd, i, r);
00123 }
00124 void popExtRuleSet(int checkPoint) {
00125
00126
00127
00128
00129 Env *temp = ruleEngineConfig.extFuncDescIndex;
00130 ruleEngineConfig.extFuncDescIndex = temp->previous;
00131
00132 ruleEngineConfig.extRuleSet->len = checkPoint;
00133 }
00134 RuleEngineStatus getRuleEngineStatus() {
00135 return ruleEngineConfig.ruleEngineStatus;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 int clearResources(int resources) {
00150 clearFuncDescIndex(APP, app);
00151 clearFuncDescIndex(SYS, sys);
00152 clearFuncDescIndex(CORE, core);
00153 clearFuncDescIndex(EXT, ext);
00154 clearRegion(APP, app);
00155 clearRegion(SYS, sys);
00156 clearRegion(CORE, core);
00157 clearRegion(EXT, ext);
00158 clearRuleSet(APP, app);
00159 clearRuleSet(CORE, core);
00160 clearRuleSet(EXT, ext);
00161
00162 if((resources & RESC_CACHE) && isComponentAllocated(ruleEngineConfig.cacheStatus)) {
00163 free(ruleEngineConfig.address);
00164 ruleEngineConfig.address = NULL;
00165 ruleEngineConfig.cacheStatus = UNINITIALIZED;
00166 }
00167 return 0;
00168 }
00169 List hashtablesToClear = {NULL, NULL};
00170 List envToClear = {NULL, NULL};
00171 List regionsToClear = {NULL, NULL};
00172 List memoryToFree = {NULL, NULL};
00173
00174 void delayClearResources(int resources) {
00175
00176
00177
00178
00179
00180
00181
00182
00183 delayClearRegion(APP, app);
00184 delayClearRegion(SYS, sys);
00185 delayClearRegion(CORE, core);
00186 delayClearRegion(EXT, ext);
00187 delayClearRuleSet(APP, app);
00188 delayClearRuleSet(CORE, core);
00189 delayClearRuleSet(EXT, ext);
00190 delayClearFuncDescIndex(APP, app);
00191 delayClearFuncDescIndex(SYS, sys);
00192 delayClearFuncDescIndex(CORE, core);
00193 delayClearFuncDescIndex(EXT, ext);
00194
00195 if((resources & RESC_CACHE) && ruleEngineConfig.cacheStatus == INITIALIZED) {
00196 listAppendNoRegion(&memoryToFree, ruleEngineConfig.address);
00197 ruleEngineConfig.cacheStatus = UNINITIALIZED;
00198 }
00199 }
00200
00201 void clearDelayed() {
00202 ListNode *n = envToClear.head;
00203 while(n!=NULL) {
00204
00205 listRemoveNoRegion(&envToClear, n);
00206 n = envToClear.head;
00207 }
00208 n = hashtablesToClear.head;
00209 while(n!=NULL) {
00210 deleteHashTable((Hashtable *) n->value, nop);
00211 listRemoveNoRegion(&hashtablesToClear, n);
00212 n = hashtablesToClear.head;
00213 }
00214 n = regionsToClear.head;
00215 while(n!=NULL) {
00216 region_free((Region *) n->value);
00217 listRemoveNoRegion(®ionsToClear, n);
00218 n = regionsToClear.head;
00219 }
00220 n = memoryToFree.head;
00221 while(n!=NULL) {
00222 free(n->value);
00223 listRemoveNoRegion(&memoryToFree, n);
00224 n = memoryToFree.head;
00225 }
00226 }
00227
00228 void setCacheAddress(unsigned char *addr, RuleEngineStatus status, long size) {
00229 ruleEngineConfig.address = addr;
00230 ruleEngineConfig.cacheStatus = status;
00231 ruleEngineConfig.cacheSize = size;
00232
00233 }
00234
00235 int generateLocalCache() {
00236 unsigned char *buf = NULL;
00237 if(ruleEngineConfig.cacheStatus == INITIALIZED) {
00238 free(ruleEngineConfig.address);
00239 }
00240 buf = (unsigned char *)malloc(SHMMAX);
00241 if(buf == NULL) {
00242 return RE_OUT_OF_MEMORY;
00243 }
00244 setCacheAddress(buf, INITIALIZED, SHMMAX);
00245 return 0;
00246 }
00247 int generateFunctionDescriptionTables() {
00248 createFuncDescIndex(SYS, sys);
00249 createFuncDescIndex(CORE, core);
00250 createFuncDescIndex(APP, app);
00251 if(!isComponentInitialized(ruleEngineConfig.extFuncDescIndexStatus)) {
00252 createFuncDescIndex(EXT, ext);
00253 ruleEngineConfig.extFuncDescIndex->previous = ruleEngineConfig.appFuncDescIndex;
00254 } else {
00255 Env *extEnv = ruleEngineConfig.extFuncDescIndex;
00256 while(extEnv->previous!= NULL) {
00257 extEnv = extEnv->previous;
00258 }
00259 extEnv->previous = ruleEngineConfig.appFuncDescIndex;
00260 }
00261 ruleEngineConfig.appFuncDescIndex->previous = ruleEngineConfig.coreFuncDescIndex;
00262 ruleEngineConfig.coreFuncDescIndex->previous = ruleEngineConfig.sysFuncDescIndex;
00263
00264 return 0;
00265 }
00266 void generateRuleSets() {
00267 createRuleSet(APP, app);
00268 createRuleSet(CORE, core);
00269 createRuleSet(EXT, ext);
00270 }
00271 void generateRegions() {
00272 createRegion(APP, app);
00273 createRegion(CORE, core);
00274 createRegion(SYS, sys);
00275 createRegion(EXT, ext);
00276 }
00277 int unlinkFuncDescIndex() {
00278 Env *extEnv = ruleEngineConfig.extFuncDescIndex;
00279 while(extEnv->previous != ruleEngineConfig.appFuncDescIndex) {
00280 extEnv = extEnv->previous;
00281 }
00282 extEnv->previous = NULL;
00283 ruleEngineConfig.appFuncDescIndex->previous = NULL;
00284 ruleEngineConfig.coreFuncDescIndex->previous = NULL;
00285 return 0;
00286 }
00287 int clearRuleIndex(ruleStruct_t *inRuleStruct) {
00288 if(inRuleStruct == &coreRuleStrct) {
00289 clearResources(RESC_CORE_FUNC_DESC_INDEX);
00290 } else if(inRuleStruct == &appRuleStrct) {
00291 clearResources(RESC_APP_FUNC_DESC_INDEX);
00292 }
00293 return 0;
00294 }
00295
00296
00297 int createRuleIndex(ruleStruct_t *inRuleStruct) {
00298 if(inRuleStruct == &coreRuleStrct) {
00299 createRuleNodeIndex(ruleEngineConfig.coreRuleSet, ruleEngineConfig.coreFuncDescIndex->current, CORE_RULE_INDEX_OFF, ruleEngineConfig.coreRegion);
00300 createCondIndex(ruleEngineConfig.coreRegion);
00301 } else if(inRuleStruct == &appRuleStrct) {
00302 createRuleNodeIndex(ruleEngineConfig.appRuleSet, ruleEngineConfig.appFuncDescIndex->current, APP_RULE_INDEX_OFF, ruleEngineConfig.appRegion);
00303 }
00304 return 0;
00305
00306 }
00307 int loadRuleFromCacheOrFile(int processType, char *irbSet, ruleStruct_t *inRuleStruct) {
00308 char r1[NAME_LEN], r2[RULE_SET_DEF_LENGTH], r3[RULE_SET_DEF_LENGTH];
00309 strcpy(r2,irbSet);
00310 int res = 0;
00311
00312 #ifdef DEBUG
00313
00314 #endif
00315
00316
00317 char fn[MAX_NAME_LEN];
00318 time_type timestamp = time_type_initializer, mtim;
00319 while (strlen(r2) > 0) {
00320 rSplitStr(r2,r1,NAME_LEN,r3,RULE_SET_DEF_LENGTH,',');
00321 getRuleBasePath(r1, fn);
00322 if((res = getModifiedTime(fn, &mtim))!=0) {
00323 return res;
00324 }
00325 if(time_type_gt(mtim, timestamp)) {
00326 time_type_set(timestamp, mtim);
00327 }
00328 #if defined(DEBUG) && !defined(USE_BOOST)
00329 printf("last modified time, %ld\n", timestamp);
00330 #endif
00331 strcpy(r2,r3);
00332 }
00333 strcpy(r2,irbSet);
00334
00335 #ifdef CACHE_ENABLE
00336
00337 Cache *cache;
00338 int update = 0;
00339 unsigned char *buf = NULL;
00340
00341 if(processType == RULE_ENGINE_TRY_CACHE && inRuleStruct == &coreRuleStrct) {
00342 buf = prepareNonServerSharedMemory();
00343 if(buf != NULL) {
00344 cache = restoreCache(buf);
00345 detachSharedMemory();
00346
00347 if(cache == NULL) {
00348 rodsLog(LOG_ERROR, "Failed to restore cache.");
00349 } else if(time_type_gt(timestamp, cache->timestamp)) {
00350 update = 1;
00351 free(cache->address);
00352 rodsLog(LOG_DEBUG, "Rule file modified, force refresh.");
00353 } else {
00354
00355 cache->cacheStatus = INITIALIZED;
00356 ruleEngineConfig = *cache;
00357
00358 generateRegions();
00359 generateRuleSets();
00360 generateFunctionDescriptionTables();
00361 if(inRuleStruct == &coreRuleStrct && ruleEngineConfig.ruleEngineStatus == UNINITIALIZED) {
00362 getSystemFunctions(ruleEngineConfig.sysFuncDescIndex->current, ruleEngineConfig.sysRegion);
00363 }
00364
00365
00366
00367 RETURN;
00368 }
00369 } else {
00370 rodsLog(LOG_DEBUG, "Cannot open shared memory.");
00371 }
00372 }
00373 #endif
00374
00375 if(ruleEngineConfig.ruleEngineStatus == INITIALIZED) {
00376
00377 unlinkFuncDescIndex();
00378 clearRuleIndex(inRuleStruct);
00379 }
00380
00381 generateRegions();
00382 generateRuleSets();
00383 generateFunctionDescriptionTables();
00384 if(inRuleStruct == &coreRuleStrct && ruleEngineConfig.ruleEngineStatus == UNINITIALIZED) {
00385 getSystemFunctions(ruleEngineConfig.sysFuncDescIndex->current, ruleEngineConfig.sysRegion);
00386 }
00387
00388
00389 while (strlen(r2) > 0) {
00390 int i = rSplitStr(r2,r1,NAME_LEN,r3,RULE_SET_DEF_LENGTH,',');
00391 if (i == 0)
00392 i = readRuleStructAndRuleSetFromFile(r1, inRuleStruct);
00393 #ifdef DEBUG
00394 printf("%d rules in core rule set\n", ruleEngineConfig.coreRuleSet->len);
00395 #endif
00396 if (i != 0) {
00397 res = i;
00398 RETURN;
00399 }
00400 strcpy(r2,r3);
00401 }
00402
00403 createRuleIndex(inRuleStruct);
00404
00405 time_type_set(ruleEngineConfig.timestamp, timestamp);
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