00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef _PERSPRODUCTCACHE_H_
00033 #define _PERSPRODUCTCACHE_H_
00034
00035
00036
00037
00038 #include <map>
00039 #include <list>
00040 #include <memory>
00041
00042
00043 #include "mutex.h"
00044 #include "chrono.h"
00045 #include "period.h"
00046 #include "persproduct.h"
00047 #include "resourcefwd.h"
00048
00049
00050
00051 namespace OSB_LIB {
00052
00077 class PersProductCache {
00078 public:
00080 explicit PersProductCache(bool useLocks);
00082 ~PersProductCache();
00083 private:
00085 PersProductCache(const PersProductCache&);
00087 PersProductCache& operator=(PersProductCache&);
00088
00089 public:
00091 void setMaxSize(long maxSize);
00098 void setCacheTime(long cacheTime);
00099
00117 ReadGuard<PersProduct*> find(
00118 const OSB_DB::Session& session,
00119 const ResourceKey& resourceKey,
00120 const DateTime& timestamp
00121 );
00122
00124 void logStats() const;
00125
00126
00127 private:
00128
00129 class Entry;
00139 typedef std::map<PersProduct::Oid, Entry*> PersProducts;
00140
00142 enum GuardStatus {
00144 ppFound = 0,
00146 ppNotFound
00147 };
00148
00150 struct Key {
00152 inline Key(
00153 const ResourceKey& resourceKey
00154 );
00155
00157 inline Key(
00158 const ResourceKey& resourceKey,
00159 const Period& assigned
00160 );
00161
00167 inline bool operator<(const Key& rhs) const;
00168
00175 inline void mkAssignPeriod();
00176
00178 ResourceKey resourceKey_;
00183 Period assigned_;
00184 };
00185
00187 struct Stats {
00189 unsigned long hits_;
00191 unsigned long unchanged_;
00193 unsigned long reloads_;
00195 unsigned long loads_;
00197 unsigned long keysAdded_;
00199 unsigned long notFound_;
00201 unsigned long evicted_;
00202
00204 Stats();
00205 };
00206
00213 typedef std::map<Key, PersProduct::Oid> Keys;
00214
00218 typedef std::list<PersProduct::Oid> Queue;
00219
00220 private:
00222 Entry* find(
00223 const Key& key
00224 );
00225
00227 Entry* load(
00228 const OSB_DB::Session& session,
00229 Key& key,
00230 const DateTime& timestamp,
00231 bool isReload
00232 );
00233
00235 Entry* add(
00236 Key& key,
00237 const PersProduct& persProduct
00238 );
00239
00241 Entry* addMiss(
00242 const OSB_DB::Session& session,
00243 Key& key,
00244 const DateTime& timestamp
00245 );
00246
00248 void addKey(
00249 Entry* entry,
00250 Key& key
00251 );
00252
00254 void remove(
00255 const PersProduct::Oid& ppId,
00256 bool force
00257 );
00258
00260 void adjustSize();
00261
00262 private:
00264 PersProducts persProducts_;
00266 Keys resources_;
00268 Queue queue_;
00269
00271 bool useLocks_;
00273 unsigned long maxSize_;
00278 long cacheTime_;
00279
00281 long nextMiss_;
00282
00284 Mutex mutex_;
00286 MutexUnlock unlock_;
00287
00289 Stats stats_;
00290 };
00291
00295 class PersProductCache::Entry {
00297 friend class PersProductCache;
00299 static bool useLocks_;
00300 public:
00302 Entry(
00303 const PersProduct& pp,
00304 long cacheTime
00305 );
00306
00307 private:
00309 Entry(const Entry&);
00311 Entry& operator=(const Entry&);
00312
00313 public:
00314 ReadGuard<PersProduct*> readLock();
00315 RwGuard writeLock(bool wait);
00316
00317 public:
00324 PersProduct persProduct_;
00331 DateTime expires_;
00333 std::vector<Keys::iterator> keys_;
00335 Queue::iterator queuePos_;
00336 private:
00338 RwMutex mutex_;
00339 };
00340 }
00341
00342
00343
00344 namespace OSB_LIB {
00345
00346
00347 inline PersProductCache::Key::Key(
00348 const ResourceKey& resourceKey
00349 ) : resourceKey_(resourceKey)
00350 {
00351
00352 }
00353
00354 inline PersProductCache::Key::Key(
00355 const ResourceKey& resourceKey,
00356 const Period& assigned
00357 ) : resourceKey_(resourceKey), assigned_(assigned)
00358 {
00359
00360 }
00361
00362 inline bool PersProductCache::Key::operator<(
00363 const PersProductCache::Key& rhs
00364 ) const
00365 {
00366 if (resourceKey_ < rhs.resourceKey_) return true;
00367 if (rhs.resourceKey_ < resourceKey_) return false;
00368 return assigned_.less(rhs.assigned_);
00369 }
00370
00371 inline void PersProductCache::Key::mkAssignPeriod()
00372 {
00373 if (assigned_.isTimestamp() &&
00374 assigned_.to() != DateTime::max()) {
00375 assigned_ = Period(assigned_.from(),
00376 assigned_.to().addSeconds(1));
00377 }
00378 }
00379 }
00380 #endif // #ifndef _PERSPRODUCTCACHE_H_