1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1180 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32\sfat\sl_dir_cache.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "sl_std.h"
1.22 +#include "sl_dir_cache.h"
1.23 +
1.24 +//======================================================================
1.25 +TDynamicDirCachePage::~TDynamicDirCachePage()
1.26 + {
1.27 + }
1.28 +
1.29 +/**
1.30 +The static cache page creation function.
1.31 +Cache page objects are not supposed to be created on the stack, so this factory function is required.
1.32 +*/
1.33 +TDynamicDirCachePage* TDynamicDirCachePage::NewL(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr)
1.34 + {
1.35 + return new(ELeave) TDynamicDirCachePage(aOwnerCache, aStartMedPos, aStartRamAddr);
1.36 + }
1.37 +
1.38 +/**
1.39 +Cache page constructor.
1.40 +@param aOwnerCache pointer of the cache that owns this page
1.41 +@param aStartMedPos the start address on the media that this page caches
1.42 +@param aStartRamAddr the start address in the ram that this page content lives
1.43 +*/
1.44 +TDynamicDirCachePage::TDynamicDirCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr)
1.45 +:iStartMedPos(aStartMedPos),
1.46 +iStartRamAddr(aStartRamAddr),
1.47 +iOwnerCache(aOwnerCache),
1.48 +iValid(EFalse),
1.49 +iLocked(EFalse)
1.50 + {
1.51 + //__PRINT3(_L("TDynamicDirCachePage::TDynamicDirCachePage(aStartMedPos=%lx, aStartRamAddr=0x%X, aPageSize=%u)"), aStartMedPos, aStartRamAddr, PageSizeInBytes());
1.52 + iType = EUnknown;
1.53 + }
1.54 +
1.55 +/////////////////////////////// class CDynamicDirCache::TLookupEntry ///////////////////////////
1.56 +/**
1.57 +Required by RHashSet<TLookupEntry> to identify individual hash set entries.
1.58 +@see RHashSet
1.59 +*/
1.60 +TBool IdentityFunction(const TLookupEntry& aEntry1, const TLookupEntry& aEntry2)
1.61 + {
1.62 + // only check starting med pos for hash searching
1.63 + return aEntry1.iPos == aEntry2.iPos;
1.64 + }
1.65 +/**
1.66 +Required by RHashSet<TLookupEntry> to generate hash value.
1.67 +@see RHashSet
1.68 +*/
1.69 +TUint32 HashFunction(const TLookupEntry& aEntry)
1.70 + {
1.71 + return (DefaultHash::Integer(I64HIGH(aEntry.iPos)) + DefaultHash::Integer(I64LOW(aEntry.iPos)));
1.72 + }
1.73 +
1.74 +/////////////////////////////// class CDynamicDirCache ///////////////////////////
1.75 +CDynamicDirCache::~CDynamicDirCache()
1.76 + {
1.77 + __PRINT(_L("CDynamicDirCache::~CDynamicDirCache()"));
1.78 +
1.79 + // we should never decommit locked pages
1.80 + while (!iLockedQ.IsEmpty())
1.81 + {
1.82 + TDynamicDirCachePage* page = iLockedQ.Last();
1.83 + DeQueue(page); // remove from queue
1.84 + LookupTblRemove(page->StartPos()); // remove from lookuptable
1.85 + delete page;
1.86 + }
1.87 + ASSERT(iLockedQCount == 0);
1.88 +
1.89 + while (!iUnlockedQ.IsEmpty())
1.90 + {
1.91 + TDynamicDirCachePage* page = iUnlockedQ.Last();
1.92 + DeQueue(page); // remove from queue
1.93 + LookupTblRemove(page->StartPos()); // remove from lookuptable
1.94 + DecommitPage(page); // inform cache client to decommit page memory
1.95 + delete page;
1.96 + }
1.97 + ASSERT(iUnlockedQCount == 0);
1.98 +
1.99 + ASSERT(iLookupTable.Count() == 0);
1.100 + iLookupTable.Close();
1.101 + if (iCacheMemoryClient)
1.102 + iCacheMemoryClient->Reset();
1.103 + }
1.104 +
1.105 +/**
1.106 +Constructor of CDynamicDirCache.
1.107 +@param aDrive local drive interface to read/write media
1.108 +@param aMinPageNum the minimum page number for the cache, includes iActive page and locked pages.
1.109 +@param aMaxPageNum the maximum page number for the cache, includes iActive page, locked pages and unlocked pages.
1.110 +@param aPageSizeInBytesLog2 the log2 value of page size in bytes, assumes page size is always a power of two
1.111 +*/
1.112 +CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2)
1.113 +:iPageSizeLog2(aPageSizeInBytesLog2),
1.114 +iMinSizeInPages(aMinPageNum),
1.115 +iMaxSizeInPages(aMaxPageNum),
1.116 +iDrive(aDrive),
1.117 +iLockedQ(_FOFF(TDynamicDirCachePage, iLink)),
1.118 +iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)),
1.119 +iLockedQCount(0),
1.120 +iUnlockedQCount(0),
1.121 +iHashFunction(HashFunction),
1.122 +iIdentityFunction(IdentityFunction),
1.123 +iLookupTable(iHashFunction, iIdentityFunction)
1.124 + {
1.125 + iPageSizeInBytes = 1 << aPageSizeInBytesLog2;
1.126 + iCacheDisabled = EFalse;
1.127 + iMinCacheSizeInBytes = aMinPageNum << aPageSizeInBytesLog2;
1.128 + iMaxCacheSizeInBytes = aMaxPageNum << aPageSizeInBytesLog2;
1.129 + ASSERT(iPageSizeInBytes && iPageSizeInBytes <= iMinCacheSizeInBytes && iMinCacheSizeInBytes <= iMaxCacheSizeInBytes);
1.130 + // initial value, will be reset from outside
1.131 + iCacheBasePos = 0;
1.132 + }
1.133 +
1.134 +/**
1.135 +Second phase constructor of CDynamicDirCache.
1.136 +@param aClientName the identification of cache memeory client this cache connects
1.137 +*/
1.138 +void CDynamicDirCache::ConstructL(const TDesC& aClientName)
1.139 + {
1.140 +// __PRINT3(_L("CDynamicDirCache::ConstructL(Min=%u, Max=%u, page=%u)"), iMinCacheSizeInBytes, iMaxCacheSizeInBytes, iPageSizeInBytes);
1.141 + CCacheMemoryManager* manager = CCacheMemoryManagerFactory::CacheMemoryManager();
1.142 + if (manager)
1.143 + {
1.144 + // client will register itself onto cache memory manager when created
1.145 + // note this operation may leave under OOM condition
1.146 + iCacheMemoryClient = manager->ConnectClientL(aClientName, iMinSizeInPages * PageSizeInSegs(), iMaxSizeInPages * PageSizeInSegs());
1.147 + }
1.148 + else
1.149 + {
1.150 + User::Leave(KErrNotSupported);
1.151 + }
1.152 +
1.153 + ASSERT(iCacheMemoryClient);
1.154 + if (!iCacheMemoryClient)
1.155 + {
1.156 + User::Leave(KErrNoMemory);
1.157 + }
1.158 +
1.159 +
1.160 + // allocate as many permanently locked pages as there are threads - plus one
1.161 + // otherwise DoMakePageMRU() won't work properly with only one thread
1.162 + //-- At present moment the size of TDrive thread pool is 1 (1 drive thread in a pool)
1.163 + iPermanentlyAllocatedPageCount = 1;
1.164 +
1.165 + if (iPermanentlyAllocatedPageCount > iMinSizeInPages)
1.166 + iMinSizeInPages = iPermanentlyAllocatedPageCount;
1.167 +
1.168 + for (TUint n=0; n<iPermanentlyAllocatedPageCount; n++)
1.169 + {
1.170 + TDynamicDirCachePage* pPage = AllocateAndLockNewPageL(0);
1.171 + AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
1.172 + LookupTblAdd(pPage);
1.173 + }
1.174 +
1.175 + }
1.176 +
1.177 +/**
1.178 +Static factory function of CDynamicDirCache
1.179 +*/
1.180 +CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName)
1.181 + {
1.182 + __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<<aPageSizeLog2);
1.183 + CDynamicDirCache* pSelf = new (ELeave) CDynamicDirCache(aDrive, aMinPageNum, aMaxPageNum, aPageSizeLog2);
1.184 + CleanupStack::PushL(pSelf);
1.185 + pSelf->ConstructL(aClientName);
1.186 + CleanupStack::Pop();
1.187 + return pSelf;
1.188 + }
1.189 +
1.190 +/**
1.191 +Insert an unlocked page into the last position of the locked queue, may squeeze the original last page into
1.192 +the unlocked queue.
1.193 +This function is used on last visited but 'unlocked' pages to avoid excessive lock/unlock calls to cache memory
1.194 +manager as contiguous entry reading/writing often happens on the same page.
1.195 +@param aPage the page to be inserted.
1.196 +@pre the page type of aPage should only be TDynamicDirCachePage::EUnknown
1.197 +*/
1.198 +void CDynamicDirCache::MakePageLastLocked(TDynamicDirCachePage* aPage)
1.199 + {
1.200 + // this function should not be called on active pages
1.201 + ASSERT(aPage->iType == TDynamicDirCachePage::EUnknown);
1.202 +
1.203 + if (iLockedQ.IsEmpty())
1.204 + {
1.205 + // if locked queue is empty, add it onto the locked queue directly
1.206 + AddFirstOntoQueue(aPage, TDynamicDirCachePage::ELocked);
1.207 + }
1.208 + else
1.209 + {
1.210 + // otherwise, we squeeze for the last position on locked queue
1.211 + while (iLockedQCount + 1 >= iMinSizeInPages)
1.212 + {
1.213 + TDynamicDirCachePage* last = iLockedQ.Last();
1.214 + DeQueue(last);
1.215 + UnlockPage(last);
1.216 + AddFirstOntoQueue(last, TDynamicDirCachePage::EUnlocked);
1.217 + }
1.218 +
1.219 + // iLockedQCount + 1 < iMinSizeInPages
1.220 + iLockedQ.AddLast(*aPage);
1.221 + aPage->SetPageType(TDynamicDirCachePage::ELocked);
1.222 + iLockedQCount++;
1.223 + }
1.224 + }
1.225 +
1.226 +/**
1.227 + Read data from a single page. If the page is not found or not valid anymore, read media onto iActive page first.
1.228 + The data will be _Appended_ the the descriptor aDes. The caller is responsible for maintaining this descriptor.
1.229 +
1.230 + @param aPos the starting position of the media address to be read.
1.231 + @param aLength the length of the content to be read.
1.232 + @param aDes the descriptor to contain the content.
1.233 + @pre aLength should be no more than page size.
1.234 +*/
1.235 +void CDynamicDirCache::ReadDataFromSinglePageL(TInt64 aPos, TInt aLength, TDes8& aDes)
1.236 + {
1.237 + //-- the data section is in the cache page entirely, take data directly from the cache
1.238 + TDynamicDirCachePage* pPage = FindPageByPos(aPos);
1.239 + if (pPage)
1.240 + {
1.241 + // lock page before reading,
1.242 + if (LockPage(pPage) != NULL)
1.243 + {
1.244 + // read data and append them to the descriptor
1.245 + aDes.Append(pPage->PtrInPage(aPos), aLength);
1.246 +
1.247 +
1.248 + // if page is from unlocked queue, insert it onto the last page of the locked
1.249 + // queue. this is to avoid excessive locking and unlocking operations that is
1.250 + // highly likely to happen for following reads.
1.251 + if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
1.252 + {
1.253 + DeQueue(pPage);
1.254 + MakePageLastLocked(pPage);
1.255 + }
1.256 + }
1.257 + else // page locking failed
1.258 + {
1.259 + ASSERT(pPage->PageType() == TDynamicDirCachePage::EUnlocked);
1.260 + DeQueue(pPage);
1.261 + LookupTblRemove(pPage->StartPos());
1.262 + DecommitPage(pPage);
1.263 + delete pPage;
1.264 + pPage = NULL;
1.265 + }
1.266 + }
1.267 +
1.268 + if (!pPage)
1.269 + {
1.270 + // if page not found or page data not valid anymore, use active page to read data in
1.271 + pPage = UpdateActivePageL(aPos);
1.272 + // read data and append them to the descriptor
1.273 + aDes.Append(pPage->PtrInPage(aPos), aLength);
1.274 + }
1.275 +
1.276 + }
1.277 +
1.278 +//====================================================================
1.279 +/**
1.280 +Implementation of pure virtual function.
1.281 +@see MWTCacheInterface::ReadL()
1.282 +*/
1.283 +void CDynamicDirCache::ReadL(TInt64 aPos, TInt aLength, TDes8& aDes)
1.284 + {
1.285 +#ifdef _DEBUG
1.286 + if(iCacheDisabled)
1.287 + {
1.288 + // cache is disabled for debug purposes
1.289 + __PRINT(_L("CDynamicDirCache disabled"));
1.290 + User::LeaveIfError(iDrive.ReadNonCritical(aPos, aLength, aDes));
1.291 + return;
1.292 + }
1.293 +#endif //_DEBUG
1.294 +
1.295 + aDes.Zero();
1.296 + const TUint32 PageSz = iPageSizeInBytes;//-- cache page size
1.297 +
1.298 + TInt64 pageStartMedPos = CalcPageStartPos(aPos);
1.299 + const TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos); //-- number of bytes from aPos to the end of the page
1.300 +
1.301 +// __PRINT5(_L("CDynamicDirCache::ReadL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, aLength, pageStartMedPos, PageSz, bytesToPageEnd);
1.302 + // if all data needed is on a single page
1.303 + if((TUint32)aLength <= bytesToPageEnd)
1.304 + {
1.305 + ReadDataFromSinglePageL(aPos, aLength, aDes);
1.306 + }
1.307 + // or data to be read cross cache page boundary or probably we have more than 1 page to read
1.308 + else
1.309 + {
1.310 + __PRINT(_L("CDynamicDirCache::ReadL() CROSS PAGE!"));
1.311 + TUint32 dataLen(aLength); //-- current data length
1.312 + TInt64 currMediaPos(aPos); //-- current media position
1.313 +
1.314 + //-- 1. read data that are already in the current page
1.315 + ReadDataFromSinglePageL(currMediaPos, bytesToPageEnd, aDes);
1.316 + dataLen -= bytesToPageEnd;
1.317 + currMediaPos += bytesToPageEnd;
1.318 +
1.319 + //-- 2. read whole pages of data
1.320 + while (dataLen >= PageSz)
1.321 + {
1.322 + //-- find out if currMediaPos is in cache. If not, find a spare page and read data there
1.323 + ReadDataFromSinglePageL(currMediaPos, PageSz, aDes);
1.324 + currMediaPos += PageSz;
1.325 + dataLen -= PageSz;
1.326 + }
1.327 +
1.328 + //-- 3. read the rest of the data
1.329 + if(dataLen > 0)
1.330 + {
1.331 + ReadDataFromSinglePageL(currMediaPos, dataLen, aDes);
1.332 + }
1.333 + } //else((TUint32)aLength <= bytesToPageEnd)
1.334 + }
1.335 +
1.336 +/**
1.337 +Write data through a single page. If the page is not found or not valid anymore, read media onto iActive page
1.338 +first, then write data through iActive page.
1.339 +@param aPos the starting position of the media address to be write.
1.340 +@param aData the starting address that the writing content lives in the ram.
1.341 +@param aDataLen the length of the content to be written.
1.342 +@pre aDataLen should be no more than page size.
1.343 +*/
1.344 +void CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen)
1.345 + {
1.346 + ASSERT(aDataLen <= iPageSizeInBytes);
1.347 + //-- the data section is in the cache page entirely, take data directly from the cache
1.348 + TDynamicDirCachePage* pPage = FindPageByPos(aPos);
1.349 + if (pPage)
1.350 + {
1.351 + // lock page before writing,
1.352 + if (LockPage(pPage) != NULL)
1.353 + {
1.354 + //-- update cache
1.355 + Mem::Copy(pPage->PtrInPage(aPos), aData, aDataLen);
1.356 + }
1.357 + else
1.358 + {
1.359 + ASSERT(pPage->PageType() == TDynamicDirCachePage::EUnlocked);
1.360 + DeQueue(pPage);
1.361 + LookupTblRemove(pPage->StartPos());
1.362 + DecommitPage(pPage);
1.363 + delete pPage;
1.364 + pPage = NULL;
1.365 + }
1.366 + }
1.367 +
1.368 + // if page not found or page data not valid anymore, use active page to read data in
1.369 + if (!pPage)
1.370 + {
1.371 + pPage = UpdateActivePageL(aPos);
1.372 + //-- update cache
1.373 + Mem::Copy(pPage->PtrInPage(aPos), aData, aDataLen);
1.374 + }
1.375 +
1.376 + // make sure the page is unlocked after use
1.377 + if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
1.378 + {
1.379 + UnlockPage(pPage);
1.380 + }
1.381 +
1.382 + // always make writting events MRU
1.383 + DoMakePageMRU(aPos);
1.384 + return;
1.385 + }
1.386 +
1.387 +/**
1.388 +Implementation of pure virtual function.
1.389 +@see MWTCacheInterface::WriteL()
1.390 +*/
1.391 +void CDynamicDirCache::WriteL(TInt64 aPos,const TDesC8& aDes)
1.392 + {
1.393 +#ifdef _DEBUG
1.394 + if(iCacheDisabled)
1.395 + {
1.396 + // cache is disabled for debug purposes
1.397 + __PRINT(_L("CDynamicDirCache disabled"));
1.398 + User::LeaveIfError(iDrive.WriteCritical(aPos,aDes));
1.399 + return;
1.400 + }
1.401 +#endif //_DEBUG
1.402 +
1.403 + TUint32 dataLen = aDes.Size();
1.404 + const TUint8* pData = aDes.Ptr();
1.405 + const TUint32 PageSz = iPageSizeInBytes; //-- cache page size
1.406 +
1.407 + TInt64 pageStartMedPos = CalcPageStartPos(aPos);
1.408 + TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos);
1.409 +
1.410 +// __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd);
1.411 +
1.412 + if(dataLen <= bytesToPageEnd)
1.413 + {
1.414 + WriteDataOntoSinglePageL(aPos, pData, dataLen);
1.415 + }
1.416 + else
1.417 + {
1.418 + __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!"));
1.419 +
1.420 + //-- Data to be written cross cache page boundary or probably we have more than 1 page to write
1.421 + TInt64 currMediaPos(aPos);
1.422 +
1.423 + //-- 1. update the current page
1.424 + WriteDataOntoSinglePageL(currMediaPos, pData, bytesToPageEnd);
1.425 +
1.426 + pData += bytesToPageEnd;
1.427 + currMediaPos += bytesToPageEnd;
1.428 + dataLen -= bytesToPageEnd;
1.429 +
1.430 + //-- 2. write whole pages of data to the cache
1.431 + while (dataLen >= PageSz)
1.432 + {
1.433 + WriteDataOntoSinglePageL(currMediaPos, pData, PageSz);
1.434 +
1.435 + pData += PageSz;
1.436 + currMediaPos += PageSz;
1.437 + dataLen -= PageSz;
1.438 + }
1.439 +
1.440 + //-- 3. write the rest of the data
1.441 + if(dataLen > 0)
1.442 + {
1.443 + WriteDataOntoSinglePageL(currMediaPos, pData, dataLen);
1.444 + }
1.445 + }// else(dataLen <= bytesToPageEnd)
1.446 +
1.447 +
1.448 + //-- write data to the media
1.449 + const TInt nErr = iDrive.WriteCritical(aPos,aDes);
1.450 + if(nErr != KErrNone)
1.451 + {//-- some serious problem occured during writing, invalidate cache.
1.452 + InvalidateCache();
1.453 + User::Leave(nErr);
1.454 + }
1.455 + }
1.456 +
1.457 +/**
1.458 + Invalidate the cache
1.459 + @see MWTCacheInterface::InvalidateCache()
1.460 +*/
1.461 +void CDynamicDirCache::DoInvalidateCache(void)
1.462 + {
1.463 + __PRINT2(_L("CDynamicDirCache::InvalidateCache(locked=%d, unlocked=%d)"), iLockedQCount, iUnlockedQCount);
1.464 + // we should never decommit locked pages as they needs to be reserved anyway
1.465 + // the overhead of unnecessary page committing operations
1.466 +
1.467 + TInt pagesToRemoveFromLockedQueue = iLockedQCount - iPermanentlyAllocatedPageCount;
1.468 + TInt n;
1.469 + for (n=0; n<pagesToRemoveFromLockedQueue; n++)
1.470 + {
1.471 + TDynamicDirCachePage* page = iLockedQ.Last();
1.472 + DeQueue(page); // remove from queue
1.473 + LookupTblRemove(page->StartPos()); // remove from lookuptable
1.474 + DecommitPage(page); // inform cache client to decommit page memory
1.475 + delete page;
1.476 + }
1.477 + ASSERT(iLockedQCount == iPermanentlyAllocatedPageCount);
1.478 +
1.479 + TDblQueIter<TDynamicDirCachePage> q(iLockedQ);
1.480 + q.SetToFirst();
1.481 + while((TDynamicDirCachePage*) q)
1.482 + {
1.483 + TDynamicDirCachePage* page = q++;
1.484 + LookupTblRemove(page->StartPos());// remove from lookuptable
1.485 + ResetPagePos(page); // reset start media position (0), invalidate page content
1.486 + }
1.487 +
1.488 + // however we should decommit unlocked pages here
1.489 + while (!iUnlockedQ.IsEmpty())
1.490 + {
1.491 + TDynamicDirCachePage* page = iUnlockedQ.Last();
1.492 + DeQueue(page); // remove from queue
1.493 + LookupTblRemove(page->StartPos()); // remove from lookuptable
1.494 + DecommitPage(page); // inform cache client to decommit page memory
1.495 + delete page;
1.496 + }
1.497 + ASSERT(iUnlockedQCount == 0);
1.498 +
1.499 + ASSERT(iLockedQCount == iPermanentlyAllocatedPageCount);
1.500 +
1.501 + ASSERT(iCacheMemoryClient);
1.502 + }
1.503 +
1.504 +/**
1.505 +Implementation of pure virtual function.
1.506 +@see MWTCacheInterface::InvalidateCache()
1.507 +*/
1.508 +void CDynamicDirCache::InvalidateCache(void)
1.509 + {
1.510 + DoInvalidateCache();
1.511 + }
1.512 +
1.513 +/** this method isn't implemented*/
1.514 +void CDynamicDirCache::InvalidateCachePage(TUint64 /*aPos*/)
1.515 + {
1.516 + ASSERT(0);
1.517 + }
1.518 +
1.519 +
1.520 +/**
1.521 +Implementation of pure virtual function.
1.522 +@see MWTCacheInterface::PosCached()
1.523 +*/
1.524 +TUint32 CDynamicDirCache::PosCached(const TInt64& aPos, TInt64& aCachedPosStart)
1.525 + {
1.526 + const TInt64 pageStartMedPos = CalcPageStartPos(aPos);
1.527 +
1.528 + // only search the page in lookup table
1.529 + // NOTE: we don't count the active page into acount here,
1.530 + // this is to avoid pulling next pages recursively
1.531 + TDynamicDirCachePage* pPage = LookupTblFind(pageStartMedPos);
1.532 +
1.533 + // then check if page is still valid if page is on Unlocked Page Queue
1.534 + if (pPage && pPage->PageType() == TDynamicDirCachePage::EUnlocked)
1.535 + {
1.536 + if (LockPage(pPage) != NULL)
1.537 + {
1.538 +// __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos);
1.539 + // have to unlock it before returning, otherwise there will be memory leak
1.540 + UnlockPage(pPage);
1.541 + aCachedPosStart = pPage->StartPos();
1.542 + return pPage->PageSizeInBytes();
1.543 + }
1.544 + else // if the unlocked page is not valid anymore, remove it
1.545 + {
1.546 + DeQueue(pPage);
1.547 + LookupTblRemove(pPage->StartPos());
1.548 + DecommitPage(pPage);
1.549 + delete pPage;
1.550 + pPage = NULL;
1.551 + }
1.552 + }
1.553 + // otherwise if page is already locked or valid active page
1.554 + else if (pPage)
1.555 + {
1.556 + __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) on Locked Queue!"), aPos);
1.557 + aCachedPosStart = pPage->StartPos();
1.558 + return pPage->PageSizeInBytes();
1.559 + }
1.560 +
1.561 + // page is not found or not valid anymore
1.562 + return 0;
1.563 + }
1.564 +
1.565 +/**
1.566 +Implementation of pure virtual function.
1.567 +@see MWTCacheInterface::CacheSizeInBytes()
1.568 +*/
1.569 +TUint32 CDynamicDirCache::CacheSizeInBytes() const
1.570 + {
1.571 + return iMaxCacheSizeInBytes;
1.572 + }
1.573 +
1.574 +/**
1.575 +Implementation of pure virtual function.
1.576 +@see MWTCacheInterface::Control()
1.577 +*/
1.578 +TInt CDynamicDirCache::Control(TUint32 aFunction, TUint32 aParam1, TAny* aParam2)
1.579 + {
1.580 + TInt r = KErrNotSupported;
1.581 +#ifdef _DEBUG
1.582 + (void)aParam2;
1.583 + switch(aFunction)
1.584 + {
1.585 + // disable / enable cache, for debug
1.586 + // if aParam1 != 0 cache will be disabled, enabled otherwise
1.587 + case EDisableCache:
1.588 + iCacheDisabled = aParam1 ? 1 : 0;
1.589 + r = KErrNone;
1.590 + break;
1.591 +
1.592 + // dump cache, for debug
1.593 + case EDumpCache:
1.594 + {
1.595 + RFs fs;
1.596 + fs.Connect();
1.597 + const TUint32 debugRegister = DebugRegister();
1.598 + fs.SetDebugRegister(debugRegister|KFSYS);
1.599 + Dump();
1.600 + fs.SetDebugRegister(debugRegister);
1.601 + fs.Close();
1.602 + break;
1.603 + }
1.604 + case ECacheInfo:
1.605 + {
1.606 + RFs fs;
1.607 + fs.Connect();
1.608 + const TUint32 debugRegister = DebugRegister();
1.609 + fs.SetDebugRegister(debugRegister|KFSYS);
1.610 + Info();
1.611 + fs.SetDebugRegister(debugRegister);
1.612 + fs.Close();
1.613 + break;
1.614 + }
1.615 +
1.616 + default:
1.617 + __PRINT1(_L("CDynamicDirCache::Control() invalid function: %d"), aFunction);
1.618 + ASSERT(0);
1.619 + break;
1.620 + }
1.621 +
1.622 +#else
1.623 + (void)aFunction; //-- supress warnings
1.624 + (void)aParam1;
1.625 + (void)aParam2;
1.626 + User::Invariant(); //-- don't call this method in release build
1.627 +#endif //_DEBUG
1.628 +
1.629 + return r;
1.630 + }
1.631 +
1.632 +/**
1.633 +Implementation of pure virtual function.
1.634 +@see MWTCacheInterface::SetCacheBasePos()
1.635 +*/
1.636 +void CDynamicDirCache::SetCacheBasePos(TInt64 aBasePos)
1.637 + {
1.638 + iCacheBasePos = aBasePos;
1.639 + }
1.640 +
1.641 +/**
1.642 +Implementation of pure virtual function.
1.643 +@see MWTCacheInterface::SetCacheBasePos()
1.644 +*/
1.645 +TUint32 CDynamicDirCache::PageSizeInBytesLog2() const
1.646 + {
1.647 + return iPageSizeLog2;
1.648 + }
1.649 +
1.650 +
1.651 +void CDynamicDirCache::DoMakePageMRU(TInt64 aPos)
1.652 + {
1.653 +// __PRINT1(_L("MakePageMRU (%lx)"), aPos);
1.654 +// __PRINT4(_L("Current Cache State: iLockedQCount=%d, iUnlockedQCount=%d, iLookupTbl=%d, iMaxSizeInPages=%d"), iLockedQCount, iUnlockedQCount, iLookupTable.Count(), iMaxSizeInPages);
1.655 + // check the MRU page first, if it is already the MRU page, we can return immediately
1.656 + TInt64 pageStartMedPos = CalcPageStartPos(aPos);
1.657 + if (!iLockedQ.IsEmpty())
1.658 + {
1.659 + if (iLockedQ.First()->StartPos() == pageStartMedPos)
1.660 + {
1.661 + return;
1.662 + }
1.663 + }
1.664 +
1.665 + TDynamicDirCachePage* pPage = FindPageByPos(aPos);
1.666 + if (pPage)
1.667 + {
1.668 + ASSERT(pPage->IsValid());
1.669 + // lock page before make it MRU
1.670 + if (pPage->PageType() == TDynamicDirCachePage::EUnlocked)
1.671 + {
1.672 + ASSERT(!pPage->IsLocked());
1.673 + if (LockPage(pPage) == NULL)
1.674 + {
1.675 + DeQueue(pPage);
1.676 + LookupTblRemove(pPage->StartPos());
1.677 + DecommitPage(pPage);
1.678 + delete pPage;
1.679 + pPage = NULL;
1.680 + }
1.681 + }
1.682 + else
1.683 + {
1.684 + // error checking: page should either be locked or active
1.685 + ASSERT(LockPage(pPage) != NULL);
1.686 + }
1.687 + }
1.688 +
1.689 + // if page not found or page data not valid anymore, use active page to read data
1.690 + if (!pPage)
1.691 + {
1.692 + TRAPD(err, pPage = UpdateActivePageL(aPos));
1.693 + if (err != KErrNone)
1.694 + {
1.695 + // problem occurred reading active page, return immediately.
1.696 + return;
1.697 + }
1.698 + }
1.699 +
1.700 + // by now, the page is either locked or active page
1.701 + ASSERT(pPage && pPage->IsValid() && pPage->IsLocked());
1.702 +
1.703 +
1.704 +
1.705 + TBool allocateNewPage = pPage == iLockedQ.Last() && !CacheIsFull();
1.706 +
1.707 +
1.708 + switch (pPage->PageType())
1.709 + {
1.710 + case TDynamicDirCachePage::EUnlocked:
1.711 + {
1.712 + // if page was originally on Unlocked Page Queque, remove it from Unlocked Page Queue, add it
1.713 + // to the Locked Page Queue and make it MRU
1.714 + DeQueue(pPage);
1.715 + AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
1.716 + // check cache limit
1.717 + CheckThresholds();
1.718 + }
1.719 + case TDynamicDirCachePage::ELocked:
1.720 + {
1.721 + // otherwise the page was on Locked Page Queue, make it MRU
1.722 + // no need to check cache limit
1.723 + if (pPage != iLockedQ.First())
1.724 + {
1.725 + DeQueue(pPage);
1.726 + AddFirstOntoQueue(pPage, TDynamicDirCachePage::ELocked);
1.727 + }
1.728 + break;
1.729 + }
1.730 + default:
1.731 + ASSERT(0);
1.732 + }
1.733 +
1.734 + if (allocateNewPage)
1.735 + {
1.736 + TDynamicDirCachePage* nPage = NULL;
1.737 + TRAPD(err, nPage = AllocateAndLockNewPageL(0));
1.738 + if (err == KErrNone)
1.739 + {
1.740 +
1.741 + // about to add a page to end of locked queue, so lie about iLockedQCount
1.742 + iLockedQCount++;
1.743 + CheckThresholds();
1.744 + iLockedQCount--;
1.745 +
1.746 + iLockedQ.AddLast(*nPage);
1.747 + nPage->SetPageType(TDynamicDirCachePage::ELocked);
1.748 + ++iLockedQCount;
1.749 + LookupTblAdd(nPage);
1.750 + }
1.751 + }
1.752 + }
1.753 +
1.754 +/**
1.755 + Implementation of pure virtual function.
1.756 + @see MDiskSpecialAccessor::MakePageMRU()
1.757 +*/
1.758 +void CDynamicDirCache::MakePageMRU(TInt64 aPos)
1.759 + {
1.760 + DoMakePageMRU(aPos);
1.761 + }
1.762 +
1.763 +//====================================================================
1.764 +/**
1.765 +Internal query function, to check if aPos is cached or not. iActive page is included in searching.
1.766 +*/
1.767 +TDynamicDirCachePage* CDynamicDirCache::FindPageByPos(TInt64 aPos)
1.768 + {
1.769 +// __PRINT1(_L("CDynamicDirCache::FindPageByPos(aPos=%lx)"), aPos);
1.770 + // align the page position
1.771 + TInt64 pageStartMedPos = CalcPageStartPos(aPos);
1.772 +
1.773 + // search in lookup table
1.774 + return LookupTblFind(pageStartMedPos);
1.775 + }
1.776 +
1.777 +/**
1.778 +read a page length data into iActive page and return iActive page if read is successful.
1.779 +*/
1.780 +TDynamicDirCachePage* CDynamicDirCache::UpdateActivePageL(TInt64 aPos)
1.781 + {
1.782 + // align the page position
1.783 + TInt64 pageStartMedPos = CalcPageStartPos(aPos);
1.784 +
1.785 + ASSERT(!iLockedQ.IsEmpty());
1.786 + TDynamicDirCachePage* activePage = iLockedQ.Last();
1.787 +
1.788 + if (activePage->StartPos() == pageStartMedPos && activePage->IsValid())
1.789 + {
1.790 + return activePage;
1.791 + }
1.792 +
1.793 + __PRINT2(_L("CDynamicDirCache::UpdateActivePageL(aPos=%lx, active=%lx)"), aPos, activePage->StartPos());
1.794 +
1.795 + activePage->Deque();
1.796 + LookupTblRemove(activePage->StartPos());
1.797 +
1.798 + // set start med pos value, no other effects, only available to active page
1.799 + activePage->SetPos(pageStartMedPos);
1.800 +
1.801 + // read data, make active page valid
1.802 + TUint8* data = activePage->PtrInPage(activePage->iStartMedPos);
1.803 + TPtr8 dataPtr(data, iPageSizeInBytes);
1.804 +
1.805 + const TInt nErr = iDrive.ReadNonCritical(activePage->iStartMedPos, iPageSizeInBytes, dataPtr);
1.806 +
1.807 + iLockedQ.AddLast(*activePage);
1.808 + LookupTblAdd(activePage);
1.809 +
1.810 + if(nErr !=KErrNone)
1.811 + {
1.812 + // some serious problem occured during reading, invalidate cache.
1.813 + DoInvalidateCache();
1.814 + User::Leave(nErr);
1.815 + }
1.816 + activePage->SetValid(ETrue);
1.817 +
1.818 + return activePage;
1.819 + }
1.820 +
1.821 +/**
1.822 +Check if the number of (locked pages + iActive page) and unlocked pages have exceeded minimum allowed page
1.823 +number and maximum allowed page number respectively.
1.824 +*/
1.825 +void CDynamicDirCache::CheckThresholds()
1.826 + {
1.827 + while (iLockedQCount + 1 > iMinSizeInPages)
1.828 + {
1.829 + TDynamicDirCachePage* movePage = iLockedQ.Last();
1.830 + UnlockPage(movePage);
1.831 + DeQueue(movePage);
1.832 + TInt err = LookupTblRemove(movePage->StartPos());
1.833 + ASSERT(err == KErrNone);
1.834 +
1.835 + // if it is a valid page, add onto unlocked queue
1.836 + if (movePage->StartPos() != 0)
1.837 + {
1.838 + ASSERT(movePage->IsValid());
1.839 + AddFirstOntoQueue(movePage, TDynamicDirCachePage::EUnlocked);
1.840 + err = LookupTblAdd(movePage);
1.841 + ASSERT(err == KErrNone);
1.842 + }
1.843 + else // reserved page, delete
1.844 + {
1.845 + DecommitPage(movePage);
1.846 + delete movePage;
1.847 + }
1.848 + }
1.849 +
1.850 + // if unlocked queue exceeds limit, delete LRU page
1.851 + // note: all pages on unlocked queue should be valid
1.852 + while (iUnlockedQCount > iMaxSizeInPages - iMinSizeInPages)
1.853 + {
1.854 + TDynamicDirCachePage* removePage = iUnlockedQ.Last();
1.855 + ASSERT(removePage->StartPos() != 0 && removePage->IsValid());
1.856 + DeQueue(removePage);
1.857 + LookupTblRemove(removePage->StartPos());
1.858 + DecommitPage(removePage);
1.859 + delete removePage;
1.860 + }
1.861 + }
1.862 +
1.863 +/**
1.864 +Try to create a new page and lock the page content when it is created. This function should only be called
1.865 +when creating iActive page or making a page MRU (which might result in page evictions).
1.866 +@return the pointer of the newly created page, or NULL if allocation failed.
1.867 +@param aStartMedPos the starting media address of the page to be created.
1.868 +@pre aStartMedPos should not already be existing in the cache.
1.869 +*/
1.870 +TDynamicDirCachePage* CDynamicDirCache::AllocateAndLockNewPageL(TInt64 aStartMedPos)
1.871 + {
1.872 + __PRINT1(_L("CDynamicDirCache::AllocateAndLockNewPageL(aStartMedPos=%lx)"), aStartMedPos);
1.873 +
1.874 + TUint8* startRamAddr = iCacheMemoryClient->AllocateAndLockSegments(PageSizeInSegs());
1.875 + if (startRamAddr)
1.876 + {
1.877 + // create new page and return
1.878 + TDynamicDirCachePage* pPage = TDynamicDirCachePage::NewL(this, aStartMedPos, startRamAddr);
1.879 + pPage->SetLocked(ETrue);
1.880 + pPage->SetValid(EFalse);
1.881 + return pPage;
1.882 + }
1.883 +
1.884 + return NULL;
1.885 + }
1.886 +
1.887 +#ifdef _DEBUG
1.888 +/**
1.889 +Dump cache information, only enabled in debug mode.
1.890 +@see CDynamicDirCache::Control()
1.891 +*/
1.892 +void CDynamicDirCache::Info() const
1.893 + {
1.894 + __PRINT(_L("======== CDynamicDirCache::Info ========="));
1.895 + const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
1.896 + // page size
1.897 + __PRINT1(_L("=== Pages size: [%d Bytes]"), iPageSizeInBytes);
1.898 + __PRINT1(_L("=== Segment size: [%d Bytes]"), 1 << SegmentSizeInBytesLog2);
1.899 +
1.900 + // data size:
1.901 + __PRINT1(_L("=== Min data size: [%d Bytes]"), iMinSizeInPages << iPageSizeLog2);
1.902 + __PRINT1(_L("=== Max data size: [%d Bytes]"), iMaxSizeInPages << iPageSizeLog2);
1.903 +
1.904 + // memory size:
1.905 + const TUint32 pageMemSizeLog2 = iPageSizeLog2 > SegmentSizeInBytesLog2 ? iPageSizeLog2 : SegmentSizeInBytesLog2;
1.906 + __PRINT1(_L("=== Min memory size: [%d Bytes]"), iMinSizeInPages << pageMemSizeLog2);
1.907 + __PRINT1(_L("=== Max memory size: [%d Bytes]"), iMaxSizeInPages << pageMemSizeLog2);
1.908 +
1.909 + // reserved pages
1.910 + __PRINT1(_L("=== Number of pages reserved: [%d]"), iMinSizeInPages);
1.911 + __PRINT1(_L("=== Reserved memory: [%d Bytes]"), (iMinSizeInPages * PageSizeInSegs()) << SegmentSizeInBytesLog2);
1.912 + // locked page num
1.913 + __PRINT1(_L("=== Number of pages locked: [%d]"), iLockedQCount);
1.914 + __PRINT1(_L("=== Locked memory: [%d Bytes]"), (iLockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
1.915 + // unlocked page num
1.916 + __PRINT1(_L("=== Number of pages unlocked: [%d]"), iUnlockedQCount);
1.917 + __PRINT1(_L("=== Unlocked memory: [%d Bytes]"), (iUnlockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
1.918 + }
1.919 +
1.920 +/**
1.921 +Dump cache content, only enabled in debug mode.
1.922 +@see CDynamicDirCache::Control()
1.923 +*/
1.924 +void CDynamicDirCache::Dump()
1.925 + {
1.926 + __PRINT(_L("======== CDynamicDirCache::Dump ========="));
1.927 + if (!iLockedQ.IsEmpty())
1.928 + {
1.929 + TDblQueIter<TDynamicDirCachePage> q(iLockedQ);
1.930 + q.SetToFirst();
1.931 + TInt i = 0;
1.932 + while((TDynamicDirCachePage*)q)
1.933 + {
1.934 + TDynamicDirCachePage* pP = q++;
1.935 + __PRINT5(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
1.936 + }
1.937 + }
1.938 + if (!iUnlockedQ.IsEmpty())
1.939 + {
1.940 + TDblQueIter<TDynamicDirCachePage> q(iUnlockedQ);
1.941 + q.SetToFirst();
1.942 + TInt i = 0;
1.943 + while((TDynamicDirCachePage*)q)
1.944 + {
1.945 + TDynamicDirCachePage* pP = q++;
1.946 + __PRINT5(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
1.947 + }
1.948 + }
1.949 +
1.950 + if (iLookupTable.Count())
1.951 + {
1.952 + TInt i = 0;
1.953 + THashSetIter<TLookupEntry> iter(iLookupTable);
1.954 + TLookupEntry* pEntry;
1.955 + pEntry = (TLookupEntry*) iter.Next();
1.956 + while(pEntry)
1.957 + {
1.958 + TDynamicDirCachePage* pP = pEntry->iPage;
1.959 + __PRINT5(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, locked=%d, valid=%d, size=%u)"), i++, pP->StartPos(), pP->IsLocked(), pP->IsValid(), pP->PageSizeInBytes());
1.960 + pEntry = (TLookupEntry*) iter.Next();
1.961 + };
1.962 + }
1.963 + __PRINT(_L("===========================================\n"));
1.964 + }
1.965 +#endif //_DEBUG
1.966 +
1.967 +/**
1.968 +Lock an unlocked page, or do nothing if the page is already locked.
1.969 +@return TUint8* pointer of the page to be locked, if locking is successful, otherwise return NULL.
1.970 +@param aPage the pointer of the page to be locked.
1.971 +*/
1.972 +TUint8* CDynamicDirCache::LockPage(TDynamicDirCachePage* aPage)
1.973 + {
1.974 + ASSERT(aPage != NULL);
1.975 + if (aPage->IsLocked())
1.976 + return aPage->StartPtr();
1.977 +
1.978 + TInt r = iCacheMemoryClient->LockSegments(aPage->StartPtr(), PageSizeInSegs());
1.979 + if (r == KErrNone)
1.980 + {
1.981 + aPage->SetLocked(ETrue);
1.982 + return aPage->StartPtr();
1.983 + }
1.984 +
1.985 + return NULL;
1.986 + }
1.987 +
1.988 +/**
1.989 +Unlock a locked page.
1.990 +@return TInt KErrNone if unlocking was successful, otherwise system-wide error code.
1.991 +@param aPage the pointer of the page to be unlocked.
1.992 +*/
1.993 +TInt CDynamicDirCache::UnlockPage(TDynamicDirCachePage* aPage)
1.994 + {
1.995 + ASSERT(aPage != NULL);
1.996 + __PRINT1(_L("CDynamicDirCache::UnlockPage(%lx)"), aPage->StartPos());
1.997 + TInt r = iCacheMemoryClient->UnlockSegments(aPage->StartPtr(), PageSizeInSegs());
1.998 + if (r == KErrNone)
1.999 + {
1.1000 + aPage->SetLocked(EFalse);
1.1001 + }
1.1002 + return r;
1.1003 + }
1.1004 +
1.1005 +/**
1.1006 +Decommit a locked or unlocked page.
1.1007 +@return TInt KErrNone if decommition was successful, otherwise system-wide error code.
1.1008 +@param aPage the pointer of the page to be decommitted.
1.1009 +*/
1.1010 +TInt CDynamicDirCache::DecommitPage(TDynamicDirCachePage* aPage)
1.1011 + {
1.1012 + ASSERT(aPage != NULL);
1.1013 + __PRINT1(_L("CDynamicDirCache::DecommitPage(%lx)"), aPage->StartPos());
1.1014 + if (aPage)
1.1015 + {
1.1016 + TInt r = iCacheMemoryClient->DecommitSegments(aPage->StartPtr(), PageSizeInSegs());
1.1017 + if (r == KErrNone)
1.1018 + {
1.1019 + aPage->SetLocked(EFalse);
1.1020 + aPage->SetValid(EFalse);
1.1021 + }
1.1022 + return r;
1.1023 + }
1.1024 + return KErrArgument;
1.1025 + }
1.1026 +
1.1027 +/////////////////////////// aluxiliary functions //////////////////////////////////
1.1028 +/**
1.1029 +Calculate the page size in segments. Segment size is the size of the kernel memory unit that cache memory manager manages.
1.1030 +We are making assumption here about the page size: page size should always be either less than segment size
1.1031 +or multiple times of segment size
1.1032 +@return TUint32 the page size in segments.
1.1033 +*/
1.1034 +TUint32 CDynamicDirCache::PageSizeInSegs() const
1.1035 + {
1.1036 + // initialize cache memory manager as all file systems have mounted by now
1.1037 + ASSERT(CCacheMemoryManagerFactory::CacheMemoryManager());
1.1038 + const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
1.1039 +
1.1040 + // Page size should be non-zero
1.1041 + ASSERT(iPageSizeInBytes);
1.1042 +
1.1043 + TUint32 segs = iPageSizeInBytes >> SegmentSizeInBytesLog2;
1.1044 + return segs > 0 ? segs : 1;
1.1045 + }
1.1046 +
1.1047 +/**
1.1048 +Deque the page from locked queue or unlocked queue. All pages are managed through these two queues, expect iActive
1.1049 +page.
1.1050 +@param aPage the pointer of the page to be dequeued
1.1051 +@return TInt KErrArgument if aPage is invalid, otherwise KErrNone.
1.1052 +*/
1.1053 +TInt CDynamicDirCache::DeQueue(TDynamicDirCachePage* aPage)
1.1054 + {
1.1055 + ASSERT(aPage);
1.1056 + if (!aPage)
1.1057 + return KErrArgument;
1.1058 +
1.1059 + if (aPage->iType == TDynamicDirCachePage::ELocked)
1.1060 + {
1.1061 + aPage->Deque();
1.1062 + aPage->SetPageType(TDynamicDirCachePage::EUnknown);
1.1063 + --iLockedQCount;
1.1064 + }
1.1065 + else if (aPage->iType == TDynamicDirCachePage::EUnlocked)
1.1066 + {
1.1067 + aPage->Deque();
1.1068 + aPage->SetPageType(TDynamicDirCachePage::EUnknown);
1.1069 + --iUnlockedQCount;
1.1070 + }
1.1071 + else
1.1072 + {
1.1073 + ASSERT(0);
1.1074 + return KErrArgument;
1.1075 + }
1.1076 + return KErrNone;
1.1077 + }
1.1078 +
1.1079 +/**
1.1080 +Insert a page to the first position of locked queue or unlocked queue.
1.1081 +@param aPage the pointer of the page to be inserted.
1.1082 +@param aType the type of the queue to be inserted.
1.1083 +@return TInt KErrArgument if aPage is invalid, otherwise KErrNone.
1.1084 +*/
1.1085 +TInt CDynamicDirCache::AddFirstOntoQueue(TDynamicDirCachePage* aPage, TDynamicDirCachePage::TPageType aType)
1.1086 + {
1.1087 + ASSERT(aPage);
1.1088 + if (!aPage)
1.1089 + return KErrArgument;
1.1090 +
1.1091 + if (aType == TDynamicDirCachePage::ELocked)
1.1092 + {
1.1093 + iLockedQ.AddFirst(*aPage);
1.1094 + aPage->SetPageType(TDynamicDirCachePage::ELocked);
1.1095 + ++iLockedQCount;
1.1096 + }
1.1097 + else if (aType == TDynamicDirCachePage::EUnlocked)
1.1098 + {
1.1099 + iUnlockedQ.AddFirst(*aPage);
1.1100 + aPage->SetPageType(TDynamicDirCachePage::EUnlocked);
1.1101 + ++iUnlockedQCount;
1.1102 + }
1.1103 + else
1.1104 + {
1.1105 + ASSERT(0);
1.1106 + return KErrArgument;
1.1107 + }
1.1108 +
1.1109 + return KErrNone;
1.1110 + }
1.1111 +
1.1112 +/**
1.1113 +Remove a page from the lookup table, indexed by the starting media address of the page content.
1.1114 +@param aPagePos the starting media position of the page to be removed.
1.1115 +*/
1.1116 +TInt CDynamicDirCache::LookupTblRemove(TInt64 aPagePos)
1.1117 + {
1.1118 + if (aPagePos == 0)
1.1119 + {
1.1120 + return KErrNone;
1.1121 + }
1.1122 +
1.1123 + TInt r = iLookupTable.Remove(TLookupEntry(aPagePos, 0, NULL));
1.1124 + return r;
1.1125 + }
1.1126 +
1.1127 +/**
1.1128 +Insert a page to the lookup table, indexed by the starting media address of the page content.
1.1129 +@param aPagePos the starting media position of the page to be inserted.
1.1130 +*/
1.1131 +TInt CDynamicDirCache::LookupTblAdd(TDynamicDirCachePage* aPage)
1.1132 + {
1.1133 + ASSERT(aPage);
1.1134 + if (!aPage)
1.1135 + return KErrArgument;
1.1136 +
1.1137 + if (aPage->StartPos() == 0)
1.1138 + {
1.1139 + return KErrNone;
1.1140 + }
1.1141 +
1.1142 + TInt r = iLookupTable.Insert(TLookupEntry(aPage->StartPos(), iPageSizeInBytes, aPage));
1.1143 + return r;
1.1144 + }
1.1145 +
1.1146 +/**
1.1147 +Reset the media address of the page to 0, also invalidate the page.
1.1148 +@param aPage the pointer of the page to be reset.
1.1149 +*/
1.1150 +TInt CDynamicDirCache::ResetPagePos(TDynamicDirCachePage* aPage)
1.1151 + {
1.1152 + ASSERT(aPage);
1.1153 + if (!aPage)
1.1154 + return KErrArgument;
1.1155 +
1.1156 + aPage->ResetPos();
1.1157 + return KErrNone;
1.1158 + }
1.1159 +
1.1160 +/**
1.1161 +Search the lookup table to find the page start with a specific media address.
1.1162 +@param aPos the starting media address to be searched.
1.1163 +*/
1.1164 +TDynamicDirCachePage* CDynamicDirCache::LookupTblFind(TInt64 aPos)
1.1165 + {
1.1166 + if (aPos == 0)
1.1167 + {
1.1168 + ASSERT(0);
1.1169 + return NULL;
1.1170 + }
1.1171 +
1.1172 + TLookupEntry* entry = iLookupTable.Find(TLookupEntry(aPos, 0, NULL));
1.1173 + if(entry)
1.1174 + {
1.1175 + // last entry on used queue is used as the 'active' page & may not be valid
1.1176 + if (!entry->iPage->IsValid())
1.1177 + return NULL;
1.1178 +
1.1179 + return entry->iPage;
1.1180 + }
1.1181 +
1.1182 + return NULL;
1.1183 + }