Fennel: /home/pub/open/dev/fennel/cache/CachePage.h Source File (original) (raw)

00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 #ifndef Fennel_CachePage_Included 00025 #define Fennel_CachePage_Included 00026 00027 #include "fennel/synch/SynchObj.h" 00028 #include "fennel/synch/SXMutex.h" 00029 #include "fennel/device/RandomAccessRequest.h" 00030 #include "fennel/cache/Cache.h" 00031 #include "fennel/cache/CacheAllocator.h" 00032 #include "fennel/common/SysCallExcn.h" 00033 00034 FENNEL_BEGIN_NAMESPACE 00035 00036 class Cache; 00037 class MappedPageListener; 00038 00039 template <class PageT,class VictimPolicyT> 00040 class CacheImpl; 00041 00045 class FENNEL_CACHE_EXPORT PageBucketListNode 00046 : public IntrusiveListNode 00047 { 00048 }; 00049 00056 class FENNEL_CACHE_EXPORT CachePage 00057 : public PageBucketListNode, private RandomAccessRequestBinding 00058 { 00059 public: 00064 enum DataStatus { 00068 DATA_INVALID, 00069 00073 DATA_ERROR, 00074 00079 DATA_CLEAN, 00080 00084 DATA_DIRTY, 00085 00089 DATA_WRITE, 00090 00095 DATA_READ 00096 }; 00097 00098 private: 00099 template <class PageT,class VictimPolicyT> 00100 friend class CacheImpl; 00101 00102 00103 00104 00108 Cache &cache; 00109 00114 StrictMutex mutex; 00115 00120 SXMutex lock; 00121 00125 PBuffer pBuffer; 00126 00127
00128
00129
00130 00135 BlockId blockId; 00136 00143 uint nReferences; 00144 00149 LocalCondition ioCompletionCondition; 00150 00155 MappedPageListener *pMappedPageListener; 00156 00160 DataStatus dataStatus; 00161 00162 00163 00164 00168 bool hasBlockId() const 00169 { 00170 return blockId != NULL_BLOCK_ID; 00171 } 00172 00178 void waitForPendingIO(StrictMutexGuard &guard) 00179 { 00180 ioCompletionCondition.wait(guard); 00181 } 00182 00186 bool isExclusiveLockHeld() const 00187 { 00188
00189 return isScratchLocked() || lock.isLocked(LOCKMODE_X); 00190 } 00191 00192 00193 00194 00195 virtual void notifyTransferCompletion(bool bSuccess); 00196 virtual PBuffer getBuffer() const; 00197 virtual uint getBufferSize() const; 00198 00199 public: 00200 explicit CachePage(Cache &,PBuffer); 00201 virtual ~CachePage(); 00202 00206 Cache &getCache() 00207 { 00208 return cache; 00209 } 00210 00215 bool isDirty() const 00216 { 00217 return dataStatus == DATA_DIRTY; 00218 } 00219 00223 bool isTransferInProgress() const 00224 { 00225 return (dataStatus >= DATA_WRITE); 00226 } 00227 00231 bool isDataValid() const 00232 { 00233 return (dataStatus >= DATA_CLEAN) && (dataStatus <= DATA_WRITE); 00234 } 00235 00239 bool isDataError() const 00240 { 00241 return (dataStatus == DATA_ERROR); 00242 } 00243 00247 BlockId getBlockId() const 00248 { 00249 return blockId; 00250 } 00251 00260 PConstBuffer getReadableData() const 00261 { 00262 assert(isDataValid()); 00263 assert(lock.isLocked(LOCKMODE_S) || isExclusiveLockHeld()); 00264 return pBuffer; 00265 } 00266 00274 PBuffer getWritableData() 00275 { 00276 assert(isExclusiveLockHeld()); 00277 assert(!isDataError()); 00278 assert(!isTransferInProgress()); 00279
00280
00281 if (!isDirty()) { 00282 getCache().markPageDirty(*this); 00283 } 00284 return pBuffer; 00285 } 00286 00290 bool isScratchLocked() const; 00291 00295 MappedPageListener *getMappedPageListener() const 00296 { 00297 assert(hasBlockId()); 00298 return pMappedPageListener; 00299 } 00300 00309 bool tryUpgrade(TxnId txnId) 00310 { 00311 StrictMutexGuard pageGuard(mutex); 00312 if (isTransferInProgress()) { 00313 return false; 00314 } 00315 #ifdef DEBUG 00316 int errorCode; 00317 if (getCache().getAllocator().setProtection( 00318 pBuffer, getCache().getPageSize(), false, &errorCode)) 00319 { 00320 throw SysCallExcn("memory protection failed", errorCode); 00321 } 00322 #endif 00323 return lock.tryUpgrade(txnId); 00324 } 00325 00332 void upgrade(TxnId txnId) 00333 { 00334 StrictMutexGuard pageGuard(mutex); 00335 while (isTransferInProgress()) { 00336 waitForPendingIO(pageGuard); 00337 } 00338 #ifdef DEBUG 00339 int errorCode; 00340 if (getCache().getAllocator().setProtection( 00341 pBuffer, getCache().getPageSize(), false, &errorCode)) 00342 { 00343 throw SysCallExcn("memory protection failed", errorCode); 00344 } 00345 #endif 00346 bool rc = lock.tryUpgrade(txnId); 00347 assert(rc); 00348 } 00349 00356 void swapBuffers(CachePage &other); 00357 }; 00358 00359 FENNEL_END_NAMESPACE 00360 00361 #endif 00362 00363