00001
00002
00003 #include <limits.h>
00004 #include "cache.h"
00005 #include "rules.h"
00006 #include "functions.h"
00007 #include "locks.h"
00008 #include "sharedmemory.h"
00009 #include "datetime.h"
00010
00011
00012 #include "cache.instance.h"
00013 #include "traversal.instance.h"
00014 #include "restruct.templates.h"
00015
00016 Cache *copyCache(unsigned char **p, size_t size, Cache *ptr) {
00017 if(size%REGION_ALIGNMENT != 0) {
00018 return NULL;
00019 }
00020
00021 unsigned char *buf = *p;
00022 unsigned char *pointers0 = buf + size;
00023
00024
00025 Hashtable *objectMap = newHashTable(100);
00026 unsigned char **pointers = &pointers0;
00027 int generatePtrDesc = 1;
00028
00029 allocateInBuffer(Cache, ecopy, ptr);
00030
00031 MK_POINTER(&(ecopy->address));
00032 MK_POINTER(&(ecopy->pointers));
00033
00034 MK_PTR(RuleSet, coreRuleSet);
00035 MK_TRANSIENT_VAL(RuleEngineStatus, coreRuleSetStatus, COMPRESSED);
00036 MK_TRANSIENT_PTR(RuleSet, appRuleSet);
00037 MK_TRANSIENT_VAL(RuleEngineStatus, appRuleSetStatus, UNINITIALIZED);
00038 MK_TRANSIENT_PTR(RuleSet, extRuleSet);
00039 MK_TRANSIENT_VAL(RuleEngineStatus, extRuleSetStatus, UNINITIALIZED);
00040 MK_PTR_GENERIC(Env, coreFuncDescIndex, GENERIC(Node));
00041 MK_TRANSIENT_VAL(RuleEngineStatus, coreFuncDescIndexStatus, COMPRESSED);
00042 MK_TRANSIENT_PTR(Hashtable, appFuncDescIndex);
00043 MK_TRANSIENT_VAL(RuleEngineStatus, appFuncDescIndexStatus, UNINITIALIZED);
00044 MK_TRANSIENT_PTR(Hashtable, extFuncDescIndex);
00045 MK_TRANSIENT_VAL(RuleEngineStatus, extFuncDescIndexStatus, UNINITIALIZED);
00046 ecopy->dataSize = (*p - buf);
00047 ecopy->address = buf;
00048 ecopy->pointers = pointers0;
00049 ecopy->cacheSize = size;
00050 ecopy->cacheStatus = INITIALIZED;
00051 ecopy->appRegion = NULL;
00052 ecopy->appRegionStatus = UNINITIALIZED;
00053 ecopy->coreRegion = NULL;
00054 ecopy->coreRegionStatus = UNINITIALIZED;
00055 ecopy->extRegion = NULL;
00056 ecopy->extRegionStatus = UNINITIALIZED;
00057 ecopy->sysRegion = NULL;
00058 ecopy->sysRegionStatus = UNINITIALIZED;
00059 MK_TRANSIENT_PTR(Hashtable, sysFuncDescIndex);
00060 MK_TRANSIENT_VAL(RuleEngineStatus, sysFuncDescIndexStatus, UNINITIALIZED);
00061 MK_TRANSIENT_VAL(RuleEngineStatus, ruleEngineStatus, UNINITIALIZED);
00062
00063 deleteHashTable(objectMap, nop);
00064
00065 return ecopy;
00066 }
00067 Cache *restoreCache(unsigned char *buf) {
00068 mutex_type *mutex;
00069 Cache *cache = (Cache *) buf;
00070 unsigned char *bufCopy;
00071 unsigned char *pointers;
00072 size_t pointersSize;
00073 unsigned char *bufMapped;
00074
00075 unsigned char *pointersCopy;
00076 unsigned char *pointersMapped;
00077 size_t dataSize;
00078 unsigned int version, version2;
00079 int success = 0;
00080 do {
00081 if(lockMutex(&mutex) != 0) {
00082 break;
00083 }
00084 version = cache->version;
00085 unlockMutex(&mutex);
00086 dataSize = cache->dataSize;
00087 pointersMapped = cache->pointers;
00088 bufMapped = cache->address;
00089 if(pointersMapped<bufMapped || pointersMapped -bufMapped > SHMMAX || dataSize > SHMMAX) {
00090 sleep(1);
00091 continue;
00092 }
00093 bufCopy = (unsigned char *)malloc(dataSize);
00094 if(bufCopy == NULL) {
00095 return NULL;
00096 }
00097 memcpy(bufCopy, buf, cache->dataSize);
00098 pointersSize = bufMapped + SHMMAX - pointersMapped;
00099 pointersCopy = (unsigned char *)malloc(pointersSize);
00100 if(pointersCopy == NULL) {
00101 free(bufCopy);
00102 return NULL;
00103 }
00104 memcpy(pointersCopy, pointersMapped+(buf - bufMapped), pointersSize);
00105 if(lockMutex(&mutex)!=0) {
00106 free(bufCopy);
00107 free(pointersCopy);
00108 break;
00109 }
00110 version2 = cache->version;
00111 unlockMutex(&mutex);
00112 if(version2 != version) {
00113 free(bufCopy);
00114 free(pointersCopy);
00115 sleep(1);
00116 } else {
00117 success = 1;
00118 }
00119 } while(!success);
00120
00121 if(!success) {
00122 return NULL;
00123 }
00124 pointers = pointersCopy;
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 long diff = bufCopy - bufMapped;
00139 long pointerDiff = diff;
00140 applyDiff(pointers, pointersSize, diff, pointerDiff);
00141 free(pointersCopy);
00142 cache = (Cache *) bufCopy;
00143 return cache;
00144 }
00145 void applyDiff(unsigned char *pointers, long pointersSize, long diff, long pointerDiff) {
00146 unsigned char *p;
00147 #ifdef DEBUG_VERBOSE
00148 printf("storing cache from buf = %p, pointers = %p\n", buf, pointers);
00149 #endif
00150 for (p = pointers; p - pointers < pointersSize; p+=CACHE_SIZE(unsigned char *, 1)) {
00151 #ifdef DEBUG_VERBOSE
00152 printf("p = %p\n", p);
00153 #endif
00154 unsigned char *pointer = *((unsigned char **)p) + pointerDiff;
00155 #ifdef DEBUG_VERBOSE
00156 printf("applying diff to pointer at %p\n", pointer);
00157 #endif
00158 *((unsigned char **)pointer) += diff;
00159 }
00160 }
00161
00162 void applyDiffToPointers(unsigned char *pointers, long pointersSize, long pointerDiff) {
00163 unsigned char *p;
00164 #ifdef DEBUG_VERBOSE
00165 printf("storing cache from buf = %p, pointers = %p\n", buf, pointers);
00166 #endif
00167 for (p = pointers; p - pointers < pointersSize; p+=CACHE_SIZE(unsigned char *, 1)) {
00168 #ifdef DEBUG_VERBOSE
00169 printf("p = %p\n", p);
00170 #endif
00171 *((unsigned char **)p) += pointerDiff;
00172 #ifdef DEBUG_VERBOSE
00173 printf("applying diff to pointer at %p\n", pointer);
00174 #endif
00175 }
00176
00177 }
00178 int updateCache(unsigned char *shared, size_t size, Cache *cache, int processType) {
00179 mutex_type *mutex;
00180 time_type timestamp;
00181 time_type_set(timestamp, cache->timestamp);
00182
00183 if(lockMutex(&mutex) != 0) {
00184 rodsLog(LOG_ERROR, "Failed to update cache, lock mutex 1.");
00185 return -1;
00186 }
00187 if(processType == RULE_ENGINE_INIT_CACHE || processType == RULE_ENGINE_REFRESH_CACHE || time_type_gt(timestamp, ((Cache *)shared)->updateTS)) {
00188 time_type_set(((Cache *)shared)->updateTS, timestamp);
00189 unlockMutex(&mutex);
00190
00191 unsigned char *buf = (unsigned char *) malloc(size);
00192 if(buf != NULL) {
00193 int ret;
00194 unsigned char *cacheBuf = buf;
00195 Cache *cacheCopy = copyCache(&cacheBuf, size, cache);
00196 if(cacheCopy != NULL) {
00197 #ifdef DEBUG
00198 printf("Buffer usage: %fM\n", ((double)(cacheCopy->dataSize))/(1024*1024));
00199 #endif
00200 size_t pointersSize = (cacheCopy->address + cacheCopy->cacheSize) - cacheCopy->pointers;
00201 long diff = shared - cacheCopy->address;
00202 unsigned char *pointers = cacheCopy->pointers;
00203
00204 applyDiff(pointers, pointersSize, diff, 0);
00205 applyDiffToPointers(pointers, pointersSize, diff);
00206
00207 if(lockMutex(&mutex) != 0) {
00208 rodsLog(LOG_ERROR, "Failed to update cache, lock mutex 2.");
00209 free(buf);
00210 return -1;
00211 }
00212 if(processType == RULE_ENGINE_INIT_CACHE || processType == RULE_ENGINE_REFRESH_CACHE || !time_type_gt(((Cache *)shared)->updateTS, timestamp)) {
00213
00214 switch(processType) {
00215 case RULE_ENGINE_INIT_CACHE:
00216 cacheCopy->version = 0;
00217 break;
00218 default:
00219 cacheCopy->version = ((Cache *)shared)->version;
00220 INC_MOD(cacheCopy->version, UINT_MAX);
00221 }
00222
00223 memcpy(shared, buf, cacheCopy->dataSize);
00224
00225 memcpy(cacheCopy->pointers, pointers, pointersSize);
00226 }
00227 unlockMutex(&mutex);
00228 ret = 0;
00229 } else {
00230 rodsLog(LOG_ERROR, "Error updating cache.");
00231 ret = -1;
00232 }
00233 free(buf);
00234 return ret;
00235 } else {
00236 rodsLog(LOG_ERROR, "Cannot update cache because of out of memory error, let some other process update it later when memory is available.");
00237 return -1;
00238 }
00239 } else {
00240 unlockMutex(&mutex);
00241 rodsLog(LOG_DEBUG, "Cache has been updated by some other process.");
00242 return 0;
00243 }
00244
00245 }
00246
00247
00248