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