00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/test/CacheTestBase.h"
00026 #include "fennel/test/PagingTestBase.h"
00027 #include "fennel/cache/Cache.h"
00028 #include "fennel/cache/QuotaCacheAccessor.h"
00029 #include "fennel/common/CompoundId.h"
00030
00031 #include <boost/test/test_tools.hpp>
00032
00033 #ifdef HAVE_MMAP
00034 #include <sys/resource.h>
00035 #endif
00036
00037 using namespace fennel;
00038
00039 #define SMALL_ADDR_SPACE (192 * 1024 * 1024) // 192 MB
00040
00051 class CacheTest : virtual public PagingTestBase
00052 {
00053 public:
00057 BlockId makeBlockId(uint i)
00058 {
00059 assert(i < nDiskPages);
00060 BlockId blockId(0);
00061 CompoundId::setDeviceId(blockId,dataDeviceId);
00062 CompoundId::setBlockNum(blockId,i);
00063 return blockId;
00064 }
00065
00066 virtual CachePage *lockPage(OpType opType,uint iPage)
00067 {
00068 BlockId blockId = makeBlockId(iPage);
00069 return getCache().lockPage(
00070 blockId,getLockMode(opType),opType != OP_ALLOCATE);
00071 }
00072
00073 virtual void unlockPage(CachePage &page,LockMode lockMode)
00074 {
00075 getCache().unlockPage(page,lockMode);
00076 }
00077
00078 virtual void prefetchPage(uint iPage)
00079 {
00080 BlockId blockId = makeBlockId(iPage);
00081 getCache().prefetchPage(blockId);
00082 }
00083
00084 virtual void prefetchBatch(uint iPage,uint nPagesPerBatch)
00085 {
00086 BlockId blockId = makeBlockId(iPage);
00087 getCache().prefetchBatch(blockId,nPagesPerBatch);
00088 }
00089
00090 explicit CacheTest()
00091 {
00092
00093 threadCounts[OP_ALLOCATE] = 0;
00094 threadCounts[OP_DEALLOCATE] = 0;
00095
00096 cbPageUsable = cbPageFull;
00097
00098 FENNEL_UNIT_TEST_CASE(CacheTest,testSingleThread);
00099 FENNEL_UNIT_TEST_CASE(CacheTest,testQuotaCacheAccessor);
00100 FENNEL_UNIT_TEST_CASE(PagingTestBase,testMultipleThreads);
00101
00102 #ifdef RLIMIT_AS
00103 FENNEL_EXTRA_UNIT_TEST_CASE(CacheTest,testLargeCacheInit);
00104 FENNEL_EXTRA_UNIT_TEST_CASE(CacheTest,testLargeCacheRequest);
00105 #endif
00106 }
00107
00108 void testSingleThread()
00109 {
00110 openStorage(DeviceMode::createNew);
00111 testAllocateAll();
00112 testSequentialRead();
00113 testRandomRead();
00114 testScratch();
00115 testSequentialWrite();
00116 testRandomWrite();
00117 closeStorage();
00118 openStorage(DeviceMode::load);
00119 testRandomRead();
00120 testSequentialRead();
00121 closeStorage();
00122 }
00123
00124 void testQuotaCacheAccessor()
00125 {
00126 openStorage(DeviceMode::createNew);
00127 QuotaCacheAccessor *pQuota = new QuotaCacheAccessor(
00128 SharedQuotaCacheAccessor(),pCache,5);
00129 SharedCacheAccessor pSharedQuota(pQuota);
00130 BOOST_CHECK_EQUAL(pQuota->getMaxLockedPages(),5U);
00131 BOOST_CHECK_EQUAL(pQuota->getLockedPageCount(),0U);
00132 CachePage *pPage = pQuota->lockPage(makeBlockId(0),LOCKMODE_S,0);
00133 BOOST_CHECK_EQUAL(pQuota->getLockedPageCount(),1U);
00134 pQuota->unlockPage(*pPage,LOCKMODE_S);
00135 BOOST_CHECK_EQUAL(pQuota->getLockedPageCount(),0U);
00136 pSharedQuota.reset();
00137 closeStorage();
00138 }
00139
00140 #ifdef RLIMIT_AS
00141
00142
00143 rlim_t setAddressSpaceLimit(rlim_t minLimit, struct rlimit &oldLimits)
00144 {
00145 int rv = getrlimit(RLIMIT_AS, &oldLimits);
00146 BOOST_REQUIRE(rv == 0);
00147
00148
00149 if (oldLimits.rlim_cur > minLimit) {
00150
00151 struct rlimit new_limits;
00152 new_limits.rlim_cur = minLimit;
00153 new_limits.rlim_max = oldLimits.rlim_max;
00154
00155 rv = setrlimit(RLIMIT_AS, &new_limits);
00156 BOOST_REQUIRE(rv == 0);
00157
00158 return minLimit;
00159 }
00160
00161 return oldLimits.rlim_cur;
00162 }
00163
00164
00165 void restoreAddressSpaceLimit(const struct rlimit &limits)
00166 {
00167
00168 int rv = setrlimit(RLIMIT_AS, &limits);
00169 BOOST_REQUIRE(rv == 0);
00170 }
00171
00172 uint computeMaxPagesUpperBound(uint addressSpaceSize, uint pageSize)
00173 {
00174 int guardPages = 0;
00175 #ifndef NDEBUG
00176
00177 guardPages = 2;
00178 #endif
00179 int osPageSize = getpagesize();
00180
00181 return addressSpaceSize / (pageSize + (guardPages * osPageSize) + 4);
00182 }
00183
00184 void testLargeCacheInit()
00185 {
00186 struct rlimit savedLimits;
00187
00188 rlim_t addrSpaceSize = setAddressSpaceLimit(
00189 SMALL_ADDR_SPACE, savedLimits);
00190
00191 CacheParams params;
00192
00193
00194
00195
00196 params.nMemPagesMax = addrSpaceSize / sizeof(void *) + 100;
00197 params.nMemPagesInit = 10;
00198
00199 SharedCache pCache;
00200
00201 BOOST_CHECK_NO_THROW(pCache = Cache::newCache(params));
00202 BOOST_CHECK_EQUAL(
00203 CacheParams::defaultMemPagesMax,
00204 pCache->getMaxAllocatedPageCount());
00205
00206
00207
00208
00209
00210 BOOST_CHECK_EQUAL(
00211 CacheParams::defaultMemPagesMax,
00212 pCache->getAllocatedPageCount());
00213
00214 pCache.reset();
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 params.cbPage = 32 * 1024;
00226
00227 params.nMemPagesMax =
00228 computeMaxPagesUpperBound(addrSpaceSize, params.cbPage);
00229 params.nMemPagesInit = params.nMemPagesMax;
00230
00231 BOOST_CHECK_NO_THROW(pCache = Cache::newCache(params));
00232 BOOST_CHECK_EQUAL(
00233 CacheParams::defaultMemPagesMax,
00234 pCache->getMaxAllocatedPageCount());
00235
00236
00237 BOOST_CHECK_EQUAL(
00238 CacheParams::defaultMemPagesMax,
00239 pCache->getAllocatedPageCount());
00240
00241 pCache.reset();
00242
00243 restoreAddressSpaceLimit(savedLimits);
00244 }
00245
00246 void testLargeCacheRequest()
00247 {
00248 struct rlimit savedLimits;
00249
00250 rlim_t addrSpaceSize =
00251 setAddressSpaceLimit(SMALL_ADDR_SPACE, savedLimits);
00252
00253 CacheParams params;
00254
00255
00256
00257 params.cbPage = 32 * 1024;
00258
00259 params.nMemPagesMax =
00260 computeMaxPagesUpperBound(addrSpaceSize, params.cbPage);
00261 params.nMemPagesInit =
00262 (params.nMemPagesMax / 2) < 1000
00263 ? (params.nMemPagesMax / 2)
00264 : 1000;
00265
00266 BOOST_CHECK_NO_THROW(pCache = Cache::newCache(params));
00267 BOOST_CHECK_EQUAL(
00268 params.nMemPagesMax,
00269 pCache->getMaxAllocatedPageCount());
00270 BOOST_CHECK_EQUAL(
00271 params.nMemPagesInit,
00272 pCache->getAllocatedPageCount());
00273
00274 BOOST_CHECK_THROW(
00275 pCache->setAllocatedPageCount(params.nMemPagesMax),
00276 std::exception);
00277 BOOST_CHECK_EQUAL(
00278 params.nMemPagesMax,
00279 pCache->getMaxAllocatedPageCount());
00280 BOOST_CHECK_EQUAL(
00281 params.nMemPagesInit,
00282 pCache->getAllocatedPageCount());
00283
00284 pCache.reset();
00285
00286 restoreAddressSpaceLimit(savedLimits);
00287 }
00288 #endif // RLIMIT_AS
00289 };
00290
00291 FENNEL_UNIT_TEST_SUITE(CacheTest);
00292
00293