PagingTestBase.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/test/PagingTestBase.cpp#13 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2005-2009 SQLstream, Inc.
00006 // Copyright (C) 2005-2009 LucidEra, Inc.
00007 // Portions Copyright (C) 1999-2009 John V. Sichi
00008 //
00009 // This program is free software; you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by the Free
00011 // Software Foundation; either version 2 of the License, or (at your option)
00012 // any later version approved by The Eigenbase Project.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/test/PagingTestBase.h"
00026 #include "fennel/common/FileSystem.h"
00027 #include "fennel/device/RandomAccessFileDevice.h"
00028 #include "fennel/synch/Thread.h"
00029 #include "fennel/cache/CachePage.h"
00030 #include "fennel/cache/CacheImpl.h"
00031 #include "fennel/cache/RandomVictimPolicy.h"
00032 #include <boost/test/test_tools.hpp>
00033 
00034 
00035 #include <functional>
00036 
00037 using namespace fennel;
00038 
00039 static boost::thread_specific_ptr<std::subtractive_rng> g_pRNG;
00040 
00041 void PagingTestBase::threadInit()
00042 {
00043     ThreadedTestBase::threadInit();
00044     g_pRNG.reset(new std::subtractive_rng());
00045 }
00046 
00047 void PagingTestBase::threadTerminate()
00048 {
00049     g_pRNG.reset();
00050     ThreadedTestBase::threadTerminate();
00051 }
00052 
00053 uint PagingTestBase::generateRandomNumber(uint iMax)
00054 {
00055     return (*g_pRNG)(iMax);
00056 }
00057 
00058 void PagingTestBase::fillPage(CachePage &page,uint x)
00059 {
00060     uint *p = reinterpret_cast<uint *>(page.getWritableData());
00061     assert(cbPageUsable);
00062     uint n = cbPageUsable / sizeof(uint);
00063     for (uint i = 0; i < n; i++) {
00064         p[i] = x + i;
00065     }
00066     uint r = generateRandomNumber(n);
00067     p[r] = 0;
00068 }
00069 
00070 void PagingTestBase::verifyPage(CachePage &page,uint x)
00071 {
00072     uint const *p = reinterpret_cast<uint const *>(page.getReadableData());
00073     assert(cbPageUsable);
00074     uint n = cbPageUsable / sizeof(uint);
00075     uint nZeros = 0;
00076     for (uint i = 0; i < n; i++) {
00077         if (p[i] != x + i) {
00078             assert(!p[i]);
00079             nZeros++;
00080         }
00081     }
00082     assert(nZeros < 2);
00083 }
00084 
00085 bool PagingTestBase::testOp(OpType opType,uint iPage,bool bNice)
00086 {
00087     CachePage *pPage = lockPage(opType,iPage);
00088     LockMode lockMode = getLockMode(opType);
00089     if (!pPage) {
00090         // must be NoWait locking failed
00091         assert(lockMode >= LOCKMODE_S_NOWAIT);
00092         return false;
00093     }
00094     CachePage &page = *pPage;
00095     if (lockMode == LOCKMODE_S
00096         || lockMode == LOCKMODE_S_NOWAIT)
00097     {
00098         verifyPage(page,iPage);
00099     } else {
00100         fillPage(page,iPage);
00101     }
00102     switch (lockMode) {
00103     case LOCKMODE_X_NOWAIT:
00104         lockMode = LOCKMODE_X;
00105         break;
00106     case LOCKMODE_S_NOWAIT:
00107         lockMode = LOCKMODE_S;
00108         break;
00109     default:
00110         break;
00111     }
00112     if (bNice) {
00113         getCache().nicePage(page);
00114     }
00115     unlockPage(page,lockMode);
00116     return true;
00117 }
00118 
00119 char const *PagingTestBase::getOpName(OpType opType)
00120 {
00121     switch (opType) {
00122     case OP_ALLOCATE:
00123         return "allocate";
00124     case OP_READ_SEQ:
00125         return "sequential read";
00126     case OP_WRITE_SEQ:
00127         return "sequential write";
00128     case OP_READ_RAND:
00129         return "random read";
00130     case OP_WRITE_RAND:
00131         return "random write";
00132     case OP_READ_NOWAIT:
00133         return "read no-wait";
00134     case OP_WRITE_NOWAIT:
00135         return "write no-wait";
00136     case OP_WRITE_SKIP:
00137         return "write every n pages";
00138     default:
00139         permAssert(false);
00140     }
00141 }
00142 
00143 LockMode PagingTestBase::getLockMode(OpType opType)
00144 {
00145     switch (opType) {
00146     case OP_ALLOCATE:
00147         return LOCKMODE_X;
00148     case OP_READ_SEQ:
00149         return LOCKMODE_S;
00150     case OP_WRITE_SEQ:
00151         return LOCKMODE_X;
00152     case OP_READ_RAND:
00153         return LOCKMODE_S;
00154     case OP_WRITE_RAND:
00155         return LOCKMODE_X;
00156     case OP_READ_NOWAIT:
00157         return LOCKMODE_S_NOWAIT;
00158     case OP_WRITE_NOWAIT:
00159         return LOCKMODE_X_NOWAIT;
00160     case OP_WRITE_SKIP:
00161         return LOCKMODE_X;
00162     default:
00163         permAssert(false);
00164     }
00165 }
00166 
00167 void PagingTestBase::testSequentialOp(OpType opType)
00168 {
00169     uint n = 0;
00170     for (uint i = 0; i < nDiskPages; i++) {
00171         if (testOp(opType,i,true)) {
00172             n++;
00173         }
00174     }
00175     StrictMutexGuard mutexGuard(logMutex);
00176     BOOST_MESSAGE(
00177         "completed " << n << " " << getOpName(opType) << " ops");
00178 }
00179 
00180 void PagingTestBase::testRandomOp(OpType opType)
00181 {
00182     uint n = 0;
00183     for (uint i = 0; i < nRandomOps; i++) {
00184         uint iPage = generateRandomNumber(nDiskPages);
00185         bool bNice = (generateRandomNumber(nRandomOps) == 0);
00186         if (testOp(opType,iPage,bNice)) {
00187             n++;
00188         }
00189     }
00190     StrictMutexGuard mutexGuard(logMutex);
00191     BOOST_MESSAGE(
00192         "completed " << n << " " << getOpName(opType) << " ops");
00193 
00194 }
00195 
00196 void PagingTestBase::testSkipOp(OpType opType, uint n)
00197 {
00198     uint numOps = 0;
00199     for (uint i = 0; i < nDiskPages; i += n) {
00200         if (testOp(opType,i,true)) {
00201             numOps++;
00202         }
00203     }
00204     StrictMutexGuard mutexGuard(logMutex);
00205     BOOST_MESSAGE(
00206         "completed " << numOps << " " << getOpName(opType) << " ops");
00207 }
00208 
00209 void PagingTestBase::testScratch()
00210 {
00211     for (uint i = 0; i < nRandomOps; i++) {
00212         CachePage &page = getCache().lockScratchPage();
00213         fillPage(page,generateRandomNumber(10000));
00214         getCache().unlockPage(page,LOCKMODE_X);
00215     }
00216     StrictMutexGuard mutexGuard(logMutex);
00217     BOOST_MESSAGE("completed " << nRandomOps << " random scratch ops");
00218 }
00219 
00220 void PagingTestBase::testPrefetch()
00221 {
00222     // TODO: parameterize this
00223     uint n = 3;
00224     for (uint i = 0; i < n; i++) {
00225         uint iPage = generateRandomNumber(nDiskPages);
00226         prefetchPage(iPage);
00227     }
00228     // give the prefetches a chance to complete
00229     snooze(1);
00230     StrictMutexGuard mutexGuard(logMutex);
00231     BOOST_MESSAGE("completed " << n << " random prefetch ops");
00232 }
00233 
00234 void PagingTestBase::testPrefetchBatch()
00235 {
00236     // TODO: parameterize this
00237     uint n = 2;
00238     uint nPagesPerBatch = 4;
00239     for (uint i = 0; i < n; i++) {
00240         uint iPage = generateRandomNumber(nDiskPages - nPagesPerBatch);
00241         prefetchBatch(iPage,nPagesPerBatch);
00242     }
00243     // give the prefetches a chance to complete
00244     snooze(1);
00245     StrictMutexGuard mutexGuard(logMutex);
00246     BOOST_MESSAGE("completed " << n << " random prefetch batch ops");
00247 }
00248 
00249 void PagingTestBase::testAllocateAll()
00250 {
00251     testSequentialOp(OP_ALLOCATE);
00252 }
00253 
00254 void PagingTestBase::testSequentialRead()
00255 {
00256     testSequentialOp(OP_READ_SEQ);
00257 }
00258 
00259 void PagingTestBase::testSequentialWrite()
00260 {
00261     testSequentialOp(OP_WRITE_SEQ);
00262 }
00263 
00264 void PagingTestBase::testRandomRead()
00265 {
00266     testRandomOp(OP_READ_RAND);
00267 }
00268 
00269 void PagingTestBase::testRandomWrite()
00270 {
00271     testRandomOp(OP_WRITE_RAND);
00272 }
00273 
00274 void PagingTestBase::testSkipWrite(uint n)
00275 {
00276     testSkipOp(OP_WRITE_SKIP, n);
00277 }
00278 
00279 void PagingTestBase::testAllocate()
00280 {
00281     permAssert(false);
00282 }
00283 
00284 void PagingTestBase::testDeallocate()
00285 {
00286     permAssert(false);
00287 }
00288 
00289 void PagingTestBase::testCheckpoint()
00290 {
00291     DeviceIdPagePredicate pagePredicate(dataDeviceId);
00292     getCache().checkpointPages(pagePredicate,CHECKPOINT_FLUSH_ALL);
00293 }
00294 
00295 void PagingTestBase::testCheckpointGuarded()
00296 {
00297     snooze(nSecondsBetweenCheckpoints);
00298     StrictMutexGuard logGuard(logMutex);
00299     BOOST_MESSAGE("checkpoint started");
00300     logGuard.unlock();
00301     SXMutexExclusiveGuard checkpointExclusiveGuard(checkpointMutex);
00302     testCheckpoint();
00303     checkpointExclusiveGuard.unlock();
00304     logGuard.lock();
00305     BOOST_MESSAGE("checkpoint completed");
00306 }
00307 
00308 void PagingTestBase::testCacheResize()
00309 {
00310     snooze(nSeconds / 3);
00311     getCache().setAllocatedPageCount(nMemPages / 2);
00312     StrictMutexGuard mutexGuard(logMutex);
00313     BOOST_MESSAGE("shrank cache");
00314     mutexGuard.unlock();
00315     snooze(nSeconds / 3);
00316     getCache().setAllocatedPageCount(nMemPages - 1);
00317     mutexGuard.lock();
00318     BOOST_MESSAGE("expanded cache");
00319     mutexGuard.unlock();
00320 }
00321 
00322 PagingTestBase::PagingTestBase()
00323 {
00324     nRandomOps = configMap.getIntParam("randomOps",5000);
00325     nSecondsBetweenCheckpoints = configMap.getIntParam("checkpointInterval",20);
00326     bTestResize = configMap.getIntParam("resizeCache",1);
00327     checkpointMutex.setSchedulingPolicy(SXMutex::SCHEDULE_FAVOR_EXCLUSIVE);
00328 
00329     threadCounts.resize(OP_MAX,-1);
00330 
00331     threadCounts[OP_READ_SEQ] = configMap.getIntParam(
00332         "readSeqThreads",-1);
00333     threadCounts[OP_WRITE_SEQ] = configMap.getIntParam(
00334         "writeSeqThreads",-1);
00335     threadCounts[OP_READ_RAND] = configMap.getIntParam(
00336         "readRandThreads",-1);
00337     threadCounts[OP_WRITE_RAND] = configMap.getIntParam(
00338         "writeRandThreads",-1);
00339     threadCounts[OP_READ_NOWAIT] = configMap.getIntParam(
00340         "readNoWaitThreads",-1);
00341     threadCounts[OP_WRITE_NOWAIT] = configMap.getIntParam(
00342         "writeNoWaitThreads",-1);
00343     threadCounts[OP_WRITE_SKIP] = configMap.getIntParam(
00344         "writeSkipThreads",-1);
00345     threadCounts[OP_SCRATCH] = configMap.getIntParam(
00346         "scratchThreads",-1);
00347     threadCounts[OP_PREFETCH] = configMap.getIntParam(
00348         "prefetchThreads",-1);
00349     threadCounts[OP_PREFETCH_BATCH] = configMap.getIntParam(
00350         "prefetchBatchThreads",-1);
00351     threadCounts[OP_ALLOCATE] = configMap.getIntParam(
00352         "allocateThreads",-1);
00353     threadCounts[OP_DEALLOCATE] = configMap.getIntParam(
00354         "deallocateThreads",-1);
00355 
00356     if (nSecondsBetweenCheckpoints < nSeconds) {
00357         threadCounts[OP_CHECKPOINT] = 1;
00358     } else {
00359         threadCounts[OP_CHECKPOINT] = 0;
00360     }
00361 
00362     if (bTestResize) {
00363         threadCounts[OP_RESIZE_CACHE] = 1;
00364     } else {
00365         threadCounts[OP_RESIZE_CACHE] = 0;
00366     }
00367 
00368     cbPageUsable = 0;
00369 
00370     threadInit();
00371 }
00372 
00373 PagingTestBase::~PagingTestBase()
00374 {
00375     threadTerminate();
00376 }
00377 
00378 bool PagingTestBase::testThreadedOp(int iOp)
00379 {
00380     SXMutexSharedGuard checkpointSharedGuard(checkpointMutex,false);
00381     assert(iOp < OP_MAX);
00382     OpType op = static_cast<OpType>(iOp);
00383     switch (op) {
00384     case PagingTestBase::OP_WRITE_SEQ:
00385         checkpointSharedGuard.lock();
00386         // fall through
00387     case PagingTestBase::OP_READ_SEQ:
00388         testSequentialOp(op);
00389         break;
00390     case PagingTestBase::OP_WRITE_RAND:
00391     case PagingTestBase::OP_WRITE_NOWAIT:
00392         checkpointSharedGuard.lock();
00393         // fall through
00394     case PagingTestBase::OP_READ_RAND:
00395     case PagingTestBase::OP_READ_NOWAIT:
00396         testRandomOp(op);
00397         break;
00398     case PagingTestBase::OP_WRITE_SKIP:
00399         checkpointSharedGuard.lock();
00400         testSkipOp(op, 5);
00401         break;
00402     case PagingTestBase::OP_SCRATCH:
00403         testScratch();
00404         break;
00405     case PagingTestBase::OP_PREFETCH:
00406         testPrefetch();
00407         break;
00408     case PagingTestBase::OP_PREFETCH_BATCH:
00409         testPrefetchBatch();
00410         break;
00411     case PagingTestBase::OP_ALLOCATE:
00412         checkpointSharedGuard.lock();
00413         testAllocate();
00414         break;
00415     case PagingTestBase::OP_DEALLOCATE:
00416         checkpointSharedGuard.lock();
00417         testDeallocate();
00418         break;
00419     case PagingTestBase::OP_CHECKPOINT:
00420         testCheckpointGuarded();
00421         break;
00422     case PagingTestBase::OP_RESIZE_CACHE:
00423         testCacheResize();
00424         return false;
00425     default:
00426         permAssert(false);
00427     }
00428     return true;
00429 }
00430 
00431 void PagingTestBase::testMultipleThreads()
00432 {
00433     openStorage(DeviceMode::createNew);
00434     testAllocateAll();
00435     runThreadedTestCase();
00436 }
00437 
00438 // End PagingTestBase.cpp

Generated on Mon Jun 22 04:00:20 2009 for Fennel by  doxygen 1.5.1