sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #if !defined(__U32PERM_H__) sl@0: #define __U32PERM_H__ sl@0: #if !defined(__S32STD_H__) sl@0: #include sl@0: #endif sl@0: #if !defined(__U32FRAME_H__) sl@0: #include "U32FRAME.H" sl@0: #endif sl@0: sl@0: #if defined(_DEBUG)&&!defined(__SMALL_BUNDLE) sl@0: //#define __SMALL_BUNDLE sl@0: #endif sl@0: sl@0: //Forward declaratons sl@0: class RPermanentFileStoreIter; sl@0: class TDriveInfo; sl@0: sl@0: //The offset of the header of a permanent file store. sl@0: //Since all permanent file store operations work in their own coordinate system, where physical file offset 32 is sl@0: //logical offset 0, KPermanentStoreHeaderOffset is set with -16, which means that the physical file offset is 32 - 16 = 16. sl@0: const TInt KPermanentStoreHeaderOffset=-16; sl@0: sl@0: //Permanent file store header length: sizeof(backup TOC ref) + sizeof(handle) + sizeof(TOC ref) + sizeof(crc) = 4 + 4 + 4 + 2 = 14 sl@0: const TInt KPermanentStoreHeaderLength=14; sl@0: sl@0: //Backup TOC ref length - 4 bytes sl@0: const TInt KPermanentStoreBackupLength=4; sl@0: sl@0: // sl@0: const TInt KMaskHandleHash=0xff000000; sl@0: const TInt KHandleInvalid=0x80000000; sl@0: const TInt KHandleTocBase=0x40000000; sl@0: const TInt KMaskHandleClear=0x30000000; sl@0: const TInt KMaskHandleGen=0x0f000000; sl@0: const TInt KIncHandleGen=0x01000000; sl@0: // sl@0: const TInt KMaxHandleIndex=0x00ffffff; sl@0: const TInt KMaskHandleIndex=0x00ffffff; sl@0: const TInt KSizeHandleIndex=3; sl@0: // sl@0: const TInt KTocDeltaCap = 64; //up to 64 entries in a delta TOC sl@0: const TInt KTocDeltaMagic = 2; sl@0: const TInt KMaxTocDeltaMagic = KMaxTUint16; sl@0: const TInt KTocDelta=KHandleInvalid; sl@0: // sl@0: const TInt KOffsetTocHeader=-12; sl@0: const TInt KSizeTocEntry=5; //base toc entry size is 5 bytes (when stored in the file, 8 bytes when presented in memory) sl@0: const TInt KSizeTocDeltaEntry=8;//delta toc entry size is 8 bytes sl@0: const TInt KSizeTocDeltaExtra=7; sl@0: const TInt KElementsTocBuf=48; sl@0: const TInt KBackTocBuf=20*KSizeTocEntry; sl@0: const TInt KSizeTocBuf=KElementsTocBuf*KSizeTocEntry; sl@0: sl@0: //TPermanentStoreHeader class. sl@0: // sl@0: //Represents the data kept in the permanent store file header. sl@0: //Data members: sl@0: // - iBackup - "backup TOC reference", 32-bits integer, which keeps the 31-bit file offset of the backup TOC. sl@0: // Plays important role in the "store commit" procedure. sl@0: // The LSB is a "dirty" bit. If during the store opening phase the dirty bit is found to be set, sl@0: // then it means - the previous "store commit" operation has not been completed successfully and sl@0: // the backup TOC shall be used instead of the TOC; sl@0: // - iHandle - 32-bit stream handle (MSB - invalid/deleted, 3 bits - unused, 4 bits - generation counter, 24 bits - stream handle). sl@0: // Plays important role in the "stream relocation" procedure during store compaction. sl@0: // iHandle keeps the handle of the stream being relocated, so if the commit phase fails, the original stream entry sl@0: // can be restored at the moment when the store is reopened; sl@0: // - iRef - Current "TOC reference". Represents a file offset, where the current TOC is; sl@0: // - iCrc - 16-bit CRC, protecting iBackup, iHandle, iRef; sl@0: class TPermanentStoreHeader sl@0: { sl@0: public: sl@0: TPermanentStoreHeader() {} sl@0: inline TUint8* Ptr(); sl@0: inline const TUint8* Ptr() const; sl@0: TBool IsValid() const; sl@0: // sl@0: inline TPermanentStoreHeader(TInt aToc); sl@0: inline TPermanentStoreHeader(TInt aBackupToc,TInt aHandle,TInt aReference); sl@0: // sl@0: inline TBool IsDirty() const; sl@0: inline void MarkDirty(); sl@0: inline void SetBackupToc(TInt aBackupToc); sl@0: inline TInt BackupToc() const; sl@0: // sl@0: inline TInt Handle() const; sl@0: inline TInt Reference() const; sl@0: private: sl@0: void Set(TInt aBackupToc,TInt aHandle,TInt aReference); sl@0: private: sl@0: TUint32 iBackup; sl@0: TInt32 iHandle; sl@0: TInt32 iRef; sl@0: TUint16 iCrc; sl@0: }; sl@0: sl@0: //CPermanentStoreToc class. sl@0: // sl@0: //Represents the data kept in the permanent file store TOC (Table Of Content). sl@0: //Each TOC consists of: sl@0: // - TOC header - CPermanentStoreToc::STocHead structure; sl@0: // - set of TOC entries - CPermanentStoreToc::TEntry structure; sl@0: // sl@0: //Each TOC entry consists of: sl@0: // - A stream handle (32 bits: MSB - invalid/deleted, 3 bits - unused, 4 bits - generation counter, 24 bits - stream handle); sl@0: // - A stream ref - the offset of the stream data in the permannet file store; sl@0: NONSHARABLE_CLASS(CPermanentStoreToc) : public CBase sl@0: { sl@0: public: sl@0: struct TEntry sl@0: { sl@0: TInt handle; sl@0: TInt ref; sl@0: static TInt Compare(const TEntry&, const TEntry&); sl@0: }; sl@0: struct STocHead sl@0: { sl@0: TInt32 primary; sl@0: TInt32 avail; sl@0: TUint32 count; sl@0: }; sl@0: enum TPut {EWrite,ETestBeforeWrite}; sl@0: public: sl@0: static CPermanentStoreToc* NewL(TStreamPos aBase,TStreamExchange& aHost,TInt aToc,TInt aBaseReloc); sl@0: ~CPermanentStoreToc(); sl@0: // sl@0: inline TInt Extent() const; sl@0: void Move(TInt aToc,TInt anExtent); sl@0: // sl@0: inline TBool IsVirtual() const; sl@0: TInt RealizeL(TInt aPrimary,TInt anExtent) const; sl@0: void Adopt(TInt aToc,TInt aPrimary); sl@0: // sl@0: inline TInt Primary() const; sl@0: inline void Changed(); sl@0: // sl@0: TInt AllocL(TInt anOffset); sl@0: TInt AllocL(); sl@0: void Cancel(TInt aHandle); sl@0: void FreeL(TInt aHandle); sl@0: TInt AtL(TInt aHandle) const; sl@0: void PutL(TInt aHandle,TInt anOffset,TPut aCheck); sl@0: TInt GetL(TInt aHandle); sl@0: TInt Set(TInt aHandle,TInt anOffset); sl@0: // sl@0: CPermanentStoreToc(TStreamPos aBase,TStreamExchange& aHost); sl@0: void ConstructL(TInt aToc,TInt aBaseReloc); sl@0: sl@0: TInt RefSpan(TInt aHandle,TInt& aLength); sl@0: sl@0: private: sl@0: inline TStreamPos Base() const; sl@0: inline TStreamExchange& Host() const; sl@0: inline const TEntry* Entry(TInt aHandle) const; sl@0: TEntry* Entry(TInt aHandle); sl@0: TEntry& FetchL(TInt aHandle); sl@0: TEntry& DoAllocL(); sl@0: TInt DoAtL(TInt aHandle) const; sl@0: void PutBaseL(TInt aHandle, TInt aReference); sl@0: void PutDeltaL(TInt aPos, TInt aHandle, TInt aReference); sl@0: void PutTocL(TInt aTocBase, TPut aCheck); sl@0: inline TBool HasDelta() const; sl@0: TBool IsDelta() const; sl@0: TInt InternalizeL(RReadStream& aIn, TInt aBaseReloc); sl@0: TInt DeltaL(RFrame16Buf& aBuf,TInt aExtent,const STocHead& aHead) const; sl@0: TInt RewriteL(RFrame16Buf& aBuf,TInt aExtent,const STocHead& aHead) const; sl@0: TInt SmallTocL(RFrame16Buf& aBuf,TInt aExtent,const STocHead& aHead) const; sl@0: private: sl@0: TInt iPrimary; sl@0: TInt iAvail; sl@0: TInt iCount; sl@0: RArray iEntries; sl@0: // sl@0: TStreamPos iBase; sl@0: TStreamExchange* iHost; sl@0: TInt iMagic; sl@0: TInt iOff; sl@0: TInt iExt; sl@0: TInt iTocOff; sl@0: TInt iTocExt; sl@0: __MUTABLE TInt iWindow; sl@0: __MUTABLE TUint8 iBuf[KSizeTocBuf]; sl@0: private: sl@0: friend class RPermanentStoreTocIter; sl@0: }; sl@0: sl@0: // sl@0: class RPermanentStoreTocIter sl@0: { sl@0: public: sl@0: typedef CPermanentStoreToc::TEntry TEntry; sl@0: typedef CPermanentStoreToc::STocHead STocHead; sl@0: public: sl@0: RPermanentStoreTocIter(const CPermanentStoreToc& aTable); sl@0: inline void Close(); sl@0: void Release(); sl@0: // sl@0: void ResetL(); sl@0: TBool NextL(TEntry& anEntry); sl@0: private: sl@0: const CPermanentStoreToc& iTable; sl@0: RFrame16Buf iBuf; sl@0: TInt iIndex; sl@0: TInt iCount; sl@0: TInt iNext; sl@0: const TEntry* iDelta; sl@0: const TEntry* iDeltaEnd; sl@0: }; sl@0: sl@0: // sl@0: class TPermanentStoreCache sl@0: { sl@0: public: sl@0: struct TItem {TInt handle;TInt offset;TInt extent;}; sl@0: public: sl@0: inline TPermanentStoreCache(); sl@0: const TItem* At(TInt aHandle) const; sl@0: void Relocated(TInt aHandle,TInt anOffset); sl@0: void Put(const TItem* anItem,TInt anOffset,TInt anExtent); sl@0: void Add(TInt aHandle,TInt anOffset,TInt anExtent); sl@0: void Remove(TInt aHandle); sl@0: void Invalidate(); sl@0: private: sl@0: enum {EItems=2*16-1}; sl@0: private: sl@0: TItem iItems[EItems]; sl@0: }; sl@0: sl@0: // sl@0: NONSHARABLE_CLASS(CPermanentStoreCoord) : public CBase sl@0: { sl@0: private: sl@0: enum {EReady,EBackup=0x1,EClip=0x2}; sl@0: enum TFileQoS sl@0: { sl@0: EUnknown, // sl@0: ESimple, //File, "write byte" is an atomic operation sl@0: EBlockAtomic, //File, "block write" is an atomic operation sl@0: ETransactional //Transactional file system. sl@0: }; sl@0: typedef TPermanentStoreCache::TItem TItem; sl@0: public: sl@0: inline TBool IsTrim() const; sl@0: TStreamPos LimitL(); sl@0: inline void Clipped(); sl@0: // sl@0: TStreamId PrimaryL(); sl@0: void ChangedL(); sl@0: TBool CommitL(TStreamId aPrimary); sl@0: TBool RevertL(TStreamId& aPrimary); sl@0: // sl@0: TStreamId ExtendL(); sl@0: void DeleteL(TStreamId anId); sl@0: // sl@0: CPermanentStoreCoord(TStreamPos aBase,TStreamExchange& aHost); sl@0: void InternalizeL(RReadStream& aStream); sl@0: ~CPermanentStoreCoord(); sl@0: private: sl@0: void CanExtendL(); sl@0: TInt DoCreateL(); sl@0: void DoReplaceL(TInt aHandle); sl@0: TInt DoOpenL(TInt& anOffset,TInt aHandle); sl@0: void DoRelease(TInt aHandle,TInt anOffset,TInt anExtent); sl@0: TInt DoCommit(TInt aHandle,TInt anOffset,TInt anExtent); sl@0: // sl@0: inline TStreamPos Base() const; sl@0: inline TStreamExchange& Host() const; sl@0: inline TInt Toc() const; sl@0: inline CPermanentStoreToc& Table() const; sl@0: CPermanentStoreToc& TableL(); sl@0: CPermanentStoreToc& ConsolidateL(); sl@0: void RelocateL(TInt aHandle,TInt anOffset); sl@0: void MoveL(TInt aToc,TInt anExtent); sl@0: inline TUint Generation() const; sl@0: inline void Inc(); sl@0: inline void Dec(); sl@0: inline TBool Accessed() const; sl@0: TFileQoS FileQoSL(); sl@0: TBool IsBlockAtomicL(TInt aDriveNo) const; sl@0: // sl@0: MStreamBuf* BeginL(TPermanentStoreHeader& aHeader); sl@0: private: sl@0: TStreamPos iBase; sl@0: TStreamExchange *iHost; sl@0: TInt iToc; sl@0: CPermanentStoreToc* iTable; sl@0: TInt iReloc; sl@0: TInt iTarget; sl@0: TPermanentStoreCache iCache; sl@0: // sl@0: TUint iGen; sl@0: TInt iRefs; sl@0: TInt iAccess; sl@0: TInt iExtend; sl@0: TInt iState; sl@0: TInt iExt; sl@0: TFileQoS iFileQos; sl@0: private: sl@0: friend class HPermanentStoreBuf; sl@0: friend class CPermanentStoreCollector; sl@0: friend class RPermanentFileStoreIter; sl@0: }; sl@0: // sl@0: NONSHARABLE_CLASS(HPermanentStoreBuf) : public RFrame16Buf sl@0: { sl@0: public: sl@0: static HPermanentStoreBuf* CreateL(CPermanentStoreCoord& aCoord,TStreamId& anId,TInt aMode=ERead|EWrite); sl@0: static HPermanentStoreBuf* ReplaceL(CPermanentStoreCoord& aCoord,TStreamId anId,TInt aMode=ERead|EWrite); sl@0: static HPermanentStoreBuf* OpenL(CPermanentStoreCoord& aCoord,TStreamId anId,TInt aMode=ERead|EWrite); sl@0: // sl@0: virtual ~HPermanentStoreBuf(); sl@0: private: sl@0: static HPermanentStoreBuf* NewLC(CPermanentStoreCoord& aCoord); sl@0: static HPermanentStoreBuf* ExtendLC(CPermanentStoreCoord& aCoord,TInt aMode); sl@0: inline HPermanentStoreBuf(CPermanentStoreCoord& aCoord); sl@0: inline CPermanentStoreCoord& Coord() const; sl@0: // sl@0: void DoRelease(); sl@0: void DoSynchL(); sl@0: private: sl@0: CPermanentStoreCoord* iCoord; sl@0: TInt iHandle; sl@0: }; sl@0: // sl@0: class TPermanentStoreStreamIter sl@0: { sl@0: #if defined(__SMALL_BUNDLE) sl@0: enum {EBundleSize=8-1}; sl@0: #else sl@0: enum {EBundleSize=64-1}; sl@0: #endif sl@0: public: sl@0: void Reset(); sl@0: TInt FillL(CPermanentStoreToc& aToc); sl@0: TInt Next(); sl@0: // sl@0: void Relocated(TInt aStream); sl@0: private: sl@0: static void Push(TInt* aHeap,TInt* aHole,TInt aValue); sl@0: static TInt PopPush(TInt* aHeap,TInt* anEnd,TInt aValue); sl@0: private: sl@0: TInt* iNext; sl@0: const TInt* iFinish; sl@0: TInt iMore; sl@0: TInt iPos; sl@0: TInt iTable[EBundleSize]; sl@0: }; sl@0: sl@0: class TPermanentStoreRelocator; sl@0: NONSHARABLE_CLASS(CPermanentStoreCollector) : public CBase,public MIncrementalCollector sl@0: { sl@0: enum TState sl@0: { sl@0: EGetFree,ESkip,EInitRelocator,EFillRelocator,EEvalRelocator,EScanRelocator,ERelocateStream,ERelocateToc, sl@0: EFastSort,EFastExtent,EFastRelocate sl@0: }; sl@0: enum {EGranularity = 64}; sl@0: enum {EExtentStep = 64}; sl@0: public: sl@0: struct TEntry sl@0: { sl@0: TInt len; sl@0: RPermanentStoreTocIter::TEntry entry; sl@0: }; sl@0: public: sl@0: static CPermanentStoreCollector* CompactorL(CPermanentStoreCoord& aCoord); sl@0: static CPermanentStoreCollector* ReclaimerL(CPermanentStoreCoord& aCoord); sl@0: protected: sl@0: CPermanentStoreCollector(CPermanentStoreCoord& aCoord); sl@0: ~CPermanentStoreCollector(); sl@0: private: sl@0: void DoRelease(); sl@0: void DoResetL(TInt& aCount); sl@0: void DoNextL(TInt& aStep,TInt& aTotal); sl@0: // sl@0: TInt GetFreeL(); sl@0: TInt SkipL(TInt& aTotal); sl@0: TInt InitRelocator(); sl@0: TInt FillRelocatorL(); sl@0: TInt EvalRelocatorL(); sl@0: TInt ScanRelocator(); sl@0: TInt RelocateStreamL(); sl@0: TBool HaveEnoughSpace() const; sl@0: TInt ExtentL(TInt aStream); sl@0: // sl@0: // fast compaction sl@0: TInt FastResetL(); sl@0: void FastSort(); sl@0: void FastExtentL(TInt& aTotal); sl@0: void FastRelocateL(TInt& aTotal); sl@0: TEntry* BestFit(TInt aPos, TInt aExt, TEntry* aFirst, TEntry* aLast); sl@0: // sl@0: // common utilities sl@0: void RelocateTocL(TInt& aTotal); sl@0: void RelocateStreamL(const TEntry& aReloc, TInt aExtent); sl@0: TInt RelocateL(TInt aStream, TInt aLength, TFrameType16 aType, TInt aExtent); sl@0: // sl@0: inline TBool Compacting() const; sl@0: inline CPermanentStoreCoord& Coord() const; sl@0: inline TStreamExchange& Host() const; sl@0: private: sl@0: CPermanentStoreCoord* iCoord; sl@0: TUint iCoordGen; sl@0: TStreamExchange* iHost; sl@0: TStreamMark iMark; sl@0: TState iState; sl@0: TInt iFree; sl@0: TInt iEnd; sl@0: TEntry* iNext; sl@0: TEntry* iLast; sl@0: RArray iStreams; sl@0: TPermanentStoreRelocator* iReloc; sl@0: TPermanentStoreStreamIter iIter; sl@0: }; sl@0: sl@0: #include "U32PERM.INL" sl@0: #endif