1 thilo.boehm 1.1.2.1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 thilo.boehm 1.1.2.1 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 thilo.boehm 1.1.2.5
|
33 thilo.boehm 1.1.2.1 #include <Pegasus/Common/SCMOClassCache.h>
34 #include <Pegasus/Common/CIMNameCast.h>
35
36 PEGASUS_NAMESPACE_BEGIN
37
|
38 thilo.boehm 1.1.2.5 PEGASUS_USING_STD;
|
39 thilo.boehm 1.1.2.1
|
40 thilo.boehm 1.1.2.5 SCMOClassCache* SCMOClassCache::_theInstance = 0;
|
41 thilo.boehm 1.1.2.1
42 void SCMOClassCache::destroy()
43 {
44 delete _theInstance;
|
45 marek 1.1.2.4 _theInstance=0;
|
46 thilo.boehm 1.1.2.1 }
47
48 SCMOClassCache* SCMOClassCache::getInstance()
49 {
50 if(_theInstance == NULL)
51 {
52 _theInstance = new SCMOClassCache();
53 }
54 return _theInstance;
55 }
56
|
57 thilo.boehm 1.1.2.5 #ifdef PEGASUS_USE_SCMO_CLASS_CACHE
|
58 thilo.boehm 1.1.2.1
|
59 thilo.boehm 1.1.2.5 SCMOClassCache::~SCMOClassCache()
|
60 thilo.boehm 1.1.2.1 {
|
61 thilo.boehm 1.1.2.5 // Signal to all callers and work in progress that the SMOClassCache
62 // will be destroyed soon.
63 // As from now, no other caller can get the the lock. They are blocked out.
64 _dying = true;
65
66 // Cleanup the class cache
67 for (Uint32 i = 0 ; i < PEGASUS_SCMO_CLASS_CACHE_SIZE; i++)
|
68 thilo.boehm 1.1.2.1 {
|
69 thilo.boehm 1.1.2.5 delete _theCache[i].data;
|
70 thilo.boehm 1.1.2.1 }
71 }
72
|
73 thilo.boehm 1.1.2.5 Uint64 SCMOClassCache::_generateKey(
74 const char* className,
75 Uint32 classNameLen,
76 const char* nameSpaceName,
77 Uint32 nameSpaceNameLen)
78 {
79 Uint64 key = 0;
80
81 key = (Uint64(classNameLen) << 48 ) |
82 (Uint64(className[0]) << 40 ) |
83 (Uint64(className[classNameLen-1]) << 32 ) |
84 (Uint64(nameSpaceNameLen) << 16 ) |
85 (Uint64(nameSpaceName[0]) << 8 ) |
86 Uint64(nameSpaceName[nameSpaceNameLen-1]);
87
88 /*
89 fprintf(stderr,"Class Name(%s) \'%04X%02X%02X\' "
90 "Name Space(%s) \'%04X%02X%02X\' "
91 "Key = %016llX\n",
92 className,classNameLen,className[0],className[classNameLen-1],
93 nameSpaceName,nameSpaceNameLen,nameSpaceName[0],
94 thilo.boehm 1.1.2.5 nameSpaceName[nameSpaceNameLen-1],key);
95 */
96 return key;
97 }
98
99 inline Boolean SCMOClassCache::_lockEntry(Uint32 index)
100 {
101 // The lock is implemented as a spin loop, since the action to
102 // verify for the right cache entry is very short.
103
104 if ( _dying )
105 {
106 // The cache is going to be destroyed.
107 // The caller will never get the lock.
108 return false;
109 }
110
111 while ( true )
112 {
113 if ( _dying )
114 {
115 thilo.boehm 1.1.2.5 // The cache is going to be destroyed.
116 // The caller will never get the lock.
117 return false;
118 }
119
120 // If the lock counter not 1,an other caller is reading the entry.
121 if ( _theCache[index].lock.get() == 1 )
122 {
123 // Decrement the atomic lock counter and test if we do have lock:
124 // _theCache[index].lock == 0
125 if ( _theCache[index].lock.decAndTestIfZero() )
126 {
127 // We do have lock!
128 return true;
129 }
130 }
131 // I did not get the lock. So signal the scheduer to change the active
132 // thread to allow other threads to proceed. This also prevents from
133 // looping in a tight loop that causes a dead look due to the
134 // lock obtaining thread does not get any time ot finsh his work.
135 #ifdef PEGASUS_DEBUG
136 thilo.boehm 1.1.2.5 _contentionCount.inc();
137 #endif
138 Threads::yield();
139 }
140 return false;
141 }
|
142 thilo.boehm 1.1.2.1
|
143 thilo.boehm 1.1.2.5 inline Boolean SCMOClassCache::_sameSCMOClass(
|
144 thilo.boehm 1.1.2.1 const char* nsName,
145 Uint32 nsNameLen,
146 const char* className,
|
147 thilo.boehm 1.1.2.5 Uint32 classNameLen,
148 SCMOClass* theClass)
|
149 thilo.boehm 1.1.2.1 {
|
150 thilo.boehm 1.1.2.5 if (_equalNoCaseUTF8Strings(
151 theClass->cls.hdr->className,
152 theClass->cls.base,
153 className,
154 classNameLen))
|
155 thilo.boehm 1.1.2.1 {
|
156 thilo.boehm 1.1.2.5 return _equalNoCaseUTF8Strings(
157 theClass->cls.hdr->nameSpace,
158 theClass->cls.base,
159 nsName,
160 nsNameLen);
161 }
|
162 thilo.boehm 1.1.2.1
|
163 thilo.boehm 1.1.2.5 return false;
164 }
|
165 thilo.boehm 1.1.2.1
|
166 thilo.boehm 1.1.2.5 SCMOClass SCMOClassCache::_addClassToCache(
167 const char* nsName,
168 Uint32 nsNameLen,
169 const char* className,
170 Uint32 classNameLen,
171 Uint64 theKey)
172 {
173 WriteLock modifyLock(_modifyCacheLock);
|
174 thilo.boehm 1.1.2.1
|
175 thilo.boehm 1.1.2.5 if ( _dying )
176 {
177 // The cache is going to be destroyed.
178 return SCMOClass();
179 }
|
180 thilo.boehm 1.1.2.1
|
181 thilo.boehm 1.1.2.5 Uint32 startIndex =_lastSuccessIndex % PEGASUS_SCMO_CLASS_CACHE_SIZE;
182 Uint32 nextIndex = startIndex;
183 // The number of used entries is form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
184 Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
185
186 // This constallation would cause an infitloop below.
187 // A miss read of global variables has happen
188 if (nextIndex > usedEntries)
189 {
190 // start from the beginning
191 startIndex = 0;
192 nextIndex = 0;
193 }
|
194 thilo.boehm 1.1.2.1
|
195 thilo.boehm 1.1.2.5 // Check the cache if the class was already added while waiting for the
196 // modifyLock.
197 //
198 // Note: The lock for each cache entry must not be obtained,
199 // because it is used to signal a modify operation, that some
200 // body is reading it. Due to we are the modify task, we know
201 // that we are reading the cache entries!
202 //
203 for (Uint32 i = 0; i < usedEntries; i++)
204 {
205 // Does the key match for the entry and the requested class ?
206 if (0 != _theCache[nextIndex].key &&
207 theKey == _theCache[nextIndex].key)
208 {
209 // To get sure we found the right class, compare name space
210 // and class name.
211 if (_sameSCMOClass(nsName,nsNameLen,className,classNameLen,
212 _theCache[nextIndex].data))
|
213 thilo.boehm 1.1.2.1 {
|
214 thilo.boehm 1.1.2.5 // The entry was added while waiting for the modify lock.
215 // The modify lock is destroyed automaticaly !
216 #ifdef PEGASUS_DEBUG
217 _cacheReadHit++;
218 #endif
219 _lastSuccessIndex = nextIndex;
220 return SCMOClass(*_theCache[nextIndex].data);
|
221 thilo.boehm 1.1.2.1 }
222 }
223
|
224 thilo.boehm 1.1.2.5 // go to the next used entries.
225 nextIndex = (nextIndex + 1) % usedEntries;
226 }
|
227 thilo.boehm 1.1.2.1
|
228 thilo.boehm 1.1.2.5 PEGASUS_ASSERT(_resolveCallBack);
|
229 thilo.boehm 1.1.2.1
|
230 thilo.boehm 1.1.2.5 #ifdef PEGASUS_DEBUG
231 _cacheReadMiss++;
232 #endif
233
234 CIMClass cc = _resolveCallBack(
235 CIMNamespaceNameCast(String(nsName,nsNameLen)),
236 CIMNameCast(String(className,classNameLen)));
237
238 if (cc.isUninitialized())
239 {
240 // The requested class was not found !
241 // The modify lock is destroyed automaticaly !
242 return SCMOClass();
243 }
244
245 SCMOClass* scmoClass = new SCMOClass(cc,nsName);
246
247 _lastWrittenIndex = (_lastWrittenIndex + 1)%PEGASUS_SCMO_CLASS_CACHE_SIZE;
248
249 // Ensure that nobody is reading the enty, so I can write.
250 if (_lockEntry(_lastWrittenIndex))
251 thilo.boehm 1.1.2.5 {
252 _theCache[_lastWrittenIndex].key = theKey;
253
254 // If the entry was reused, release old object form the cache.
255 if (0 != _theCache[_lastWrittenIndex].data )
256 {
257 #ifdef PEGASUS_DEBUG
258 _cacheRemoveLRU++;
259 #endif
260 delete _theCache[_lastWrittenIndex].data;
261 }
262
263 _theCache[_lastWrittenIndex].data = scmoClass;
264
265 if (_fillingLevel < PEGASUS_SCMO_CLASS_CACHE_SIZE)
266 {
267 _fillingLevel ++;
268 }
269
270 _lastSuccessIndex = _lastWrittenIndex;
271
272 thilo.boehm 1.1.2.5 _unlockEntry(_lastWrittenIndex);
273 }
274 else
275 {
276 // The cache is going to be destroyed.
277 // The lock can not be obtained.
278 delete scmoClass;
279 return SCMOClass();
280 }
|
281 thilo.boehm 1.1.2.1
|
282 thilo.boehm 1.1.2.5 // The modify lock is destroyed automaticaly !
283 return SCMOClass(*scmoClass);
284 }
|
285 thilo.boehm 1.1.2.1
|
286 thilo.boehm 1.1.2.5 SCMOClass SCMOClassCache::getSCMOClass(
287 const char* nsName,
288 Uint32 nsNameLen,
289 const char* className,
290 Uint32 classNameLen)
291 {
292 Uint64 theKey;
|
293 marek 1.1.2.3
|
294 thilo.boehm 1.1.2.5 // Due to the _lastSuccessIndex may contain an invalid value,
295 // use the modulo to ensure it the index is in a valid range.
296 Uint32 startIndex =_lastSuccessIndex % PEGASUS_SCMO_CLASS_CACHE_SIZE;
297 Uint32 nextIndex = startIndex;
298 // The number of used entries form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
299 Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
300
301 // This constallation would cause an infitloop below.
302 // A miss read of global variables has happen
303 if (nextIndex > usedEntries)
304 {
305 // start from the beginning
306 startIndex = 0;
307 nextIndex = 0;
308 }
309
310 if (nsName && className && nsNameLen && classNameLen)
311 {
312 theKey = _generateKey(className,classNameLen,nsName,nsNameLen);
313
|
314 thilo.boehm 1.1.2.6 // The counter i is never used as index.
315 // It is used to ensure to look through all used entries.
|
316 thilo.boehm 1.1.2.5 for (Uint32 i = 0; i < usedEntries; i++)
317 {
318 if(_lockEntry(nextIndex))
319 {
320 // does the key match for the entry and the requested class ?
321 if ( 0 != _theCache[nextIndex].key &&
322 theKey == _theCache[nextIndex].key)
323 {
324 // To get sure we found the right class, compare name space
325 // and class name.
326 if (_sameSCMOClass(nsName,nsNameLen,className,classNameLen,
327 _theCache[nextIndex].data))
328 {
329 // Yes, we got it !
330 SCMOClass theClass(*_theCache[nextIndex].data);
331 _lastSuccessIndex = nextIndex;
332 #ifdef PEGASUS_DEBUG
333 _cacheReadHit++;
334 #endif
335 _unlockEntry(nextIndex);
336 return theClass;
337 thilo.boehm 1.1.2.5 }
338 }
339 // It was the wrong entry, go to the next.
340 _unlockEntry(nextIndex);
341 }
342 else
343 {
344 // The cache is going to be destroyed.
345 // The lock can not be obtained. Give up.
346 return SCMOClass();
347 }
348 // It was the wrong entry, go to the next used entry..
349 nextIndex = (nextIndex + 1) % usedEntries;
350
351 }
352
353 // If we end up here, the class is not in the cache !
354 // We have to get it from the repositroy and add it into the cache.
355 return _addClassToCache(nsName,nsNameLen,className,classNameLen,theKey);
|
356 thilo.boehm 1.1.2.1 }
357
|
358 thilo.boehm 1.1.2.5 return SCMOClass();
359 }
360
|
361 thilo.boehm 1.1.2.6 void SCMOClassCache::removeSCMOClass(
362 CIMNamespaceName cimNameSpace,
363 CIMName cimClassName)
364 {
365
366 if (cimClassName.isNull() || cimNameSpace.isNull())
367 {
368 return ;
369 }
370
371 CString nsName = cimNameSpace.getString().getCString();
372 Uint32 nsNameLen = strlen(nsName);
373 CString clsName = cimClassName.getString().getCString();
374 Uint32 clsNameLen = strlen(clsName);
375
376 // The number of used entries form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
377 Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
378
379 Uint64 theKey = _generateKey(clsName,clsNameLen,nsName,nsNameLen);
380
381 // A straight forward loop through all used entries,
382 thilo.boehm 1.1.2.6 // ignoring the last success.
383 for (Uint32 i = 0; i < usedEntries; i++)
384 {
385 if(_lockEntry(i))
386 {
387 // does the key match for the entry and the requested class ?
388 if ( 0 != _theCache[i].key && theKey == _theCache[i].key)
389 {
390 // To get sure we found the right class, compare name space
391 // and class name.
392 if (_sameSCMOClass(nsName,nsNameLen,clsName,clsNameLen,
393 _theCache[i].data))
394 {
395 // Yes, we got it !
396 _theCache[i].key = 0;
397 delete _theCache[i].data;
398 _theCache[i].data = 0;
399 _unlockEntry(i);
400 return;
401 }
402 }
403 thilo.boehm 1.1.2.6 // It was the wrong entry, go to the next.
404 _unlockEntry(i);
405 }
406 else
407 {
408 // We do not get the lock, if the cache is going to be destroyed.
409 return;
410 }
411 }
412 }
413
414 void SCMOClassCache::clear()
415 {
416 WriteLock modifyLock(_modifyCacheLock);
417
418 if ( _dying )
419 {
420 // The cache is going to be destroyed.
421 return ;
422 }
423
424 thilo.boehm 1.1.2.6 // The number of used entries form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
425 Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
426
427 // A straight forwar loop through all used entries,
428 // ignoring the last success.
429 for (Uint32 i = 0; i < usedEntries; i++)
430 {
431 if(_lockEntry(i))
432 {
433 _theCache[i].key = 0;
434 delete _theCache[i].data;
435 _theCache[i].data = 0;
436 _unlockEntry(i);
437 }
438 else
439 {
440 // We do not get the lock, if the cache is going to be destroyed.
441 return;
442 }
443 }
444 // Reset all controll data
445 thilo.boehm 1.1.2.6 _fillingLevel = 0;
446 _lastSuccessIndex = 0;
447 _lastWrittenIndex = PEGASUS_SCMO_CLASS_CACHE_SIZE-1;
448
449
450 }
|
451 thilo.boehm 1.1.2.5 #ifdef PEGASUS_DEBUG
452 void SCMOClassCache::DisplayCacheStatistics()
453 {
454 PEGASUS_STD(cout) << "SCMOClass Cache Statistics:" <<
455 PEGASUS_STD(endl);
456 PEGASUS_STD(cout) << " Size (current/max): " <<
457 _fillingLevel << "/" << PEGASUS_SCMO_CLASS_CACHE_SIZE <<
458 PEGASUS_STD(endl);
459 PEGASUS_STD(cout) << " Requests satisfied from cache: " <<
460 _cacheReadHit << PEGASUS_STD(endl);
461 PEGASUS_STD(cout) << " Requests *not* satisfied from cache: " <<
462 _cacheReadMiss << " (implies write to cache)" << PEGASUS_STD(endl);
463 PEGASUS_STD(cout) <<
464 " Cache entries \"aged out\" due to cache size constraints: " <<
465 _cacheRemoveLRU << PEGASUS_STD(endl);
466 PEGASUS_STD(cout) << " Number of lock contentions: " <<
467 _contentionCount.get() << PEGASUS_STD(endl);
468
|
469 thilo.boehm 1.1.2.1 }
|
470 thilo.boehm 1.1.2.5 #endif
471
472
473 #else // PEGASUS_USE_SCMO_CLASS_CACHE
474 SCMOClass SCMOClassCache::getSCMOClass(
475 const char* nsName,
476 Uint32 nsNameLen,
477 const char* className,
478 Uint32 classNameLen)
479 {
|
480 thilo.boehm 1.1.2.6 if (nsName && className && nsNameLen && classNameLen)
481 {
482
483 PEGASUS_ASSERT(_resolveCallBack);
484
485 CIMClass cc = _resolveCallBack(
486 CIMNamespaceNameCast(String(nsName,nsNameLen)),
487 CIMNameCast(String(className,classNameLen)));
488
489 if (cc.isUninitialized())
490 {
491 // The requested class was not found !
492 return SCMOClass();
493 }
|
494 thilo.boehm 1.1.2.5
|
495 thilo.boehm 1.1.2.6 return SCMOClass(cc,nsName);
496 }
|
497 thilo.boehm 1.1.2.5
|
498 thilo.boehm 1.1.2.6 return SCMOClass();
|
499 thilo.boehm 1.1.2.5
|
500 thilo.boehm 1.1.2.6 }
|
501 thilo.boehm 1.1.2.5
|
502 thilo.boehm 1.1.2.6 void SCMOClassCache::removeSCMOClass(
503 CIMNamespaceName cimNameSpace,
504 CIMName cimClassName)
505 {
|
506 thilo.boehm 1.1.2.5 }
507
|
508 thilo.boehm 1.1.2.6
509 void SCMOClassCache::clear()
|
510 thilo.boehm 1.1.2.5 {
511 }
512
|
513 thilo.boehm 1.1.2.6 # ifdef PEGASUS_DEBUG
|
514 thilo.boehm 1.1.2.5 void SCMOClassCache::DisplayCacheStatistics(){}
|
515 thilo.boehm 1.1.2.6 # endif
|
516 thilo.boehm 1.1.2.1
|
517 thilo.boehm 1.1.2.5 #endif
|
518 thilo.boehm 1.1.2.1 PEGASUS_NAMESPACE_END
|