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