PECengine/StorageManager2/ClientSrc/CPEngStorageManager.cpp
changeset 0 094583676ce7
--- /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 <e32base.h>
+#include <s32mem.h>
+#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<TPEngStorageType>( 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<TPEngStorageType>( currentType << 1 );
+        }
+
+    buf->Compress();
+    entrySize = buf->Size();
+    // update store type, depends if lock shall be obeyed
+    entryType = static_cast<TPEngStorageType>
+                ( 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<CPEngStoreEntry&> ( aStoreEntry ) ).iEntryVersion =
+        aStoreEntry.iEntryVersion  % KMaxTInt + 1;
+
+    ( const_cast<CPEngStoreEntry&> ( aStoreEntry ) ).iSize = entrySize;
+
+    CleanupStack::PopAndDestroy( 2 );// ws & buffer
+    }
+
+//  End of File
+