--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/store/UPAGE/UP_STOR.CPP Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,402 @@
+// Copyright (c) 1998-2009 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:
+//
+
+#include "UP_STD.H"
+
+#include <pbe.h>
+
+EXPORT_C void TStorePagePoolToken::ExternalizeL(RWriteStream& aStream) const
+/** Externalises a TStorePagePoolToken object to a stream.
+
+@param aStream Stream to which the object should be externalised */
+ {
+ aStream<<iHead;
+ aStream<<iAvail;
+ }
+
+EXPORT_C void TStorePagePoolToken::InternalizeL(RReadStream& aStream)
+/** Internalises a TStorePagePoolToken object from a stream.
+
+@param aStream Stream from which the object should be internalised */
+ {
+ aStream>>iHead;
+ aStream>>iAvail;
+ }
+
+// Class RStorePagePool
+
+EXPORT_C RStorePagePool::RStorePagePool()
+ : iStore(NULL)
+/** Default constructor. */
+ {}
+
+EXPORT_C RStorePagePool::RStorePagePool(CPageCache& aCache)
+ : TCachePagePool(aCache),iStore(NULL)
+/** Constructor with a page cache for the pool.
+
+@param aCache Page cache for the pool */
+ {}
+
+EXPORT_C RStorePagePool::RStorePagePool(CStreamStore& aStore)
+/** Constructor with a stream store to use for the pool.
+
+@param aStore Stream store to use for the pool */
+ {
+ Create(aStore);
+ }
+
+EXPORT_C RStorePagePool::RStorePagePool(CStreamStore& aStore,const TStorePagePoolToken& aToken)
+/** Constructor with a stream store and settings to use for the pool.
+
+@param aStore Stream store to use for the pool
+@param aToken Stream store pool settings */
+ {
+ Open(aStore,aToken);
+ }
+
+EXPORT_C void RStorePagePool::Create(CStreamStore& aStore)
+/** Creates a new pool.
+
+@param aStore Stream store to use for the pool */
+ {
+ iStore=&aStore;
+ iHead=KNullStreamId;
+ iAvail=KNullPageRef;
+ iDirty=EFalse;
+ }
+
+EXPORT_C void RStorePagePool::Open(CStreamStore& aStore,const TStorePagePoolToken& aToken)
+/** Opens an existing pool.
+
+@param aStore Stream store for the pool
+@param aToken Pool settings */
+ {
+ iStore=&aStore;
+ iHead=aToken.iHead;
+ iAvail=aToken.iAvail;
+ iDirty=EFalse;
+ }
+
+EXPORT_C TStorePagePoolToken RStorePagePool::Token() const
+/** Gets an object that encapsulates the page pool settings.
+
+That object can then be used to externalise the settings.
+
+@return Encapsulates the page pool settings */
+ {
+ return TStorePagePoolToken(iHead,iAvail);
+ }
+
+EXPORT_C void RStorePagePool::Close()
+/** Flushes and purges the page cache and stops using the stream store. */
+ {
+ TCachePagePool::Flush();
+ Release();
+ }
+
+EXPORT_C TBool RStorePagePool::ReclaimL()
+/** Deletes the first stream that stores reclaimable pages in the store.
+
+@return True if there are remaining streams (pages), false if there are no
+more streams */
+ {
+ __ASSERT_DEBUG(iStore!=NULL,Panic(EPageNotOpen));
+ __ASSERT_ALWAYS(iAvail==KNullPageRef,Panic(EPageReclaimAvailable));
+ if (iHead!=KNullStreamId)
+ {
+ RStoreReadStream out;
+ out.OpenLC(*iStore,iHead);
+ TStreamId next;
+ out>>next;
+ CleanupStack::PopAndDestroy();
+ iStore->DeleteL(iHead);
+ iHead=next;
+ MarkDirty();
+ if (next!=KNullStreamId)
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+EXPORT_C void RStorePagePool::ReclaimAllL()
+/** Deletes all streams in the store. */
+ {
+ while (ReclaimL())
+ ;
+ }
+
+EXPORT_C TPageRef RStorePagePool::ExtendL(const TAny* aPage,TPageReclamation aReclamation)
+//
+// Create a new page.
+//
+ {
+ return StorePagePool::ExtendL(*this,aPage,aReclamation);
+ }
+
+EXPORT_C void RStorePagePool::WriteL(TPageRef aRef,const TAny* aPage,TPageChange aChange)
+//
+// Write a page to the store.
+//
+ {
+ StorePagePool::WriteL(*this,aRef,aPage,aChange);
+ }
+
+EXPORT_C void RStorePagePool::ReadL(TPageRef aRef,TAny* aPage)
+//
+// Read from the store into a page.
+//
+ {
+ StorePagePool::ReadL(*this,aRef,aPage);
+ }
+
+EXPORT_C void RStorePagePool::DoDeleteL(TPageRef aRef)
+//
+// Delete from store.
+//
+ {
+ StorePagePool::DeleteL(*this,aRef);
+ }
+
+// Class RSecureStorePagePool
+
+
+
+EXPORT_C RSecureStorePagePool::RSecureStorePagePool(const CPBEncryptSet& aKey)
+ : iKey(aKey)
+ {}
+
+EXPORT_C RSecureStorePagePool::RSecureStorePagePool(CPageCache& aCache, const CPBEncryptSet& aKey)
+ : RStorePagePool(aCache),
+ iKey(aKey)
+ {}
+
+/** Adds a new page to the pool.
+
+@param aPage Data for the page
+@param aReclamation Flags that define how allocated pages can be reclaimed
+@return Reference to newly created page */
+EXPORT_C TPageRef RSecureStorePagePool::ExtendL(const TAny* aPage,TPageReclamation aReclamation)
+ {
+ return StorePagePool::ExtendL(*this,aPage,aReclamation);
+ }
+
+/** Writes data to a page in the pool.
+
+@param aRef Reference to the page to which to write
+@param aPage Data to write
+@param aChange Flags that define how a page should be treated when it is unlocked
+for writing */
+EXPORT_C void RSecureStorePagePool::WriteL(TPageRef aRef,const TAny* aPage,TPageChange aChange)
+ {
+ StorePagePool::WriteL(*this,aRef,aPage,aChange);
+ }
+
+/** Reads a specified page from the pool.
+
+@param aRef Reference to page to read
+@param aPage On return, the page data */
+EXPORT_C void RSecureStorePagePool::ReadL(TPageRef aRef,TAny* aPage)
+ {
+ StorePagePool::ReadL(*this,aRef,aPage);
+ }
+
+/** Deletes a specified page.
+
+@param aRef Reference to page to delete */
+EXPORT_C void RSecureStorePagePool::DoDeleteL(TPageRef aRef)
+ {
+ StorePagePool::DeleteL(*this,aRef);
+ }
+
+// Class StorePagePool
+// the implementation of the clever bits to share code between the secure and plain sotre page pools
+
+const TInt KMaxPageIndex=15;
+
+inline TInt PageSize(const CPBEncryptionBase* aKey)
+ {
+ return aKey ? aKey->MaxCiphertextLength(KPoolPageSize) : KPoolPageSize;
+ }
+
+inline TPageRef PageRef(TStreamId anId,TInt anIndex=0)
+ {
+ __ASSERT_DEBUG(anIndex>=0&&anIndex<=KMaxPageIndex,User::Invariant());
+ return TPageRef((anId.Value()<<4)+anIndex);
+ }
+inline TInt PageIndex(TPageRef aRef)
+ {return aRef.Value()&0xf;}
+inline TStreamId StreamId(TPageRef aRef)
+ {return TStreamId(aRef.Value()>>4);}
+inline TStreamPos PagePos(TInt anIndex,TInt aPageSize)
+ {return TStreamPos(sizeof(TStreamId)+(anIndex-1)*aPageSize);}
+
+void StorePagePool::PadL(RWriteStream& aStream,TInt aLength)
+//
+// zero-pad a stream
+//
+ {
+ TUint8 zero[KPoolPageSize];
+ Mem::FillZ(zero,KPoolPageSize);
+ while ((aLength-=KPoolPageSize)>0)
+ aStream.WriteL(zero,KPoolPageSize);
+ aStream.WriteL(zero,aLength+KPoolPageSize);
+ }
+
+//
+// Encrypt the page to the stream, padding out to full page size
+void StorePagePool::EncryptL(RWriteStream& aStream,const TAny* aPage,const CPBEncryptionBase& aKey)
+ {
+ REncryptStream encrypt;
+ encrypt.OpenLC(aStream,aKey);
+ encrypt.WriteL((const TUint8*)aPage,KPoolPageSize);
+ encrypt.CommitL();
+ CleanupStack::PopAndDestroy(&encrypt);
+ }
+
+//
+// Encrypt the page to the stream, padding out to full page size
+//
+void StorePagePool::EncryptNewL(RWriteStream& aStream,const TAny* aPage,const CPBEncryptionBase& aKey)
+ {
+ TStreamPos pos=aStream.Sink()->TellL(MStreamBuf::EWrite); // remember the start of the data
+ EncryptL(aStream,aPage,aKey);
+ TInt pad=PageSize(&aKey)-(aStream.Sink()->TellL(MStreamBuf::EWrite)-pos); // bytes written
+ __ASSERT_DEBUG(pad>=0,Panic(EPageCipherTextOverrun));
+ if (pad)
+ PadL(aStream,pad);
+ }
+
+//
+// Encrypt the page to the stream, padding out to full page size
+//
+void StorePagePool::DecryptL(RReadStream& aStream,TAny* aPage,const CPBEncryptionBase& aKey)
+ {
+ RDecryptStream decrypt;
+ decrypt.OpenLC(aStream,aKey);
+ decrypt.ReadL((TUint8*)aPage,KPoolPageSize);
+ CleanupStack::PopAndDestroy();
+ }
+
+void StorePagePool::SeekL(MStreamBuf* aBuf,TInt aMark,TPageRef aRef,const CPBEncryptionBase* aKey)
+ {
+ TInt ix=PageIndex(aRef);
+ if (ix)
+ aBuf->SeekL(aMark,PagePos(ix,PageSize(aKey)));
+ }
+
+TPageRef StorePagePool::ExtendL(RStorePagePool& aPool,const TAny* aPage,TPageReclamation aReclamation,const CPBEncryptionBase* aKey)
+ {
+ __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen));
+ TPageRef page;
+ RStoreWriteStream out;
+ if (aReclamation==EPageDeleteOnly)
+ { // non-reclaimable page
+ page=PageRef(out.CreateLC(*aPool.iStore));
+ }
+ else if (aPool.iAvail!=KNullPageRef)
+ { // use free page
+ page=aPool.iAvail;
+ out.OpenLC(*aPool.iStore,StreamId(page));
+ MStreamBuf* buf=out.Sink();
+ SeekL(buf,MStreamBuf::ERead|MStreamBuf::EWrite,page,aKey);
+ RReadStream in(buf);
+ in>>aPool.iAvail;
+ aPool.MarkDirty();
+ }
+ else
+ { // allocate new block, and create free list
+ TStreamId id=out.CreateLC(*aPool.iStore);
+ out<<aPool.iHead; // block list
+ const TInt pad=PageSize(aKey)-sizeof(TPageRef);
+ page=KNullPageRef; // free-list terminator
+ for (TInt index=0;++index<KMaxPageIndex;)
+ {
+ out<<page;
+ PadL(out,pad);
+ page=PageRef(id,index);
+ }
+ aPool.MarkDirty();
+ aPool.iHead=id;
+ aPool.iAvail=page;
+ page=PageRef(id,KMaxPageIndex); // page is written at end
+ }
+ if (aKey)
+ EncryptNewL(out,aPage,*aKey);
+ else
+ out.WriteL((const TUint8*)aPage,KPoolPageSize);
+ out.CommitL();
+ CleanupStack::PopAndDestroy();
+ return page;
+ }
+
+void StorePagePool::WriteL(RStorePagePool& aPool,TPageRef aRef,const TAny* aPage,TPageChange aChange,const CPBEncryptionBase* aKey)
+ {
+ __ASSERT_DEBUG(aChange>=EPageDirty,Panic(EPageChangeInvalid));
+ __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen));
+ RStoreWriteStream out;
+ if (aChange==EPageUpdate)
+ {
+ __ASSERT_DEBUG(PageIndex(aRef)==0,Panic(EPageChangeInvalid));
+ out.ReplaceLC(*aPool.iStore,StreamId(aRef));
+ if (aKey)
+ EncryptNewL(out,aPage,*aKey);
+ else
+ out.WriteL((const TUint8*)aPage,KPoolPageSize);
+ }
+ else
+ { // re-write the page, no padding req'd
+ out.OpenLC(*aPool.iStore,StreamId(aRef));
+ SeekL(out.Sink(),MStreamBuf::EWrite,aRef,aKey);
+ if (aKey)
+ EncryptL(out,aPage,*aKey);
+ else
+ out.WriteL((const TUint8*)aPage,KPoolPageSize);
+ }
+ out.CommitL();
+ CleanupStack::PopAndDestroy();
+ }
+
+void StorePagePool::ReadL(RStorePagePool& aPool,TPageRef aRef,TAny* aPage,const CPBEncryptionBase* aKey)
+ {
+ __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen));
+ RStoreReadStream in;
+ in.OpenLC(*aPool.iStore,StreamId(aRef));
+ SeekL(in.Source(),MStreamBuf::ERead,aRef,aKey);
+ if (aKey)
+ DecryptL(in,aPage,*aKey);
+ else
+ in.ReadL((TUint8*)aPage,KPoolPageSize);
+ CleanupStack::PopAndDestroy(); // in
+ }
+
+void StorePagePool::DeleteL(RStorePagePool& aPool,TPageRef aRef,const CPBEncryptionBase* aKey)
+ {
+ aPool.CacheDeleteL(aRef);
+ __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen));
+ if (PageIndex(aRef)==0)
+ { //non-reclaimable
+ aPool.iStore->DeleteL(StreamId(aRef));
+ return;
+ }
+ // add to free list
+ RStoreWriteStream out;
+ out.OpenLC(*aPool.iStore,StreamId(aRef));
+ SeekL(out.Sink(),MStreamBuf::EWrite,aRef,aKey);
+ out<<aPool.iAvail;
+ out.CommitL();
+ CleanupStack::PopAndDestroy();
+ aPool.iAvail=aRef;
+ aPool.MarkDirty();
+ }