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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2