(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           // Author: Mike Brasher, Inova Europe (mbrasher@bmc.com)
 33           //
 34 mike  1.1 //%/////////////////////////////////////////////////////////////////////////////
 35           
 36           #ifndef PegasusRepository_ObjectCache_h
 37           #define PegasusRepository_ObjectCache_h
 38           
 39           #include <Pegasus/Common/Config.h>
 40           #include <Pegasus/Common/CIMClass.h>
 41           #include <Pegasus/Common/CIMInstance.h>
 42           #include <Pegasus/Common/HashTable.h>
 43 mike  1.6 #include <Pegasus/Common/Mutex.h>
 44 mike  1.1 #include <Pegasus/Repository/Linkage.h>
 45           
 46           PEGASUS_NAMESPACE_BEGIN
 47           
 48           Uint32 ObjectCacheHash(const String& str);
 49           
 50           template<class OBJECT>
 51           class PEGASUS_REPOSITORY_LINKAGE ObjectCache
 52           {
 53           public:
 54           
 55               ObjectCache(size_t maxEntries);
 56           
 57               void put(const String& path, OBJECT& object);
 58           
 59               bool get(const String& path, OBJECT& object);
 60           
 61               bool evict(const String& path);
 62           
 63 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
 64                     void DisplayCacheStatistics(void)
 65                     {
 66 kumpf       1.4         PEGASUS_STD(cout) << "  Size (current/max): " << _numEntries <<
 67                             "/" << _maxEntries << PEGASUS_STD(endl);
 68                         PEGASUS_STD(cout) << "  Requests satisfied from cache: " <<
 69                             _cacheReadHit << PEGASUS_STD(endl);
 70                         PEGASUS_STD(cout) << "  Requests *not* satisfied from cache: " <<
 71                             _cacheReadMiss << " (implies write to cache)" << PEGASUS_STD(endl);
 72                         PEGASUS_STD(cout) <<
 73                             "  Cache entries \"aged out\" due to cache size constraints: " <<
 74                             _cacheRemoveLRU << PEGASUS_STD(endl);
 75 dave.sudlik 1.3     }
 76                 #endif
 77                 
 78                 
 79 mike        1.1 private:
 80                 
 81                     static Uint32 _hash(const String& s)
 82                     {
 83                 	return ObjectCacheHash(s);
 84                     }
 85                 
 86                     static bool _equal(const String& s1, const String& s2)
 87                     {
 88                         return String::equalNoCase(s1, s2);
 89                     }
 90                 
 91                     struct Entry
 92                     {
 93                 	Uint32 code;
 94                 	String path;
 95                 	OBJECT object;
 96                 	Entry* hashNext;
 97                 	Entry* queueNext;
 98                 	Entry* queuePrev;
 99                 
100 mike        1.1 	Entry(Uint32 code_, const String& path_, OBJECT& object_) :
101                 	    code(code_), path(path_), object(object_.clone()) { }
102                     };
103                 
104                     enum { NUM_CHAINS = 128 };
105                 
106                     Entry* _chains[NUM_CHAINS];
107                     Entry* _front;
108                     Entry* _back;
109                     size_t _numEntries;
110                     size_t _maxEntries;
111                     Mutex _mutex;
112 dave.sudlik 1.3 
113                 #ifdef PEGASUS_DEBUG
114                     Uint32 _cacheReadHit;
115                     Uint32 _cacheReadMiss;
116                     Uint32 _cacheRemoveLRU;
117                 #endif
118                 
119                 
120 mike        1.1 };
121                 
122                 template<class OBJECT>
123                 ObjectCache<OBJECT>::ObjectCache(size_t maxEntries) : 
124                     _front(0), _back(0), _numEntries(0), _maxEntries(maxEntries)
125 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
126                     , _cacheReadHit(0), _cacheReadMiss(0), _cacheRemoveLRU(0)
127                 #endif
128 mike        1.1 {
129                     memset(_chains, 0, sizeof(_chains));
130                 }
131                 
132                 template<class OBJECT>
133                 void ObjectCache<OBJECT>::put(const String& path, OBJECT& object)
134                 {
135                     if (_maxEntries == 0)
136                 	return;
137                 
138 mike        1.6     _mutex.lock();
139 mike        1.1 
140                     //// Update object if it is already in cache:
141                 
142                     Uint32 code = _hash(path);
143                     Uint32 index = code % NUM_CHAINS;
144                 
145                     for (Entry* p = _chains[index]; p; p = p->hashNext)
146                     {
147                         if (code == p->code && _equal(p->path, path))
148                 	{
149                 	    // Update the repository.
150                 	    p->object = object.clone();
151                 	    _mutex.unlock();
152                 	    return;
153                 	}
154                     }
155                 
156                     //// Add to hash table:
157                 
158                     Entry* entry = new Entry(code, path, object);
159                     entry->hashNext = _chains[index];
160 mike        1.1     _chains[index] = entry;
161                 
162                     //// Add to back of FIFO queue:
163                 
164                     entry->queueNext = 0;
165                 
166                     if (_back)
167                     {
168                 	_back->queueNext = entry;
169                 	entry->queuePrev = _back;
170                 	_back = entry;
171                     }
172                     else
173                     {
174                 	_front = entry;
175                 	_back = entry;
176                 	entry->queuePrev = 0;
177                     }
178                 
179                     _numEntries++;
180                 
181 mike        1.1     //// Evict LRU entry if necessary (from front).
182                 
183                     if (_numEntries > _maxEntries)
184                     {
185                 	Entry* entry = _front;
186                 
187                 	//// Remove from hash table first.
188                 
189                 	Uint32 index = entry->code % NUM_CHAINS;
190                 	Entry* hashPrev = 0;
191                 
192                 	for (Entry* p = _chains[index]; p; p = p->hashNext)
193                 	{
194                 	    if (p->code == entry->code && _equal(p->path, entry->path))
195                 	    {
196                 		if (hashPrev)
197                 		    hashPrev->hashNext = p->hashNext;
198                 		else
199                 		    _chains[index] = p->hashNext;
200                 
201                 		break;
202 mike        1.1 	    }
203                 
204                 	    hashPrev = p;
205                 	}
206                 
207                 	//// Now remove from queue:
208                 
209                 	_front = entry->queueNext;
210                 
211                 	if (_front)
212                 	    _front->queuePrev = 0;
213                 
214                 	delete entry;
215                 	_numEntries--;
216 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
217                     _cacheRemoveLRU++;
218                 #endif
219 mike        1.1     }
220                 
221                     _mutex.unlock();
222                     return;
223                 }
224                 
225                 template<class OBJECT>
226                 bool ObjectCache<OBJECT>::get(const String& path, OBJECT& object)
227                 {
228                     if (_maxEntries == 0)
229                 	return false;
230                 
231 mike        1.6     _mutex.lock();
232 mike        1.1 
233                     //// Search cache for object.
234                 
235                     Uint32 code = _hash(path);
236                     Uint32 index = code % NUM_CHAINS;
237                 
238                     for (Entry* p = _chains[index]; p; p = p->hashNext)
239                     {
240                         if (code == p->code && _equal(p->path, path))
241                 	{
242                 	    object = p->object.clone();
243 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
244                         _cacheReadHit++;
245                 #endif
246 mike        1.1 	    _mutex.unlock();
247                 	    return true;
248                 	}
249                     }
250                 
251                     /// Not found!
252                 
253 dave.sudlik 1.3 #ifdef PEGASUS_DEBUG
254                     _cacheReadMiss++;
255                 #endif
256 mike        1.1     _mutex.unlock();
257                     return false;
258                 }
259                 
260                 template<class OBJECT>
261                 bool ObjectCache<OBJECT>::evict(const String& path)
262                 {
263                     if (_maxEntries == 0)
264                 	return false;
265                 
266 mike        1.6     _mutex.lock();
267 mike        1.1 
268                     //// Find and remove the given element.
269                 
270                     Uint32 code = _hash(path);
271                     Uint32 index = code % NUM_CHAINS;
272                     Entry* hashPrev = 0;
273                 
274                     for (Entry* p = _chains[index]; p; p = p->hashNext)
275                     {
276                         if (code == p->code && _equal(p->path, path))
277                 	{
278                 	    // Remove from hash chain:
279                 
280                             if (hashPrev)
281                                 hashPrev->hashNext = p->hashNext;
282                             else
283                                 _chains[index] = p->hashNext;
284                 
285                 	    // Remove from queue:
286                 
287                 	    if (p->queuePrev)
288 mike        1.1 		p->queuePrev->queueNext = p->queueNext;
289 mike        1.2 	    else
290                 		_front = p->queueNext;
291 mike        1.1 
292                 	    if (p->queueNext)
293                 		p->queueNext->queuePrev = p->queuePrev;
294 mike        1.2 	    else
295                 		_back = p->queuePrev;
296 mike        1.1 
297                 	    // Delete the entry and update the number of entries.
298                 
299                 	    delete p;
300                 	    _numEntries--;
301                 
302                 	    _mutex.unlock();
303                 	    return true;
304                 	}
305                 
306                 	hashPrev = p;
307                     }
308                 
309                     //// Not found!
310                 
311                     _mutex.unlock();
312                     return false;
313                 }
314                 
315                 PEGASUS_NAMESPACE_END
316                 
317 mike        1.1 #endif /* PegasusRepository_ObjectCache_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2