(file) Return to SCMOClassCache.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2