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

  1 thilo.boehm 1.2 //%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.2 // 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                 
 33                 #include <Pegasus/Common/SCMOClassCache.h>
 34                 #include <Pegasus/Common/CIMNameCast.h>
 35                 
 36                 PEGASUS_NAMESPACE_BEGIN
 37                 
 38                 PEGASUS_USING_STD;
 39                 
 40                 SCMOClassCache* SCMOClassCache::_theInstance = 0;
 41                 
 42                 void SCMOClassCache::destroy()
 43 thilo.boehm 1.2 {
 44                     delete _theInstance;
 45                     _theInstance=0;
 46                 }
 47                 
 48                 SCMOClassCache* SCMOClassCache::getInstance()
 49                 {
 50                     if(_theInstance == NULL)
 51                     {
 52                         _theInstance = new SCMOClassCache();
 53                     }
 54                     return _theInstance;
 55                 }
 56                 
 57                 #ifdef PEGASUS_USE_SCMO_CLASS_CACHE
 58                 
 59                 SCMOClassCache::~SCMOClassCache()
 60                 {
 61                     // 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 thilo.boehm 1.2     _dying = true;
 65                 
 66                     // Cleanup the class cache
 67                     for (Uint32 i = 0 ; i < PEGASUS_SCMO_CLASS_CACHE_SIZE; i++)
 68                     {
 69                         delete _theCache[i].data;
 70                     }
 71                 }
 72                 
 73                 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 thilo.boehm 1.2             (Uint64(nameSpaceName[0]) << 8 ) |
 86                             Uint64(nameSpaceName[nameSpaceNameLen-1]);
 87                 
 88                     return key;
 89                 }
 90                 
 91                 inline Boolean SCMOClassCache::_lockEntry(Uint32 index)
 92                 {
 93                     // The lock is implemented as a spin loop, since the action to
 94                     // verify for the right cache entry is very short.
 95                 
 96                     if ( _dying )
 97                     {
 98                         // The cache is going to be destroyed.
 99                         // The caller will never get the lock.
100                         return false;
101                     }
102                 
103                     while ( true )
104                     {
105                         if ( _dying )
106 thilo.boehm 1.2         {
107                             // The cache is going to be destroyed.
108                             // The caller will never get the lock.
109                             return false;
110                         }
111                 
112                         // If the lock counter not 1,an other caller is reading the entry.
113                         if ( _theCache[index].lock.get() == 1 )
114                         {
115                             // Decrement the atomic lock counter and test if we do have lock:
116                             // _theCache[index].lock == 0
117                             if ( _theCache[index].lock.decAndTestIfZero() )
118                             {
119                                 // We do have lock!
120                                 return true;
121                             }
122                         }
123                         // I did not get the lock. So signal the scheduer to change the active
124                         // thread to allow other threads to proceed. This also prevents from
125                         // looping in a tight loop that causes a dead look due to the
126                         // lock obtaining thread does not get any time ot finsh his work.
127 thilo.boehm 1.2 #ifdef PEGASUS_DEBUG
128                         _contentionCount.inc();
129                 #endif
130                         Threads::yield();
131                     }
132                     return false;
133                 }
134                 
135                 inline Boolean SCMOClassCache::_sameSCMOClass(
136                         const char* nsName,
137                         Uint32 nsNameLen,
138                         const char* className,
139                         Uint32 classNameLen,
140                         SCMOClass* theClass)
141                 {
142                     if (_equalNoCaseUTF8Strings(
143                             theClass->cls.hdr->className,
144                             theClass->cls.base,
145                             className,
146                             classNameLen))
147                     {
148 thilo.boehm 1.2         return _equalNoCaseUTF8Strings(
149                                 theClass->cls.hdr->nameSpace,
150                                 theClass->cls.base,
151                                 nsName,
152                                 nsNameLen);
153                     }
154                 
155                     return false;
156                 }
157                 
158                 SCMOClass SCMOClassCache::_addClassToCache(
159                         const char* nsName,
160                         Uint32 nsNameLen,
161                         const char* className,
162                         Uint32 classNameLen,
163                         Uint64 theKey)
164                 {
165                     WriteLock modifyLock(_modifyCacheLock);
166                 
167                     if ( _dying )
168                     {
169 thilo.boehm 1.2         // The cache is going to be destroyed.
170                         return SCMOClass();
171                     }
172                 
173                     Uint32 startIndex =_lastSuccessIndex % PEGASUS_SCMO_CLASS_CACHE_SIZE;
174                     Uint32 nextIndex = startIndex;
175                     // The number of used entries is form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
176                     Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
177                 
178                     // This constallation would cause an infitloop below.
179                     // A miss read of global variables has happen
180                     if (nextIndex > usedEntries)
181                     {
182                         // start from the beginning
183                         startIndex = 0;
184                         nextIndex = 0;
185                     }
186                 
187                     // Check the cache if the class was already added while waiting for the
188                     // modifyLock.
189                     //
190 thilo.boehm 1.2     // Note: The lock for each cache entry must not be obtained,
191                     //       because it is used to signal a modify operation, that some
192                     //       body is reading it. Due to we are the modify task, we know
193                     //       that we are reading the cache entries!
194                     //
195                     for (Uint32 i = 0; i < usedEntries; i++)
196                     {
197                         // Does the key match for the entry and the requested class ?
198                         if (0 != _theCache[nextIndex].key &&
199                             theKey == _theCache[nextIndex].key)
200                         {
201                             // To get sure we found the right class, compare name space
202                             // and class name.
203                             if (_sameSCMOClass(nsName,nsNameLen,className,classNameLen,
204                                                _theCache[nextIndex].data))
205                             {
206                                 // The entry was added while waiting for the modify lock.
207                                 // The modify lock is destroyed automaticaly !
208                 #ifdef PEGASUS_DEBUG
209                                 _cacheReadHit++;
210                 #endif
211 thilo.boehm 1.2                 _lastSuccessIndex = nextIndex;
212                                 return SCMOClass(*_theCache[nextIndex].data);
213                             }
214                         }
215                 
216                         // go to the next used entries.
217                         nextIndex = (nextIndex + 1) % usedEntries;
218                     }
219                 
220                     PEGASUS_ASSERT(_resolveCallBack);
221                 
222                 #ifdef PEGASUS_DEBUG
223                     _cacheReadMiss++;
224                 #endif
225                 
226                     SCMOClass tmp = _resolveCallBack(
227                          CIMNamespaceNameCast(String(nsName,nsNameLen)),
228                          CIMNameCast(String(className,classNameLen)));
229                 
230                     if (tmp.isEmpty())
231                     {
232 thilo.boehm 1.2          // The requested class was not found !
233                          // The modify lock is destroyed automaticaly !
234                          return SCMOClass();
235                     }
236                 
237                     SCMOClass* scmoClass = new SCMOClass(tmp);
238                 
239                     _lastWrittenIndex = (_lastWrittenIndex + 1)%PEGASUS_SCMO_CLASS_CACHE_SIZE;
240                 
241                     // Ensure that nobody is reading the enty, so I can write.
242                     if (_lockEntry(_lastWrittenIndex))
243                     {
244                         _theCache[_lastWrittenIndex].key = theKey;
245                 
246                         // If the entry was reused, release old object form the cache.
247                         if (0 != _theCache[_lastWrittenIndex].data )
248                         {
249                 #ifdef PEGASUS_DEBUG
250                             _cacheRemoveLRU++;
251                 #endif
252                             delete _theCache[_lastWrittenIndex].data;
253 thilo.boehm 1.2         }
254                 
255                         _theCache[_lastWrittenIndex].data = scmoClass;
256                 
257                         if (_fillingLevel  < PEGASUS_SCMO_CLASS_CACHE_SIZE)
258                         {
259                             _fillingLevel ++;
260                         }
261                 
262                         _lastSuccessIndex = _lastWrittenIndex;
263                 
264                         _unlockEntry(_lastWrittenIndex);
265                     }
266                     else
267                     {
268                         // The cache is going to be destroyed.
269                         // The lock can not be obtained.
270                         delete scmoClass;
271                         return SCMOClass();
272                     }
273                 
274 thilo.boehm 1.2     // The modify lock is destroyed automaticaly !
275                     return SCMOClass(*scmoClass);
276                 }
277                 
278                 SCMOClass SCMOClassCache::getSCMOClass(
279                         const char* nsName,
280                         Uint32 nsNameLen,
281                         const char* className,
282                         Uint32 classNameLen)
283                 {
284                     Uint64 theKey;
285                 
286                     // Due to the _lastSuccessIndex may contain an invalid value,
287                     // use the modulo to ensure it the index is in a valid range.
288                     Uint32 startIndex =_lastSuccessIndex % PEGASUS_SCMO_CLASS_CACHE_SIZE;
289                     Uint32 nextIndex = startIndex;
290                     // The number of used entries form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
291                     Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
292                 
293                     // This constallation would cause an infitloop below.
294                     // A miss read of global variables has happen
295 thilo.boehm 1.2     if (nextIndex > usedEntries)
296                     {
297                         // start from the beginning
298                         startIndex = 0;
299                         nextIndex = 0;
300                     }
301                 
302                     if (nsName && className && nsNameLen && classNameLen)
303                     {
304                       theKey = _generateKey(className,classNameLen,nsName,nsNameLen);
305                 
306                       // The counter i is never used as index.
307                       // It is used to ensure to look through all used entries.
308                       for (Uint32 i = 0; i < usedEntries; i++)
309                       {
310                           if(_lockEntry(nextIndex))
311                           {
312                               // does the key match for the entry and the requested class ?
313                               if ( 0 != _theCache[nextIndex].key &&
314                                   theKey == _theCache[nextIndex].key)
315                               {
316 thilo.boehm 1.2                   // To get sure we found the right class, compare name space
317                                   // and class name.
318                                   if (_sameSCMOClass(nsName,nsNameLen,className,classNameLen,
319                                                      _theCache[nextIndex].data))
320                                   {
321                                       // Yes, we got it !
322                                       SCMOClass theClass(*_theCache[nextIndex].data);
323                                       _lastSuccessIndex = nextIndex;
324                 #ifdef PEGASUS_DEBUG
325                                        _cacheReadHit++;
326                 #endif
327                                       _unlockEntry(nextIndex);
328                                       return theClass;
329                                   }
330                               }
331                               // It was the wrong entry, go to the next.
332                               _unlockEntry(nextIndex);
333                           }
334                           else
335                           {
336                               // The cache is going to be destroyed.
337 thilo.boehm 1.2               // The lock can not be obtained. Give up.
338                               return SCMOClass();
339                           }
340                           // It was the wrong entry, go to the next used entry..
341                           nextIndex = (nextIndex + 1) % usedEntries;
342                 
343                       }
344                 
345                       // If we end up here, the class is not in the cache !
346                       // We have to get it from the repositroy and add it into the cache.
347                       return _addClassToCache(nsName,nsNameLen,className,classNameLen,theKey);
348                     }
349                 
350                     return SCMOClass();
351                 }
352                 
353                 void SCMOClassCache::removeSCMOClass(
354                     CIMNamespaceName cimNameSpace,
355                     CIMName cimClassName)
356                 {
357                 
358 thilo.boehm 1.2     if (cimClassName.isNull() || cimNameSpace.isNull())
359                     {
360                         return ;
361                     }
362                 
363                    CString nsName = cimNameSpace.getString().getCString();
364                    Uint32 nsNameLen = strlen(nsName);
365                    CString clsName = cimClassName.getString().getCString();
366                    Uint32 clsNameLen = strlen(clsName);
367                 
368                    // The number of used entries form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
369                    Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
370                 
371                    Uint64  theKey = _generateKey(clsName,clsNameLen,nsName,nsNameLen);
372                 
373                    // A straight forward loop through all used entries,
374                    // ignoring the last success.
375                    for (Uint32 i = 0; i < usedEntries; i++)
376                    {
377                        if(_lockEntry(i))
378                        {
379 thilo.boehm 1.2            // does the key match for the entry and the requested class ?
380                            if ( 0 != _theCache[i].key && theKey == _theCache[i].key)
381                            {
382                                // To get sure we found the right class, compare name space
383                                // and class name.
384                                if (_sameSCMOClass(nsName,nsNameLen,clsName,clsNameLen,
385                                                   _theCache[i].data))
386                                {
387                                    // Yes, we got it !
388                                    _theCache[i].key = 0;
389                                    delete _theCache[i].data;
390                                    _theCache[i].data = 0;
391                                    _unlockEntry(i);
392                                    return;
393                                }
394                            }
395                            // It was the wrong entry, go to the next.
396                            _unlockEntry(i);
397                        }
398                        else
399                        {
400 thilo.boehm 1.2            // We do not get the lock, if the cache is going to be destroyed.
401                            return;
402                        }
403                    }
404                 }
405                 
406                 void SCMOClassCache::clear()
407                 {
408                     WriteLock modifyLock(_modifyCacheLock);
409                 
410                     if ( _dying )
411                     {
412                         // The cache is going to be destroyed.
413                         return ;
414                     }
415                 
416                     // The number of used entries form 0 to PEGASUS_SCMO_CLASS_CACHE_SIZE
417                     Uint32 usedEntries = _fillingLevel % (PEGASUS_SCMO_CLASS_CACHE_SIZE + 1);
418                 
419                     // A straight forwar loop through all used entries,
420                     // ignoring the last success.
421 thilo.boehm 1.2     for (Uint32 i = 0; i < usedEntries; i++)
422                     {
423                         if(_lockEntry(i))
424                         {
425                             _theCache[i].key = 0;
426                             delete _theCache[i].data;
427                             _theCache[i].data = 0;
428                             _unlockEntry(i);
429                         }
430                         else
431                         {
432                             // We do not get the lock, if the cache is going to be destroyed.
433                             return;
434                         }
435                     }
436                     // Reset all controll data
437                     _fillingLevel = 0;
438                     _lastSuccessIndex = 0;
439                     _lastWrittenIndex = PEGASUS_SCMO_CLASS_CACHE_SIZE-1;
440                 
441                 
442 thilo.boehm 1.2 }
443                 #ifdef PEGASUS_DEBUG
444                 void SCMOClassCache::DisplayCacheStatistics()
445                 {
446                     PEGASUS_STD(cout) << "SCMOClass Cache Statistics:" <<
447                         PEGASUS_STD(endl);
448                     PEGASUS_STD(cout) << "  Size (current/max): " <<
449                         _fillingLevel << "/" << PEGASUS_SCMO_CLASS_CACHE_SIZE <<
450                         PEGASUS_STD(endl);
451                     PEGASUS_STD(cout) << "  Requests satisfied from cache: " <<
452                         _cacheReadHit << PEGASUS_STD(endl);
453                     PEGASUS_STD(cout) << "  Requests *not* satisfied from cache: " <<
454                         _cacheReadMiss << " (implies write to cache)" << PEGASUS_STD(endl);
455                     PEGASUS_STD(cout) <<
456                         "  Cache entries \"aged out\" due to cache size constraints: " <<
457                         _cacheRemoveLRU << PEGASUS_STD(endl);
458                     PEGASUS_STD(cout) << "  Number of lock contentions: " <<
459                         _contentionCount.get() << PEGASUS_STD(endl);
460                 
461                 }
462                 #endif
463 thilo.boehm 1.2 
464                 
465                 #else // PEGASUS_USE_SCMO_CLASS_CACHE
466                 SCMOClass SCMOClassCache::getSCMOClass(
467                         const char* nsName,
468                         Uint32 nsNameLen,
469                         const char* className,
470                         Uint32 classNameLen)
471                 {
472                     if (nsName && className && nsNameLen && classNameLen)
473                     {
474                 
475                          PEGASUS_ASSERT(_resolveCallBack);
476                 
477                 
478                           SCMOClass tmp = _resolveCallBack(
479                               CIMNamespaceNameCast(String(nsName,nsNameLen)),
480                               CIMNameCast(String(className,classNameLen)));
481                 
482                           if (tmp->isEpmpty())
483                           {
484 thilo.boehm 1.2                // The requested class was not found !
485                                // The modify lock is destroyed automaticaly !
486                                return SCMOClass();
487                           }
488                 
489                           return SCMOClass(tmp);
490                     }
491                 
492                     return SCMOClass();
493                 
494                 }
495                 
496                 void SCMOClassCache::removeSCMOClass(
497                     CIMNamespaceName cimNameSpace,
498                     CIMName cimClassName)
499                 {
500                 }
501                 
502                 
503                 void SCMOClassCache::clear()
504                 {
505 thilo.boehm 1.2 }
506                 
507                 #  ifdef PEGASUS_DEBUG
508                 void SCMOClassCache::DisplayCacheStatistics(){}
509                 #  endif
510                 
511                 #endif
512                 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2