diff -r 000000000000 -r 094583676ce7 PECengine/StorageManager2/ClientSrc/CPEngStorageManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PECengine/StorageManager2/ClientSrc/CPEngStorageManager.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,519 @@ +/* +* Copyright (c) 2002 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: Implementation of class CPEngStorageManager +* +*/ + + +// INCLUDE FILES +#include +#include +#include "CPEngStorageManager.h" +#include "CPEngStoreEntry.h" +#include "PEngHashTool.h" +#include "PEngStorageGlobals.h" +#include "PEngStorageServerCommon.h" +#include "MPEngStorageManagerWatcher.h" +#include "CPEngSessionSlotId.h" + +#include "PEngMessagePacker.h" + +// Debug prints +#include "PresenceDebugPrint.h" + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::CPEngStoreEntry +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CPEngStorageManager::CPEngStorageManager( + MPEngStorageManagerWatcher& aWatcher ) + : iAccessCount( 1 ), // init count to 1 + iStorageManagerWatcher( aWatcher ), + iSessionSlot( aWatcher.SessionSlotId() ) + { + // Increase handler count + iStorageManagerWatcher.Open(); // CSI: 65 # + } + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::BaseConstructL +// Symbian 2nd phase Base constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPEngStorageManager::ConstructL( + RPEngStorageClient& aStorageMainClient ) + { + // connect to the Server with the Sub Session + HBufC8* sessionName = iSessionSlot.PackLC(); + User::LeaveIfError( iSubFolderClient.Connect( aStorageMainClient, *sessionName ) ); + CleanupStack::PopAndDestroy(); // sessionName + } + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngStorageManager* CPEngStorageManager::NewL( + MPEngStorageManagerWatcher& aWatcher, + RPEngStorageClient& aStorageMainClient ) + { + CPEngStorageManager* self = CPEngStorageManager::NewLC( aWatcher, aStorageMainClient ); + + CleanupStack::Pop( ); // self + return self; + } + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngStorageManager* CPEngStorageManager::NewLC( + MPEngStorageManagerWatcher& aWatcher, + RPEngStorageClient& aStorageMainClient ) + { + CPEngStorageManager* self = + new ( ELeave ) CPEngStorageManager( aWatcher ); + + CleanupClosePushL( *self ); + self->ConstructL( aStorageMainClient ); + + return self; + } + +// Destructor +CPEngStorageManager::~CPEngStorageManager() + { + // Use same Panic as CObject is using for Reference counted objects + __ASSERT_ALWAYS( iAccessCount == 0, + User::Panic( KPEngSMEuserCBasePanic, + KPEngSMEuserCBasePanicReason ) ); + + iSubFolderClient.Close(); + // close handle to watcher + iStorageManagerWatcher.Close(); + } + + +// ----------------------------------------------------------------------------- +// ==== Functions from the MPEngStorageManager base classes ==================== +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::Open() +// ----------------------------------------------------------------------------- +// +void CPEngStorageManager::Open() + { + iAccessCount++; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::Close() +// ----------------------------------------------------------------------------- +// +void CPEngStorageManager::Close() + { + iAccessCount--; + if ( iAccessCount == 0 ) + { + delete this; + } + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::StoreL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageManager::StoreL( const CPEngStoreEntry& aStoreEntry ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::StoreL() [%S][%d]" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + + // Etrue to obey lock of the store entry + StoreEntryL( aStoreEntry, ETrue ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::StoreExclusiveL() +// ----------------------------------------------------------------------------- +// +void CPEngStorageManager::StoreExclusiveL( const CPEngStoreEntry& aStoreEntry ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::StoreExclusiveL() [%S][%d]" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + + + // EFalse to obey lock of the store entry + StoreEntryL( aStoreEntry, EFalse ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::RetrieveL() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::RetrieveL( CPEngStoreEntry& aStoreEntry, + TBool aObeyVersion /* ETrue */ ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::RetrieveL() [%S][%d]" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + + // Get Entry size for all parts + TPEngStorageType entryType ( aStoreEntry.StorageType() ); + // Initialize size with some room for version numbers + TUint32 entrySize( KStoreVersionSize + aStoreEntry.EntrySize() ); + if ( entrySize <= 0 ) + { + entrySize = KStoreEntryDefaultSize; + } + // do not believe and correct entry size + entrySize += entrySize / KStoreEntryRetrieveOverlap; + + // create buffer with estimated size + HBufC8* buffer = HBufC8::NewLC( entrySize ); + TPtr8 ptr = buffer->Des(); + + // get Buffer from Server, positive response is size of needed buffer, it it's too small + TInt err( 1 ); // to make at least one round in following loop + while ( err > KErrNone ) + { + err = iSubFolderClient.Retrieve( aStoreEntry.StorageId(), + aStoreEntry.StorageType(), + ptr ); + + // check if we need to realloc buffer + if ( err > KErrNone ) + { + // realloc buffer and once more, be careful with Clean up stack + CleanupStack::PopAndDestroy(); // buffer + buffer = HBufC8::NewLC( err ); + ptr.Set( buffer->Des() ); + } + } + + if ( err == KErrNotFound ) + { + CleanupStack::PopAndDestroy( ); // buffer + // set store Version back to the Zero,so following store wont fail + aStoreEntry.iEntryVersion = KErrNone; + return KErrNotFound; + } + + User::LeaveIfError( err ); + + RDesReadStream drs( buffer->Des() ); + CleanupClosePushL( drs ); + + // store version of the entry + TInt32 retrievedVersion = drs.ReadInt32L(); + + // check if internalizing is even necessary + if ( aObeyVersion && ( retrievedVersion == aStoreEntry.iEntryVersion ) ) + { + CleanupStack::PopAndDestroy( 2 );//buffer, drs + return KErrNone; + } + + entrySize = ptr.Size(); + + // Internalize all parts of the store entry + TPEngStorageType currentType( EPEngStorageBasicFirst ); + while ( !( currentType & EPEngStorageBasicLast ) ) + { + if ( entryType & currentType ) + { + TInt strmPartType = drs.ReadInt32L(); + TInt strmPartLength = drs.ReadInt32L(); + + if ( currentType != strmPartType ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::RetrieveL() [%S][%d] - type order mismatch: strmPartType %d currentType %d" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType(), strmPartType, currentType ); + User::Panic( KPEngSMPanic, EPEngSM_TypeOrderMismatch ); + } + + if ( strmPartLength != KErrNotFound ) + { + MStreamBuf* rawStream = drs.Source(); + TStreamPos readStartPos = rawStream->TellL( MStreamBuf::ERead ); + + aStoreEntry.InternalizeL( drs, currentType ); + + TStreamPos readEndPos = rawStream->TellL( MStreamBuf::ERead ); + TInt readLength = readEndPos - readStartPos; + + // panic client if did not internalize properly + if ( readLength != strmPartLength ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::RetrieveL() [%S][%d] - internalize length mismatch: readLength %d strmPartLength %d" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType(), strmPartType, currentType ); + + User::Panic( KPEngSMPanic, EPEngSM_InternalizeLengthMismatch ); + } + } + } + + currentType = static_cast( currentType << 1 ); // rotate once to left + } + + // update version after successful internalize + aStoreEntry.iEntryVersion = retrievedVersion; + aStoreEntry.iSize = entrySize; + CleanupStack::PopAndDestroy( 2 );//buffer, drs + return KErrNone; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::Delete() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::Delete( + const CPEngStoreEntry& aStoreEntry ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::Delete() [%S][%d] - By entry " ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + + return iSubFolderClient.Delete( aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::Delete() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::Delete( const TDesC& aStoreEntryId ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::Delete() [%S] - By entry id" ), &aStoreEntryId ); + // set as type everything + return iSubFolderClient.Delete( aStoreEntryId , EPEngMixedPermanentCached ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::LockedL() +// ----------------------------------------------------------------------------- +// +TBool CPEngStorageManager::LockedL( + const CPEngStoreEntry& aStoreEntry, + TPengStorageLockPriority aPriority /*EStorageLockLevelBasic*/ ) const + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::LockedL() [%S][%d] - Priority %d" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType(), aPriority ); + + TInt ret( iSubFolderClient.StoreEntryLocked( aStoreEntry.StorageId(), + aStoreEntry.StorageType(), + aPriority ) ); + User::LeaveIfError( ret ); + return ( ret == 0 ? EFalse : ETrue ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::LockedL() +// ----------------------------------------------------------------------------- +// +TBool CPEngStorageManager::Locked( + const CPEngStoreEntry& aStoreEntry, + TPengStorageLockPriority aPriority /*EStorageLockLevelBasic*/ ) const + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::Locked() [%S][%d] - Priority %d" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType(), aPriority ); + + TInt ret( iSubFolderClient.StoreEntryLocked( aStoreEntry.StorageId(), + aStoreEntry.StorageType(), + aPriority ) ); + return ( ret <= 0 ? EFalse : ETrue ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::Lock() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::Lock( + const CPEngStoreEntry& aStoreEntry, + TPengStorageLockPriority aPriority /*EStorageLockLevelBasic*/, + TBool aCreateEntry /* = ETrue */ ) const + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::Locked() [%S][%d] - Priority %d" ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType(), aPriority ); + + return iSubFolderClient.LockStoreEntry( aStoreEntry.StorageId(), + aStoreEntry.StorageType(), + aPriority, + aCreateEntry ); + } + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::Unlock() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::Unlock( const CPEngStoreEntry& aStoreEntry ) const + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::Unlock() store id: %S, StoreTypeL %d " ), + &aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + return iSubFolderClient.UnlockStoreEntry( aStoreEntry.StorageId(), aStoreEntry.StorageType() ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::NotifyChangedSId() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::NotifyChangedSId( const TDesC& aChangedSId, + TPEngStorageType aSidStorageType ) + { + return iSubFolderClient.NotifyChangedSIdBlind( aChangedSId, aSidStorageType ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::BufferServerSideNotifications() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::BufferServerSideNotifications( TInt aCount ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::BufferServerSideNotifications() - Count %d" ), + aCount ); + return iSubFolderClient.BufferServerSideNotifications( aCount ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::ReleaseServerSideBuffering() +// ----------------------------------------------------------------------------- +// +TInt CPEngStorageManager::ReleaseServerSideBuffering( TInt aCount ) + { + PENG_DP( D_PENG_LIT( "CPEngStorageManager::ReleaseServerSideBuffering() - count %d" ), + aCount ); + return iSubFolderClient.ReleaseServerSideBuffering( aCount ); + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::StorageManagerWatcher() +// ----------------------------------------------------------------------------- +// +MPEngStorageManagerWatcher& CPEngStorageManager::StorageManagerWatcher() + { + return iStorageManagerWatcher; + } + + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::SessionSlotId() +// ----------------------------------------------------------------------------- +// +const CPEngSessionSlotId& CPEngStorageManager::SessionSlotId() const + { + return iSessionSlot; + } + + +// ============================================================================= +// =============== New private Functions of the class ========================== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngStorageManager::BaseStoragePath +// Stores Store Entry given as an argument. +// Based on the passed parameter is obeyed lock or not. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngStorageManager::StoreEntryL( const CPEngStoreEntry& aStoreEntry, + TBool aObeyLock ) + { + // count how much space wee need for storing + TUint32 entrySize( KStoreVersionSize + aStoreEntry.EntrySize() ); + // do not believe and correct entry size + entrySize += entrySize / KStoreEntrySizeTolerance; + + // get buffer for transfer + CBufFlat* buf = CBufFlat::NewL( entrySize ); + CleanupStack::PushL( buf ); + RBufWriteStream ws; + CleanupClosePushL( ws ); + ws.Open( *buf ); // CSI: 65 # + + // get all parts of the store entry, and Externalize them + TPEngStorageType entryType ( aStoreEntry.StorageType() ); + TPEngStorageType currentType( EPEngStorageBasicFirst ); + + // Write current version of the entry, increased by one, for server info + ws.WriteInt32L( aStoreEntry.iEntryVersion + 1 ); + + // Write actual data + while ( !( currentType & EPEngStorageBasicLast ) ) + { + if ( entryType & currentType ) + { + + //Write first type and type length "holder" + ws.WriteInt32L( currentType ); + ws.WriteInt32L( KErrNotFound ); + + MStreamBuf* rawStream = ws.Sink(); + + //Do the write and cache locally the write start and points + TStreamPos typeStartPos = rawStream->TellL( MStreamBuf::EWrite ); + aStoreEntry.ExternalizeL( ws, currentType ); + TStreamPos typeEndPos = rawStream->TellL( MStreamBuf::EWrite ); + + //Caculate write length + TInt typeLength = typeEndPos - typeStartPos; + + //Patch the length holder + //-4 below: Length holder is TInt32 (4 bytes) just before the actual data + typeStartPos -= 4; + rawStream->SeekL( MStreamBuf::EWrite, typeStartPos ); + ws.WriteInt32L( typeLength ); + rawStream->SeekL( MStreamBuf::EWrite, typeEndPos ); + } + + // rotate once to left + currentType = static_cast( currentType << 1 ); + } + + buf->Compress(); + entrySize = buf->Size(); + // update store type, depends if lock shall be obeyed + entryType = static_cast + ( aObeyLock ? entryType : ( entryType | EPEngStorageLockIgnored ) ); + + // store data to the server + User::LeaveIfError( iSubFolderClient.Store( aStoreEntry.StorageId(), + entryType , buf->Ptr( 0 ) ) ); + + // update version after successful update by 1 + ( const_cast ( aStoreEntry ) ).iEntryVersion = + aStoreEntry.iEntryVersion % KMaxTInt + 1; + + ( const_cast ( aStoreEntry ) ).iSize = entrySize; + + CleanupStack::PopAndDestroy( 2 );// ws & buffer + } + +// End of File +