diff -r 87c71b25c937 -r 88ee4cf65e19 remotestoragefw/remotefileengine/src/rsfwpermanentstore.cpp --- a/remotestoragefw/remotefileengine/src/rsfwpermanentstore.cpp Wed Jun 09 10:37:35 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,885 +0,0 @@ -/* -* Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: Provides persistent storage for memory blocks -* -*/ - - -// This is a simple block based permanent storage, in which transient -// indices are computed on the fly when all data is sequentially read -// from the storage. -// -// The data is put into "slots" that consist of one or more "blocks". -// Subsequent updates to the data slots only use the current slot -// if the required slot size (block count) has not changed. -// -// The storage contains a header that may contain any data. -// In addition, Each slot contains a header (of type TInt) that -// describes the size of the data in the slot. -// -// The file can be compressed for space efficiency. -// -// The assumption is that the store is first opened for reading for loading -// the data, and then it is only opened for writing until the file is closed. -// -// (We don't use CRsfwPermanentStore because besides data, we should -// also maintain the indices in a stream of its own) - -// INCLUDE FILES -#include -#include - -#include "rsfwpermanentstore.h" -#include "mdebug.h" - - -// CONSTANTS -const TUint KHeaderStart = 0xbabefade; -const TInt KSlotHeaderSize = 4; // sizeof(TInt) -const TInt KDefaultBlockSize = 128; // default block size in bytes -// max value for integer read from the stream, subsequently used to create descriptor -const TInt KMaxDescriptorSize = 16384; - - -// ============================ MEMBER FUNCTIONS ============================== - -// ---------------------------------------------------------------------------- -// TFileHeader::ExternalizeL -// ---------------------------------------------------------------------------- -// -void TFileHeader::ExternalizeL(RWriteStream& aStream) const - { - aStream.WriteInt32L(iHeaderStart); - aStream.WriteInt32L(iBlockSize); - aStream.WriteInt32L(iHeaderSize); - aStream << *iHeader; - } - -// ---------------------------------------------------------------------------- -// TFileHeader::InternalizeL -// ---------------------------------------------------------------------------- -// -void TFileHeader::InternalizeL(RReadStream& aStream) - { - iHeaderStart = aStream.ReadInt32L(); - iBlockSize = aStream.ReadInt32L(); - if (iBlockSize < 0 || iBlockSize > KMaxDescriptorSize) - { - User::Leave(KErrCorrupt); - } - iHeaderSize = aStream.ReadInt32L(); - if (iHeaderSize < 0 || iHeaderSize > KMaxDescriptorSize) - { - User::Leave(KErrCorrupt); - } - iHeader = HBufC8::NewL(aStream, iHeaderSize); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::NewL -// ---------------------------------------------------------------------------- -// -CRsfwPermanentStore* CRsfwPermanentStore::NewL(const TDesC& aPath, - TInt aHeaderSize, - TInt aBlockSize) - { - CRsfwPermanentStore* self = new (ELeave) CRsfwPermanentStore(); - CleanupStack::PushL(self); - self->ConstructL(aPath, aHeaderSize, aBlockSize); - CleanupStack::Pop(self); - return self; - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::~CRsfwPermanentStore -// ---------------------------------------------------------------------------- -// -CRsfwPermanentStore::~CRsfwPermanentStore() - { - ClearFreeBlockLists(); - iSlots.Close(); - iFileReadStream.Close(); - iFileWriteStream.Close(); - iFile.Close(); - iFs.Close(); - delete iFileHeader.iHeader; - delete iZeroBlock; - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::ConstructL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::ConstructL(const TDesC& aPath, - TInt aHeaderSize, - TInt aBlockSize) - { - DEBUGSTRING(("CRsfwPermanentStore::ConstructL()")); - User::LeaveIfError(iFs.Connect()); - iPath.Copy(aPath); - - iHeaderSize = aHeaderSize; - // Offset to the block data - iFileHeaderSize = iHeaderSize + sizeof(TFileHeader); - TRAPD(err, LoadHeaderL()); - if (err == KErrNone) - { - // Read parameters from the existing file, if any - iHeaderSize = iFileHeader.iHeaderSize; - iBlockSize = iFileHeader.iBlockSize; - } - else - { - // There was no existing file - DEBUGSTRING(("LoadHeaderL returns %d", err)); - if (aBlockSize) - { - iBlockSize = aBlockSize; - } - else - { - iBlockSize = KDefaultBlockSize; - } - iFileHeader.iHeaderStart = KHeaderStart; - iFileHeader.iHeaderSize = iHeaderSize; - iFileHeader.iBlockSize = iBlockSize; - } - // Compute the offset to data blocks - // (this is 4 bytes too many but that is OK ...) - iFileHeaderSize = iHeaderSize + sizeof(TFileHeader); - // Make a block of zeroes - iZeroBlock = HBufC8::NewL(iBlockSize); - iZeroBlock->Des().FillZ(); - DEBUGSTRING(("ConstructL() done, blocksize=%d", iBlockSize)); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::ResetL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::ResetL(TBool aWriting) - { - // This function is called by the client - // before starting to read or write data slots - if (aWriting) - { - SetFileStateL(EFileStateWriting); - // Set write pointer to the end of the file - MStreamBuf* streamBuf = iFileWriteStream.Sink(); - TInt size = streamBuf->SizeL(); - iWriteBlockNumber = (size - iFileHeaderSize) / iBlockSize; - if ((iWriteBlockNumber * iBlockSize) != (size - iFileHeaderSize)) - { - DEBUGSTRING(("ResetL(): file size incorrect (%d)", - size)); - } - } - else - { - // reading - SetFileStateL(EFileStateReading); - // Skip file header - MStreamBuf* streamBuf = iFileReadStream.Source(); - streamBuf->SeekL(MStreamBuf::ERead, - EStreamBeginning, - iFileHeaderSize); - iReadBlockNumber = 0; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::Commit -// ---------------------------------------------------------------------------- -// -TInt CRsfwPermanentStore::Commit() - { - TInt err = KErrNone; - // Commit writing - if (iFileState == EFileStateWriting) - { - MStreamBuf* streamBuf = iFileWriteStream.Sink(); - err = streamBuf->Synch(); - } - return err; - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::Purge -// ---------------------------------------------------------------------------- -// -TInt CRsfwPermanentStore::Purge() - { - iFileReadStream.Close(); - iFileWriteStream.Close(); - iFile.Close(); - return iFs.Delete(iPath); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::CompactL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::CompactL() - { - // Compact the file by dropping empty slots. - // The slot table is also fixed and the free block lists are cleared - // to reflect the new file layout. - - // This function must not be called while the file is opened for reading. - // It is most efficient to call this function before any data is read - // (then there is no slot table to fix) - - // This function must be called before doing GetNextDataL() - // (must be followed by ResetL()). - // However, this function can be called while doing PutDataL(). - - DEBUGSTRING(("CompactL()")); - SetFileStateL(EFileStateClosed); - SetFileStateL(EFileStateReading); - - TBuf dstPath; - dstPath.Copy(iPath); - dstPath.Append('a'); - RFile dstFile; - User::LeaveIfError(dstFile.Replace(iFs, - dstPath, - EFileShareAny | EFileWrite)); - CleanupClosePushL(dstFile); - RFileWriteStream dstFileWriteStream(dstFile); - CleanupClosePushL(dstFileWriteStream); - MStreamBuf* streamBuf = iFileReadStream.Source(); - - // Copy header - dstFileWriteStream.WriteL(iFileReadStream, iFileHeaderSize); - - RArray gaps; - CleanupClosePushL(gaps); - - TInt blockNumber = 0; - TInt lastReadBlockNumber = 0; - TInt nextWriteBlockNumber = 0; - TInt err = KErrNone; - while (err == KErrNone) - { - TSlot gap; - TInt dataLength = 0; - TRAP(err, dataLength = iFileReadStream.ReadInt32L()); - if (err == KErrNone) - { - TInt blockCount; - if (dataLength >= 0) - { - // real data - blockCount = BlockCount(dataLength); -#if 0 - DEBUGSTRING(("Copying at block %d, count %d", - blockNumber, - blockCount)); -#endif - // Back off four bytes - streamBuf->SeekL(MStreamBuf::ERead, - EStreamMark, - -KSlotHeaderSize); - dstFileWriteStream.WriteL(iFileReadStream, - blockCount * iBlockSize); - lastReadBlockNumber = blockNumber; - nextWriteBlockNumber += blockCount; - } - else - { - // empty slot - DEBUGSTRING(("Compacting at block %d", blockNumber)); - blockCount = -dataLength; - streamBuf->SeekL(MStreamBuf::ERead, - EStreamMark, - blockCount * iBlockSize - KSlotHeaderSize); - // Mark block position - gap.iIndex = 0; // not needed here - gap.iBlockNumber = blockNumber; - gap.iBlockCount = blockCount; - gaps.Append(gap); - } - blockNumber += blockCount; - } - } - if (err == KErrEof) - { - err = KErrNone; - } - // Replace old file with the compressed file - SetFileStateL(EFileStateClosed); - dstFileWriteStream.Close(); - dstFile.Close(); - if ((err == KErrNone) && gaps.Count()) - { - // No errors and some compaction was achieved - err = iFs.Delete(iPath); - if (err == KErrNone) - { - err = iFs.Rename(dstPath, iPath); - if (err == KErrNone) - { - DEBUGSTRING(("CompactL(): gaps %d slots %d", - gaps.Count(), - iSlots.Count())); - if (gaps.Count() && iSlots.Count()) - { - // Fix slot table (0(n**2)) - TInt oldBlockNumber = 0; - TInt newBlockNumber = 0; - while (oldBlockNumber <= lastReadBlockNumber) - { - if (gaps.Count()) - { - // still more gaps ... - if (oldBlockNumber == gaps[0].iBlockNumber) - { - oldBlockNumber += gaps[0].iBlockCount; - gaps.Remove(0); - } - } - if (oldBlockNumber != newBlockNumber) - { - FixSlot(oldBlockNumber, newBlockNumber); - } - oldBlockNumber++; - newBlockNumber++; - } - } - } - } - // Clear free block lists - ClearFreeBlockLists(); - // Setup next block to write - iWriteBlockNumber = nextWriteBlockNumber; - } - else - { - // Some error occured or no compaction was achieved - TInt r = iFs.Delete(dstPath); -#ifdef _DEBUG - DEBUGSTRING(("CompactL(): destination file deletion returns %d ", r)); -#endif - } - - CleanupStack::PopAndDestroy(3, &dstFile); // gaps, dstFileWriteStream, dstFile - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::SetHeaderL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::SetHeaderL(TDesC8& aHeader) - { - delete iFileHeader.iHeader; - iFileHeader.iHeader = NULL; - iFileHeader.iHeader = aHeader.AllocL(); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::Header -// ---------------------------------------------------------------------------- -// -const HBufC8* CRsfwPermanentStore::Header() - { - if (iFileHeader.iHeader) - { - return iFileHeader.iHeader; - } - else - { - return NULL; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::GetNextDataL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::GetNextDataL(TUint8* aData, - TInt& aDataLength, - TInt& aIndex) - { - // Return the next slotful of data. - // This function must only be used for sequential access - SetFileStateL(EFileStateReading); - - MStreamBuf* streamBuf = iFileReadStream.Source(); - - TBool done = EFalse; - while (!done) - { - TInt dataLength = 0; - // Eventually leaves with KErrEof - dataLength = iFileReadStream.ReadInt32L(); - TInt blockCount; - if (dataLength >= 0) - { - // Fill data - iFileReadStream.ReadL(aData, dataLength); - aDataLength = dataLength; - aIndex = iIndex; - - // Update block map - blockCount = BlockCount(dataLength); -#if 0 - DEBUGSTRING(( - "GetNextDataL(): index=%d, block=%d, count=%d, len=%d", - iIndex, - iReadBlockNumber, - blockCount, - dataLength)); -#endif - - ReserveSlot(iIndex, iReadBlockNumber, blockCount); - iIndex++; - iReadBlockNumber += blockCount; - - // Update read position to the start of next block - TInt offset = iBlockSize - - (KSlotHeaderSize + dataLength) % iBlockSize; - if (offset != iBlockSize) - { - streamBuf->SeekL(MStreamBuf::ERead, EStreamMark, offset); - } - - done = ETrue; - } - else - { - // Negative length indicates a number of free blocks. - // Put such empty blocks into the free block list - blockCount = -dataLength; - PutToFreeBlockList(iReadBlockNumber, blockCount); - - // Seek to the next slot - streamBuf->SeekL(MStreamBuf::ERead, - EStreamMark, - blockCount * iBlockSize - KSlotHeaderSize); - iReadBlockNumber += blockCount; - } - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::PutDataL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::PutDataL(const TUint8* aData, - TInt aDataLength, - TInt& aIndex) - { - // Write data with the given index - // If the index < 0, this a new data - SetFileStateL(EFileStateWriting); - - if (aDataLength == 0) - { - // We just want to dispose of the slot - ClearSlotL(aIndex); - return; - } - - TBool done = EFalse; - TInt blockCount = BlockCount(aDataLength); - if (aIndex >= 0) - { - // Check if we have space in the existing slot - TSlot* slot = Slot(aIndex); - // We should always find the slot - if (slot) - { - if (slot->iBlockCount == blockCount) - { - // We can use the current slot - WriteBlocksL(aData, aDataLength, slot->iBlockNumber); - done = ETrue; - } - else - { - // Clear the slot - ClearSlotL(aIndex); - } - } - else - { - DEBUGSTRING(("Slot %d not found!", aIndex)); - } - } - else - { - // Allocate new index - aIndex = iIndex++; - } - - if (!done) - { - // Try to get a free slot - TInt blockNumber = GetFromFreeBlockList(blockCount); - if (blockNumber == KErrNotFound) - { - // We have to append to the file - blockNumber = iWriteBlockNumber; - iWriteBlockNumber += blockCount; - } - - ReserveSlot(aIndex, blockNumber, blockCount); - WriteBlocksL(aData, aDataLength, blockNumber); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::BlockCount -// ---------------------------------------------------------------------------- -// -TInt CRsfwPermanentStore::BlockCount(TInt aDataLength) - { - // Get the block count for a given data size - return (KSlotHeaderSize + aDataLength - 1) / iBlockSize + 1; - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::StreamPosition -// ---------------------------------------------------------------------------- -// -TInt CRsfwPermanentStore::StreamPosition(TInt aBlockNumber) - { - // Get the stream position from block position - return (iFileHeaderSize + aBlockNumber * iBlockSize); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::Slot -// ---------------------------------------------------------------------------- -// -TSlot* CRsfwPermanentStore::Slot(TInt aIndex) - { - // Find the slot with the given index - TSlot slot; // dummy slot for Find() - slot.iIndex = aIndex; - TInt i = iSlots.Find(slot); - if (i != KErrNotFound) - { - return &iSlots[i]; - } - else - { - return NULL; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::FixSlot -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::FixSlot(TInt aOldBlockNumber, TInt aNewBlockNumber) - { - // Assign a new starting block to the slot that used to - // start at aOldBlockNumber. - // The block numbers are changed due to compaction - - // thus the block numbers can only become smaller. - TInt i; - for (i = 0; i < iSlots.Count(); i++) - { - TSlot& slot = iSlots[i]; - // Note that this function can also be called with block numbers - // that do not start a slot - then there will be no match - if (slot.iBlockNumber == aOldBlockNumber) - { - DEBUGSTRING(("Fixing slot %d = %d", - aOldBlockNumber, - aNewBlockNumber)); - slot.iBlockNumber = aNewBlockNumber; - return; - } - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::SetFileStateL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::SetFileStateL(TInt aFileState) - { - DEBUGSTRING(("CRsfwPermanentStore::SetFileStateL")); - DEBUGSTRING(("iFileState = %d, aFileState = %d", iFileState, aFileState)); - if (iFileState != aFileState) - { - switch (iFileState) - { - case EFileStateClosed: - { - if (aFileState == EFileStateReading) - { - DEBUGSTRING(("opening a closed file for reading")); - DEBUGSTRING16(("path is %S", &iPath)); - User::LeaveIfError(iFile.Open(iFs, - iPath, - EFileShareAny | EFileRead)); - TInt size; - iFile.Size(size); - DEBUGSTRING(("opening successfull, file size is %d", size)); - DEBUGSTRING(("header size %d", iFileHeaderSize)); - // sanity - if (size < iFileHeaderSize) - { - // Close the file and leave the file state as "closed" - iFile.Close(); - User::Leave(KErrNotFound); - } - else - { - iFileReadStream.Attach(iFile); - } - } - else - { - // EFileStateWriting - TInt err = iFile.Open(iFs, iPath, EFileShareAny | EFileWrite); - if (err != KErrNone) - { - // The file did not exist - User::LeaveIfError( - iFile.Create(iFs, - iPath, - EFileShareAny | EFileWrite)); - } - TInt size; - User::LeaveIfError(iFile.Size(size)); - iFileWriteStream.Attach(iFile); - if (size < iFileHeaderSize) - { - // Store header if this was a new file - SaveHeaderL(); - } - } - } - break; - - case EFileStateReading: - case EFileStateWriting: - { - // close and redo - if (iFileState == EFileStateReading) - { - iFileReadStream.Close(); - } - else - { - iFileWriteStream.Close(); - } - iFile.Close(); - iFileState = EFileStateClosed; - SetFileStateL(aFileState); - } - break; - - default: - break; - } - - iFileState = aFileState; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::LoadHeaderL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::LoadHeaderL() - { - DEBUGSTRING(("CRsfwPermanentStore::LoadHeaderL")); - SetFileStateL(EFileStateReading); - iFileHeader.InternalizeL(iFileReadStream); - ResetL(EFalse); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::SaveHeaderL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::SaveHeaderL() - { - // Write header with filler - iFileHeader.ExternalizeL(iFileWriteStream); - MStreamBuf* streamBuf = iFileWriteStream.Sink(); - TInt fileHeaderSize = streamBuf->TellL(MStreamBuf::EWrite).Offset(); - TInt residue = iFileHeaderSize - fileHeaderSize; - HBufC8* fill = HBufC8::NewLC(residue); - TPtr8 fillZ = fill->Des(); - fillZ.SetLength(residue); - fillZ.FillZ(); - DEBUGSTRING(("SaveHeader(): header=%d, filler=%d", - iFileHeaderSize, - fillZ.Length())); - iFileWriteStream.WriteL(fillZ); - Commit(); - CleanupStack::PopAndDestroy(fill); // fill - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::ClearFreeBlockLists -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::ClearFreeBlockLists() - { - TInt i; - for (i = 0; i < iFreeBlockLists.Count(); i++) - { - iFreeBlockLists[i].iFreeBlockList.Close(); - } - iFreeBlockLists.Close(); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::ClearSlotL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::ClearSlotL(TInt aIndex) - { - // Mark a slot as unused in the file and - // add the slot in the free block list - - TSlot s; // dummy slot for iSlots.Find() - s.iIndex = aIndex; - TInt i = iSlots.Find(s); - if (i != KErrNotFound) - { - TSlot& slot = iSlots[i]; - // Mark the slot in the file as empty - TInt pos = iFileHeaderSize + slot.iBlockNumber * iBlockSize; - - DEBUGSTRING(("ClearSlotL(): index=%d, block=%d, count=%d, pos=%d", - aIndex, - slot.iBlockNumber, - slot.iBlockCount, - pos)); - - MStreamBuf* streamBuf = iFileWriteStream.Sink(); - streamBuf->SeekL(MStreamBuf::EWrite, EStreamBeginning, pos); - iFileWriteStream.WriteInt32L(-slot.iBlockCount); - - // Add the slot in the free block list - PutToFreeBlockList(slot.iBlockNumber, slot.iBlockCount); - - // Delete the slot from the slot table - iSlots.Remove(i); - } - else - { - DEBUGSTRING(("ClearSlotL(): index=%d not found!", aIndex)); - User::Leave(KErrNotFound); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::WriteBlocksL -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::WriteBlocksL(const TUint8* aData, - TInt aDataLength, - TInt aBlockNumber) - { - // Put the given data in the slot specified by the index - TInt pos = iFileHeaderSize + aBlockNumber * iBlockSize; - -#if 0 - DEBUGSTRING(("WriteBlocksL(): block=%d, len=%d, pos=%d", - aBlockNumber, - aDataLength, - pos)); -#endif -#if 0 - TInt size; - iFile.Size(size); - - DEBUGSTRING(("size=%d", size)); -#endif - - MStreamBuf* streamBuf = iFileWriteStream.Sink(); - streamBuf->SeekL(MStreamBuf::EWrite, EStreamBeginning, pos); - - // Write the data in the file (preceded by the length) - iFileWriteStream.WriteInt32L(aDataLength); - iFileWriteStream.WriteL(aData, aDataLength); - - // We have to fill the whole slot if this is the last slot - // in the file. Well, we will will the last bock of all slots - TInt residue = iBlockSize - (KSlotHeaderSize + aDataLength) % iBlockSize; - if (residue != iBlockSize) - { - iFileWriteStream.WriteL(iZeroBlock->Des().Ptr(), residue); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::ReserveSlot -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::ReserveSlot(TInt aIndex, - TInt aBlockNumber, - TInt aBlockCount) - { - TSlot slot; - - slot.iIndex = aIndex; - slot.iBlockNumber = aBlockNumber; - slot.iBlockCount = aBlockCount; - iSlots.Append(slot); - } - - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::PutToFreeBlockList -// ---------------------------------------------------------------------------- -// -void CRsfwPermanentStore::PutToFreeBlockList(TInt aBlockPos, TInt aBlockCount) - { - while (iFreeBlockLists.Count() < aBlockCount) - { - // Construct list until blockCount size - TFreeBlockList freeBlockList; - iFreeBlockLists.Append(freeBlockList); - } - iFreeBlockLists[aBlockCount - 1].iFreeBlockList.Append(aBlockPos); - } - -// ---------------------------------------------------------------------------- -// CRsfwPermanentStore::GetFromFreeBlockList -// ---------------------------------------------------------------------------- -// -TInt CRsfwPermanentStore::GetFromFreeBlockList(TInt aBlockCount) - { - // Only support exact matches. - // That is, bigger slots are not broken into smaller slots - if (iFreeBlockLists.Count() < aBlockCount) - { - // no list - return KErrNotFound; - } - - TFreeBlockList& freeBlockList = iFreeBlockLists[aBlockCount - 1]; - if (freeBlockList.iFreeBlockList.Count() == 0) - { - // no entries in the list - return KErrNotFound; - } - - // Get the first entry in the list - TInt blockPos = freeBlockList.iFreeBlockList[0]; - freeBlockList.iFreeBlockList.Remove(0); - return blockPos; - } - -// End of File