irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cache.cpp
Go to the documentation of this file.
1 /* For copyright information please refer to files in the COPYRIGHT directory
2  */
3 #include <limits.h>
4 #include "cache.hpp"
5 #include "rules.hpp"
6 #include "functions.hpp"
7 #include "locks.hpp"
8 #include "sharedmemory.hpp"
9 #include "datetime.hpp"
10 
11 
12 #include "cache.instance.hpp"
13 #include "traversal.instance.hpp"
14 #include "restruct.templates.hpp"
15 
16 /* Copy the data stored in a Cache struct into a continuously allocated memory block in *p.
17  * All sub structure status are either uninitialized or compressed, which meaning that they are not allocated separately and therefore should not be deallocated.
18  * Only coreRuleSet and coreFuncDescIndex are copied.
19  * Starting from *p+size backwards, a list of pointers to pointers in the copied data structures are stored.
20  * There pointers are used to quickly access all pointers in the stored data structures so that they can be offset when they are copied to a new memory address.
21  * This function returns NULL if it runs out of memory allocated between in *p and *p+size.
22  * The rule engine status is also set to uninitialized. */
23 Cache *copyCache( unsigned char **p, size_t size, Cache *ptr ) {
24  /* size should be large enough and divisible by ALIGNMENT */
25  if (size < DEFAULT_BLOCK_SIZE || 0 != size % REGION_ALIGNMENT) {
26  return NULL;
27  }
28 
29  unsigned char *buf = *p;
30  unsigned char *pointers0 = buf + size;
31 
32  /* shared objects */
33  unsigned char **pointers = &pointers0;
34  int generatePtrDesc = 1;
35 
36  allocateInBuffer( Cache, ecopy, ptr );
37 
38  MK_POINTER( &( ecopy->address ) );
39  MK_POINTER( &( ecopy->pointers ) );
40 
41  // objectMap will use a hash table size that is twice the number of objects being held (to favor speed).
42  // Example: The shared memory region has a size of SHMMAX (see shared_memory.hpp). SHMMAX == 30000000.
43  // The upper bound of the passed-in size is the shared memory region size.
44  // With an average compiled object size of 75 bytes (taken over sample of 9000 lines of rule code), SHMMAX / 75 = 400000 objects.
45  // The maximum size of the hash table should be twice the objects that can fit in shared memory (400000 * 2 = 800000).
46  // The ratio of the shared memory region size to the maximum hash table size is 30000000 / 800000 = 37.5
47  // Since the calculations are based on an average size, the ratio is rounded to 40 to avoid imbuing too much significance.
48  // The size of the hash table for a cache of the passed-in size, then, should be the size of the cache divided by the ratio.
49  // hashtable size upper limit == cache size upper limit / 40 == 30000000 / 40 < 800000
50  const int SHMEM_TO_MAX_HASHTABLE_SIZE_RATIO{40};
51  Hashtable *objectMap = newHashTable(size / SHMEM_TO_MAX_HASHTABLE_SIZE_RATIO);
52 
53  MK_PTR( RuleSet, coreRuleSet );
54  ecopy->coreRuleSetStatus = COMPRESSED;
55  ecopy->appRuleSet = NULL;
56  ecopy->appRuleSetStatus = UNINITIALIZED;
57  ecopy->extRuleSet = NULL;
58  ecopy->extRuleSetStatus = UNINITIALIZED;
59  MK_PTR_TAPP( Env, coreFuncDescIndex, PARAM( Node ) );
60  ecopy->coreFuncDescIndexStatus = COMPRESSED; /* The coreFuncDescIndex is stored in a continuously allocated memory block in *buf */
61  ecopy->appFuncDescIndex = NULL;
62  ecopy->appFuncDescIndexStatus = UNINITIALIZED;
63  ecopy->extFuncDescIndex = NULL;
64  ecopy->extFuncDescIndexStatus = UNINITIALIZED;
65  ecopy->dataSize = ( *p - buf );
66  ecopy->address = buf;
67  ecopy->pointers = pointers0;
68  ecopy->cacheSize = size;
69  ecopy->cacheStatus = INITIALIZED;
70  ecopy->appRegion = NULL;
71  ecopy->appRegionStatus = UNINITIALIZED;
72  ecopy->coreRegion = NULL;
73  ecopy->coreRegionStatus = UNINITIALIZED;
74  ecopy->extRegion = NULL;
75  ecopy->extRegionStatus = UNINITIALIZED;
76  ecopy->sysRegion = NULL;
77  ecopy->sysRegionStatus = UNINITIALIZED;
78  ecopy->sysFuncDescIndex = NULL;
79  ecopy->sysFuncDescIndexStatus = UNINITIALIZED;
80  ecopy->ruleEngineStatus = UNINITIALIZED;
81  MK_VAR_ARRAY_IN_STRUCT( char, ruleBase );
82 
83  deleteHashTable( objectMap, nop );
84 
85  return ecopy;
86 }
87 
88 /*
89  * Restore a Cache struct from buf into a malloc'd buffer.
90  * This function returns NULL if failed to acquire or release the mutex.
91  * It first create a local copy of buf's data section and pointer pointers section. This part needs synchronization.
92  * Then it works on its local copy, which does not need synchronization.
93  */
94 Cache *restoreCache( const char* _inst_name ) {
95  mutex_type *mutex;
96  lockReadMutex(_inst_name, &mutex);
97  unsigned char *buf = prepareNonServerSharedMemory( _inst_name );
98  if (buf == NULL) {
99  return NULL;
100  }
101  Cache *cache = ( Cache * ) buf;
102  unsigned char *bufCopy;
103  unsigned char *pointers;
104  size_t pointersSize;
105  unsigned char *bufMapped;
106 
107  unsigned char *pointersCopy;
108  unsigned char *pointersMapped;
109  size_t dataSize;
110  dataSize = cache->dataSize;
111  bufCopy = ( unsigned char * )malloc( dataSize );
112  if ( bufCopy == NULL ) {
113  rodsLog( LOG_ERROR, "Cannot allocate object buffer of size %lld" , dataSize);
114  unlockReadMutex(_inst_name, &mutex);
115  return NULL;
116  }
117  memcpy( bufCopy, buf, cache->dataSize );
118  Cache *cacheCopy = ( Cache * ) bufCopy;
119  pointersMapped = cacheCopy->pointers;
120  bufMapped = cacheCopy->address;
121  pointersSize = bufMapped + SHMMAX - pointersMapped;
122  pointersCopy = ( unsigned char * )malloc( pointersSize );
123  if ( pointersCopy == NULL ) {
124  free( bufCopy );
125  rodsLog( LOG_ERROR, "Cannot allocate pointer pointer buffer of size %lld", pointersSize);
126  detachSharedMemory( _inst_name );
127  unlockReadMutex(_inst_name, &mutex);
128  return NULL;
129  }
130  memcpy( pointersCopy, pointersMapped + ( buf - bufMapped ), pointersSize );
131  detachSharedMemory( _inst_name );
132  unlockReadMutex(_inst_name, &mutex);
133  pointers = pointersCopy;
134  /* bufCopy = (unsigned char *)malloc(cache->dataSize);
135 
136  if(bufCopy == NULL) {
137  return NULL;
138  }
139  memcpy(bufCopy, buf, cache->dataSize);
140 
141  bufMapped = cache->address;
142 
143  long diffBuf = buf - bufMapped;
144  pointers = cache->pointers + diffBuf;
145  pointersSize = pointers - buf; */
146  long diff = bufCopy - bufMapped;
147  long pointerDiff = diff;
148  applyDiff( pointers, pointersSize, diff, pointerDiff );
149  free( pointersCopy );
150 
151 #ifdef RE_CACHE_CHECK
152  Hashtable *objectMap = newHashTable( 100 );
153  cacheChkEnv( cacheCopy->coreFuncDescIndex, cacheCopy, ( CacheChkFuncType * ) cacheChkNode, objectMap );
154  cacheChkRuleSet( cacheCopy->coreRuleSet, cacheCopy, objectMap );
155 #endif
156  return cacheCopy;
157 }
158 void applyDiff( unsigned char *pointers, long pointersSize, long diff, long pointerDiff ) {
159  unsigned char *p;
160 #ifdef DEBUG_VERBOSE
161  printf( "storing cache from buf = %p, pointers = %p\n", buf, pointers );
162 #endif
163  for ( p = pointers; p - pointers < pointersSize; p += CACHE_SIZE( unsigned char *, 1 ) ) {
164 #ifdef DEBUG_VERBOSE
165  printf( "p = %p\n", p );
166 #endif
167  unsigned char *pointer = *( ( unsigned char ** )p ) + pointerDiff;
168 #ifdef DEBUG_VERBOSE
169  printf( "applying diff to pointer at %p\n", pointer );
170 #endif
171  *( ( unsigned char ** )pointer ) += diff;
172  }
173 }
174 
175 void applyDiffToPointers( unsigned char *pointers, long pointersSize, long pointerDiff ) {
176  unsigned char *p;
177 #ifdef DEBUG_VERBOSE
178  printf( "storing cache from buf = %p, pointers = %p\n", buf, pointers );
179 #endif
180  for ( p = pointers; p - pointers < pointersSize; p += CACHE_SIZE( unsigned char *, 1 ) ) {
181 #ifdef DEBUG_VERBOSE
182  printf( "p = %p\n", p );
183 #endif
184  *( ( unsigned char ** )p ) += pointerDiff;
185 #ifdef DEBUG_VERBOSE
186  printf( "applying diff to pointer at %p\n", pointer );
187 #endif
188  }
189 
190 }
191 
192 /*
193  * Update shared with a new cache.
194  * This function checks
195  * if new cache has a newer timestamp than the shared cache and updates,
196  * then the updateTS of the shared cache before it starts to update the cached data.
197  * else return.
198  * except when the processType is RULE_ENGINE_INIT_CACHE, which means that the share caches has not been initialized.
199  * or when the processType is RULE_ENGINE_REFRESH_CACHE, which means that we want to refresh the cache with the new cache.
200  * It prepares the data in the new cache for copying into the shared cache.
201  * It checks the timestamp again and does the actually copying.
202  */
203 int updateCache( const char* _inst_name, size_t size, Cache *cache ) {
204  unsigned char *buf = ( unsigned char * ) malloc( size );
205  if ( buf != NULL ) {
206  int ret;
207  unsigned char *cacheBuf = buf;
208  Cache *cacheCopy = copyCache( &cacheBuf, size, cache );
209  if ( cacheCopy != NULL ) {
210 #ifdef DEBUG
211  printf( "Buffer usage: %fM\n", ( ( double )( cacheCopy->dataSize ) ) / ( 1024 * 1024 ) );
212 #endif
213  size_t pointersSize = ( cacheCopy->address + cacheCopy->cacheSize ) - cacheCopy->pointers;
214  mutex_type *mutex;
215  lockWriteMutex(_inst_name, &mutex);
216  unsigned char *shared = prepareServerSharedMemory( _inst_name );
217  if (shared == NULL) {
218  ret = -1;
219  } else {
220  long diff = shared - cacheCopy->address;
221  unsigned char *pointers = cacheCopy->pointers;
222 
223  applyDiff( pointers, pointersSize, diff, 0 );
224  applyDiffToPointers( pointers, pointersSize, diff );
225 
226  memset( shared, 0, SHMMAX );
227  /* copy data */
228  memcpy( shared, buf, cacheCopy->dataSize );
229  /* copy pointers */
230  memcpy( cacheCopy->pointers, pointers, pointersSize );
231  ret = 0;
232  detachSharedMemory( _inst_name );
233  }
234  unlockWriteMutex(_inst_name, &mutex);
235  }
236  else {
237  rodsLog( LOG_ERROR, "Error updating cache." );
238  ret = -1;
239  }
240  free( buf );
241  return ret;
242  }
243  else {
244  rodsLog( LOG_ERROR, "Cannot update cache because of out of memory error, let some other process update it later when memory is available." );
245  return -1;
246  }
247 
248 }
249 
250 
251 
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
NULL
#define NULL
Definition: rodsDef.h:70
applyDiff
void applyDiff(unsigned char *pointers, long pointersSize, long diff, long pointerDiff)
Definition: cache.cpp:158
Cache
Definition: configuration.hpp:34
SHMMAX
#define SHMMAX
Definition: sharedmemory.hpp:14
updateCache
int updateCache(const char *_inst_name, size_t size, Cache *cache)
Definition: cache.cpp:203
allocateInBuffer
#define allocateInBuffer(ty, vn, val)
Definition: cache.instance.hpp:10
unlockReadMutex
void unlockReadMutex(const char *, mutex_type **mutex)
Definition: locks.cpp:70
locks.hpp
env
Definition: restructs.hpp:226
pid_age.p
p
Definition: pid_age.py:13
detachSharedMemory
void detachSharedMemory(const std::string &)
Definition: sharedmemory.cpp:52
unlockWriteMutex
void unlockWriteMutex(const char *, mutex_type **mutex)
Definition: locks.cpp:60
node
Definition: restructs.hpp:244
REGION_ALIGNMENT
#define REGION_ALIGNMENT
Definition: region.h:11
datetime.hpp
prepareServerSharedMemory
unsigned char * prepareServerSharedMemory(const std::string &)
Definition: sharedmemory.cpp:14
Cache::coreRuleSet
RuleSet * coreRuleSet
Definition: configuration.hpp:53
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
pointer
Definition: parser.hpp:34
MK_PTR
#define MK_PTR(type, f)
Definition: key.instance.hpp:17
UNINITIALIZED
@ UNINITIALIZED
Definition: configuration.hpp:26
functions.hpp
traversal.instance.hpp
restoreCache
Cache * restoreCache(const char *_inst_name)
Definition: cache.cpp:94
MK_PTR_TAPP
#define MK_PTR_TAPP(type, f, cpfn)
Definition: key.instance.hpp:21
Cache::cacheSize
size_t cacheSize
Definition: configuration.hpp:39
lockWriteMutex
int lockWriteMutex(const char *, mutex_type **mutex)
Definition: locks.cpp:10
Cache::coreFuncDescIndex
Env * coreFuncDescIndex
Definition: configuration.hpp:57
DEFAULT_BLOCK_SIZE
#define DEFAULT_BLOCK_SIZE
Definition: region.h:9
rules.hpp
sharedmemory.hpp
mutex_type
boost::interprocess::named_sharable_mutex mutex_type
Definition: locks.hpp:11
Cache::address
unsigned char * address
Definition: configuration.hpp:36
COMPRESSED
@ COMPRESSED
Definition: configuration.hpp:28
MK_POINTER
#define MK_POINTER(ptr)
Definition: cache.instance.hpp:23
Cache::dataSize
size_t dataSize
Definition: configuration.hpp:38
INITIALIZED
@ INITIALIZED
Definition: configuration.hpp:27
Cache::pointers
unsigned char * pointers
Definition: configuration.hpp:37
copyCache
Cache * copyCache(unsigned char **p, size_t size, Cache *ptr)
Definition: cache.cpp:23
MK_VAR_ARRAY_IN_STRUCT
#define MK_VAR_ARRAY_IN_STRUCT(type, f)
Definition: key.instance.hpp:29
newHashTable
Hashtable * newHashTable(int size)
Definition: hashtable.cpp:46
cache.instance.hpp
applyDiffToPointers
void applyDiffToPointers(unsigned char *pointers, long pointersSize, long pointerDiff)
Definition: cache.cpp:175
hashtable
Definition: irods_hashtable.h:16
size
long long size
Definition: filesystem.cpp:102
PARAM
#define PARAM(T)
Definition: traversal.instance.hpp:37
CACHE_SIZE
#define CACHE_SIZE(t, l)
Definition: region.h:16
buf
static char buf[64+50+1]
Definition: rsAuthRequest.cpp:21
deleteHashTable
void deleteHashTable(Hashtable *h, void(*f)(const void *))
Definition: hashtable.cpp:260
cache.hpp
nop
void nop(const void *a)
Definition: hashtable.cpp:284
restruct.templates.hpp
lockReadMutex
int lockReadMutex(const char *, mutex_type **mutex)
Definition: locks.cpp:35
prepareNonServerSharedMemory
unsigned char * prepareNonServerSharedMemory(const std::string &)
Definition: sharedmemory.cpp:72
ruleSet
Definition: restructs.hpp:282