(file) Return to ObjectCache.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Repository

  1 karl  1.5 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.1 //
  3           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6           // IBM Corp.; EMC Corporation, The Open Group.
  7           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.5 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12           // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.1 //
 14           // Permission is hereby granted, free of charge, to any person obtaining a copy
 15           // of this software and associated documentation files (the "Software"), to
 16           // deal in the Software without restriction, including without limitation the
 17           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18           // sell copies of the Software, and to permit persons to whom the Software is
 19           // furnished to do so, subject to the following conditions:
 20           // 
 21           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29           //
 30           //==============================================================================
 31           //
 32           //%/////////////////////////////////////////////////////////////////////////////
 33           
 34 mike  1.1 #ifndef PegasusRepository_ObjectCache_h
 35           #define PegasusRepository_ObjectCache_h
 36           
 37           #include <Pegasus/Common/Config.h>
 38           #include <Pegasus/Common/CIMClass.h>
 39           #include <Pegasus/Common/CIMInstance.h>
 40           #include <Pegasus/Common/HashTable.h>
 41 mike  1.6 #include <Pegasus/Common/Mutex.h>
 42 mike  1.1 #include <Pegasus/Repository/Linkage.h>
 43           
 44           PEGASUS_NAMESPACE_BEGIN
 45           
 46           Uint32 ObjectCacheHash(const String& str);
 47           
 48           template<class OBJECT>
 49           class PEGASUS_REPOSITORY_LINKAGE ObjectCache
 50           {
 51           public:
 52           
 53               ObjectCache(size_t maxEntries);
 54           
 55               void put(const String& path, OBJECT& object);
 56           
 57               bool get(const String& path, OBJECT& object);
 58           
 59               bool evict(const String& path);
 60           
 61 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
 62 kumpf       1.7     void DisplayCacheStatistics()
 63 dave.sudlik 1.3     {
 64 kumpf       1.4         PEGASUS_STD(cout) << "  Size (current/max): " << _numEntries <<
 65                             "/" << _maxEntries << PEGASUS_STD(endl);
 66                         PEGASUS_STD(cout) << "  Requests satisfied from cache: " <<
 67                             _cacheReadHit << PEGASUS_STD(endl);
 68                         PEGASUS_STD(cout) << "  Requests *not* satisfied from cache: " <<
 69                             _cacheReadMiss << " (implies write to cache)" << PEGASUS_STD(endl);
 70                         PEGASUS_STD(cout) <<
 71                             "  Cache entries \"aged out\" due to cache size constraints: " <<
 72                             _cacheRemoveLRU << PEGASUS_STD(endl);
 73 dave.sudlik 1.3     }
 74                 #endif
 75                 
 76                 
 77 mike        1.1 private:
 78                 
 79                     static Uint32 _hash(const String& s)
 80                     {
 81 kumpf       1.7         return ObjectCacheHash(s);
 82 mike        1.1     }
 83                 
 84                     static bool _equal(const String& s1, const String& s2)
 85                     {
 86                         return String::equalNoCase(s1, s2);
 87                     }
 88                 
 89                     struct Entry
 90                     {
 91 kumpf       1.7         Uint32 code;
 92                         String path;
 93                         OBJECT object;
 94                         Entry* hashNext;
 95                         Entry* queueNext;
 96                         Entry* queuePrev;
 97 mike        1.1 
 98 kumpf       1.7         Entry(Uint32 code_, const String& path_, OBJECT& object_) :
 99                             code(code_), path(path_), object(object_.clone()) { }
100 mike        1.1     };
101                 
102                     enum { NUM_CHAINS = 128 };
103                 
104                     Entry* _chains[NUM_CHAINS];
105                     Entry* _front;
106                     Entry* _back;
107                     size_t _numEntries;
108                     size_t _maxEntries;
109                     Mutex _mutex;
110 dave.sudlik 1.3 
111                 #ifdef PEGASUS_DEBUG
112                     Uint32 _cacheReadHit;
113                     Uint32 _cacheReadMiss;
114                     Uint32 _cacheRemoveLRU;
115                 #endif
116                 
117                 
118 mike        1.1 };
119                 
120                 template<class OBJECT>
121 kumpf       1.7 ObjectCache<OBJECT>::ObjectCache(size_t maxEntries)
122                     : _front(0), _back(0), _numEntries(0), _maxEntries(maxEntries)
123 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
124                     , _cacheReadHit(0), _cacheReadMiss(0), _cacheRemoveLRU(0)
125                 #endif
126 mike        1.1 {
127                     memset(_chains, 0, sizeof(_chains));
128                 }
129                 
130                 template<class OBJECT>
131                 void ObjectCache<OBJECT>::put(const String& path, OBJECT& object)
132                 {
133                     if (_maxEntries == 0)
134 kumpf       1.7         return;
135 mike        1.1 
136 kumpf       1.7.4.1     AutoMutex lock(_mutex);
137 mike        1.1     
138                         //// Update object if it is already in cache:
139                     
140                         Uint32 code = _hash(path);
141                         Uint32 index = code % NUM_CHAINS;
142                     
143                         for (Entry* p = _chains[index]; p; p = p->hashNext)
144                         {
145                             if (code == p->code && _equal(p->path, path))
146 kumpf       1.7             {
147                                 // Update the repository.
148                                 p->object = object.clone();
149                                 return;
150                             }
151 mike        1.1         }
152                     
153                         //// Add to hash table:
154                     
155                         Entry* entry = new Entry(code, path, object);
156                         entry->hashNext = _chains[index];
157                         _chains[index] = entry;
158                     
159                         //// Add to back of FIFO queue:
160                     
161                         entry->queueNext = 0;
162                     
163                         if (_back)
164                         {
165 kumpf       1.7             _back->queueNext = entry;
166                             entry->queuePrev = _back;
167                             _back = entry;
168 mike        1.1         }
169                         else
170                         {
171 kumpf       1.7             _front = entry;
172                             _back = entry;
173                             entry->queuePrev = 0;
174 mike        1.1         }
175                     
176                         _numEntries++;
177                     
178                         //// Evict LRU entry if necessary (from front).
179                     
180                         if (_numEntries > _maxEntries)
181                         {
182 kumpf       1.7             Entry* entry = _front;
183 mike        1.1     
184 kumpf       1.7             //// Remove from hash table first.
185 mike        1.1     
186 kumpf       1.7             Uint32 index = entry->code % NUM_CHAINS;
187                             Entry* hashPrev = 0;
188 mike        1.1     
189 kumpf       1.7             for (Entry* p = _chains[index]; p; p = p->hashNext)
190                             {
191                                 if (p->code == entry->code && _equal(p->path, entry->path))
192                                 {
193                                     if (hashPrev)
194                                         hashPrev->hashNext = p->hashNext;
195                                     else
196                                         _chains[index] = p->hashNext;
197 mike        1.1     
198 kumpf       1.7                     break;
199                                 }
200 mike        1.1     
201 kumpf       1.7                 hashPrev = p;
202                             }
203 mike        1.1     
204 kumpf       1.7             //// Now remove from queue:
205 mike        1.1     
206 kumpf       1.7             _front = entry->queueNext;
207 mike        1.1     
208 kumpf       1.7             if (_front)
209                                 _front->queuePrev = 0;
210 mike        1.1     
211 kumpf       1.7             delete entry;
212                             _numEntries--;
213 dave.sudlik 1.3     #ifdef PEGASUS_DEBUG
214                         _cacheRemoveLRU++;
215                     #endif
216 mike        1.1         }
217                     }
218                     
219                     template<class OBJECT>
220                     bool ObjectCache<OBJECT>::get(const String& path, OBJECT& object)
221                     {
222                         if (_maxEntries == 0)
223 kumpf       1.7             return false;
224 mike        1.1     
225 kumpf       1.7.4.1     AutoMutex lock(_mutex);
226 mike        1.1     
227                         //// Search cache for object.
228                     
229                         Uint32 code = _hash(path);
230                         Uint32 index = code % NUM_CHAINS;
231                     
232                         for (Entry* p = _chains[index]; p; p = p->hashNext)
233                         {
234                             if (code == p->code && _equal(p->path, path))
235 kumpf       1.7             {
236                                 object = p->object.clone();
237 dave.sudlik 1.3     #ifdef PEGASUS_DEBUG
238                             _cacheReadHit++;
239                     #endif
240 kumpf       1.7                 return true;
241                             }
242 mike        1.1         }
243                     
244                         /// Not found!
245                     
246 dave.sudlik 1.3     #ifdef PEGASUS_DEBUG
247                         _cacheReadMiss++;
248                     #endif
249 mike        1.1         return false;
250                     }
251                     
252                     template<class OBJECT>
253                     bool ObjectCache<OBJECT>::evict(const String& path)
254                     {
255                         if (_maxEntries == 0)
256 kumpf       1.7             return false;
257 mike        1.1     
258 kumpf       1.7.4.1     AutoMutex lock(_mutex);
259 mike        1.1     
260                         //// Find and remove the given element.
261                     
262                         Uint32 code = _hash(path);
263                         Uint32 index = code % NUM_CHAINS;
264                         Entry* hashPrev = 0;
265                     
266                         for (Entry* p = _chains[index]; p; p = p->hashNext)
267                         {
268                             if (code == p->code && _equal(p->path, path))
269 kumpf       1.7             {
270                                 // Remove from hash chain:
271 mike        1.1     
272                                 if (hashPrev)
273                                     hashPrev->hashNext = p->hashNext;
274                                 else
275                                     _chains[index] = p->hashNext;
276                     
277 kumpf       1.7                 // Remove from queue:
278 mike        1.1     
279 kumpf       1.7                 if (p->queuePrev)
280                                     p->queuePrev->queueNext = p->queueNext;
281                                 else
282                                     _front = p->queueNext;
283 mike        1.1     
284 kumpf       1.7                 if (p->queueNext)
285                                     p->queueNext->queuePrev = p->queuePrev;
286                                 else
287                                     _back = p->queuePrev;
288 mike        1.1     
289 kumpf       1.7                 // Delete the entry and update the number of entries.
290 mike        1.1     
291 kumpf       1.7                 delete p;
292                                 _numEntries--;
293 mike        1.1     
294 kumpf       1.7                 return true;
295                             }
296 mike        1.1     
297 kumpf       1.7             hashPrev = p;
298 mike        1.1         }
299                     
300                         //// Not found!
301                     
302                         return false;
303                     }
304                     
305                     PEGASUS_NAMESPACE_END
306                     
307                     #endif /* PegasusRepository_ObjectCache_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2