/* * Update shared with a new cache. * This function checks * if new cache has a newer timestamp than the shared cache and updates, * then the updateTS of the shared cache before it starts to update the cached data. * else return. * except when the processType is RULE_ENGINE_INIT_CACHE, which means that the share caches has not been initialized. * or when the processType is RULE_ENGINE_REFRESH_CACHE, which means that we want to refresh the cache with the new cache. * It prepares the data in the new cache for copying into the shared cache. * It checks the timestamp again and does the actually copying. */ int updateCache( const char* _inst_name, size_t size, Cache *cache ) { unsigned char *buf = ( unsigned char * ) malloc( size ); if ( buf != NULL ) { int ret; unsigned char *cacheBuf = buf; Cache *cacheCopy = copyCache( &cacheBuf, size, cache ); if ( cacheCopy != NULL ) { #ifdef DEBUG printf( "Buffer usage: %fM\n", ( ( double )( cacheCopy->dataSize ) ) / ( 1024 * 1024 ) ); #endif size_t pointersSize = ( cacheCopy->address + cacheCopy->cacheSize ) - cacheCopy->pointers; mutex_type *mutex; lockWriteMutex(_inst_name, &mutex); unsigned char *shared = prepareServerSharedMemory( _inst_name ); if (shared == NULL) { ret = -1; } else { long diff = shared - cacheCopy->address; unsigned char *pointers = cacheCopy->pointers; applyDiff( pointers, pointersSize, diff, 0 ); applyDiffToPointers( pointers, pointersSize, diff ); memset( shared, 0, SHMMAX ); /* copy data */ memcpy( shared, buf, cacheCopy->dataSize ); /* copy pointers */ memcpy( cacheCopy->pointers, pointers, pointersSize ); ret = 0; detachSharedMemory( _inst_name ); } unlockWriteMutex(_inst_name, &mutex); } else { rodsLog( LOG_ERROR, "Error updating cache." ); ret = -1; } free( buf ); return ret; } else { rodsLog( LOG_ERROR, "Cannot update cache because of out of memory error, let some other process update it later when memory is available." ); return -1; } }
int loadRuleFromCacheOrFile( int processType, char *irbSet, ruleStruct_t *inRuleStruct ) { char r1[NAME_LEN], r2[RULE_SET_DEF_LENGTH], r3[RULE_SET_DEF_LENGTH]; snprintf( r2, sizeof( r2 ), "%s", irbSet ); int res = 0; #ifdef DEBUG /*Cache *cache;*/ #endif /* get max timestamp */ char fn[MAX_NAME_LEN]; time_type timestamp = time_type_initializer, mtim; while ( strlen( r2 ) > 0 ) { rSplitStr( r2, r1, NAME_LEN, r3, RULE_SET_DEF_LENGTH, ',' ); getRuleBasePath( r1, fn ); if ( ( res = getModifiedTime( fn, &mtim ) ) != 0 ) { return res; } if ( time_type_gt( mtim, timestamp ) ) { time_type_set( timestamp, mtim ); } snprintf( r2, sizeof( r2 ), "%s", r3 ); } snprintf( r2, sizeof( r2 ), "%s", irbSet ); #ifdef CACHE_ENABLE int update = 0; unsigned char *buf = NULL; /* try to find shared memory cache */ if ( processType == RULE_ENGINE_TRY_CACHE && inRuleStruct == &coreRuleStrct ) { buf = prepareNonServerSharedMemory(); if ( buf != NULL ) { Cache * cache = restoreCache( buf ); detachSharedMemory(); if ( cache == NULL ) { rodsLog( LOG_ERROR, "Failed to restore cache." ); } else { int diffIrbSet = strcmp( cache->ruleBase, irbSet ) != 0; if ( diffIrbSet ) { rodsLog( LOG_DEBUG, "Rule base set changed, old value is %s", cache->ruleBase ); } if ( diffIrbSet || time_type_gt( timestamp, cache->timestamp ) ) { update = 1; free( cache->address ); rodsLog( LOG_DEBUG, "Rule base set or rule files modified, force refresh." ); } else { cache->cacheStatus = INITIALIZED; ruleEngineConfig = *cache; /* generate extRuleSet */ generateRegions(); generateRuleSets(); generateFunctionDescriptionTables(); if ( inRuleStruct == &coreRuleStrct && ruleEngineConfig.ruleEngineStatus == UNINITIALIZED ) { getSystemFunctions( ruleEngineConfig.sysFuncDescIndex->current, ruleEngineConfig.sysRegion ); } /* ruleEngineConfig.extRuleSetStatus = LOCAL; ruleEngineConfig.extFuncDescIndexStatus = LOCAL; */ /* createRuleIndex(inRuleStruct); */ ruleEngineConfig.ruleEngineStatus = INITIALIZED; //free( cache ); return res; } } //free( cache ); } else { rodsLog( LOG_DEBUG, "Cannot open shared memory." ); } } #endif if ( ruleEngineConfig.ruleEngineStatus == INITIALIZED ) { /* Reloading rule set, clear previously generated rule set */ unlinkFuncDescIndex(); clearRuleIndex( inRuleStruct ); } generateRegions(); generateRuleSets(); generateFunctionDescriptionTables(); if ( inRuleStruct == &coreRuleStrct && ruleEngineConfig.ruleEngineStatus == UNINITIALIZED ) { getSystemFunctions( ruleEngineConfig.sysFuncDescIndex->current, ruleEngineConfig.sysRegion ); } /*ruleEngineConfig.extRuleSetStatus = LOCAL; ruleEngineConfig.extFuncDescIndexStatus = LOCAL;*/ while ( strlen( r2 ) > 0 ) { int i = rSplitStr( r2, r1, NAME_LEN, r3, RULE_SET_DEF_LENGTH, ',' ); if ( i == 0 ) { i = readRuleStructAndRuleSetFromFile( r1, inRuleStruct ); } #ifdef DEBUG printf( "%d rules in core rule set\n", ruleEngineConfig.coreRuleSet->len ); #endif if ( i != 0 ) { res = i; ruleEngineConfig.ruleEngineStatus = INITIALIZED; return res; } snprintf( r2, sizeof( r2 ), "%s", r3 ); } createRuleIndex( inRuleStruct ); /* set max timestamp */ time_type_set( ruleEngineConfig.timestamp, timestamp ); snprintf( ruleEngineConfig.ruleBase, sizeof( ruleEngineConfig.ruleBase ), "%s", irbSet ); #ifdef CACHE_ENABLE if ( ( processType == RULE_ENGINE_INIT_CACHE || update ) && inRuleStruct == &coreRuleStrct ) { unsigned char *shared = prepareServerSharedMemory(); if ( shared != NULL ) { int ret = updateCache( shared, SHMMAX, &ruleEngineConfig, processType ); detachSharedMemory(); if ( ret != 0 ) { removeSharedMemory(); } } else { rodsLog( LOG_ERROR, "Cannot open shared memory." ); } } #endif ruleEngineConfig.ruleEngineStatus = INITIALIZED; return res; }
/* * Restore a Cache struct from buf into a malloc'd buffer. * This function returns NULL if failed to acquire or release the mutex. * It first create a local copy of buf's data section and pointer pointers section. This part needs synchronization. * Then it works on its local copy, which does not need synchronization. */ Cache *restoreCache( const char* _inst_name ) { mutex_type *mutex; lockReadMutex(_inst_name, &mutex); unsigned char *buf = prepareNonServerSharedMemory( _inst_name ); if (buf == NULL) { return NULL; } Cache *cache = ( Cache * ) buf; unsigned char *bufCopy; unsigned char *pointers; size_t pointersSize; unsigned char *bufMapped; unsigned char *pointersCopy; unsigned char *pointersMapped; size_t dataSize; dataSize = cache->dataSize; bufCopy = ( unsigned char * )malloc( dataSize ); if ( bufCopy == NULL ) { rodsLog( LOG_ERROR, "Cannot allocate object buffer of size %lld" , dataSize); unlockReadMutex(_inst_name, &mutex); return NULL; } memcpy( bufCopy, buf, cache->dataSize ); Cache *cacheCopy = ( Cache * ) bufCopy; pointersMapped = cacheCopy->pointers; bufMapped = cacheCopy->address; pointersSize = bufMapped + SHMMAX - pointersMapped; pointersCopy = ( unsigned char * )malloc( pointersSize ); if ( pointersCopy == NULL ) { free( bufCopy ); rodsLog( LOG_ERROR, "Cannot allocate pointer pointer buffer of size %lld", pointersSize); detachSharedMemory( _inst_name ); unlockReadMutex(_inst_name, &mutex); return NULL; } memcpy( pointersCopy, pointersMapped + ( buf - bufMapped ), pointersSize ); detachSharedMemory( _inst_name ); unlockReadMutex(_inst_name, &mutex); pointers = pointersCopy; /* bufCopy = (unsigned char *)malloc(cache->dataSize); if(bufCopy == NULL) { return NULL; } memcpy(bufCopy, buf, cache->dataSize); bufMapped = cache->address; long diffBuf = buf - bufMapped; pointers = cache->pointers + diffBuf; pointersSize = pointers - buf; */ long diff = bufCopy - bufMapped; long pointerDiff = diff; applyDiff( pointers, pointersSize, diff, pointerDiff ); free( pointersCopy ); #ifdef RE_CACHE_CHECK Hashtable *objectMap = newHashTable( 100 ); cacheChkEnv( cacheCopy->coreFuncDescIndex, cacheCopy, ( CacheChkFuncType * ) cacheChkNode, objectMap ); cacheChkRuleSet( cacheCopy->coreRuleSet, cacheCopy, objectMap ); #endif return cacheCopy; }