PECengine/StorageManager2/ServerSrc/CPEngStorageFolder.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PECengine/StorageManager2/ServerSrc/CPEngStorageFolder.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,891 @@
+/*
+* 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:  One Storage folder management
+*
+*/
+
+
+
+// INCLUDE FILES
+#include    <e32std.h>
+
+#include <f32file.h>
+
+#include    "CPEngStorageFolder.h"
+#include    "PEngInternalGlobalConsts.h"
+
+// Data entries
+#include    "CPEngDataEntry.h"
+
+// Request Handlers
+#include    "CPEngRequestHandler.h"
+#include    "CPEngHandlerListenSIDs.h"
+
+#include    "CPEngSessionSlotState.h"
+#include    "CPEngSessionSlotId.h"
+
+// Clients message
+#include    "RPEngMessage.h"
+
+// Storages globals
+#include    "PEngStorageGlobals.h"
+
+// Hash tools
+#include    "PEngHashTool.h"
+
+#include    "TPEngStorageServerBTreeKeys.h"
+
+//  Debug prints
+#include    "PresenceDebugPrint.h"
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::CPEngStorageFolder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CPEngStorageFolder::CPEngStorageFolder(
+    RFs& aFs,
+    const TDesC& aTempFolder,
+    RBuf16& aCommBuff )
+        : iFs( aFs ),
+        iTempFolder( aTempFolder ),
+        iBuffer( aCommBuff ),
+        iDataEntryTree( EBtreeSecure )
+    {
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::ConstructL( )
+    {
+    iObservers = CObjectCon::NewL();
+    // we need to put some number to the CObjectCon::iUniqueID so it takes ownerships
+    iObservers->iUniqueID = reinterpret_cast<TInt>( this );
+
+    iPool = CMemPagePool::NewL();
+    iDataEntryTree.Connect( iPool, &iDataEntryTreeKey );
+    //client must track if the tree is connected or not, if it is not connected,
+    //you MUST NOT call for example ResetL, because it panics!!
+    iTreeConnected = ETrue;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPEngStorageFolder* CPEngStorageFolder::NewL(
+    RFs& aFs,
+    const TDesC& aTempFolder,
+    RBuf16& aCommBuff )
+    {
+    CPEngStorageFolder* self = NewLC( aFs,
+                                      aTempFolder,
+                                      aCommBuff );
+    CleanupStack::Pop(); // self
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPEngStorageFolder* CPEngStorageFolder::NewLC(
+    RFs& aFs,
+    const TDesC& aTempFolder,
+    RBuf16& aCommBuff )
+    {
+    CPEngStorageFolder* self = new( ELeave ) CPEngStorageFolder(
+        aFs,
+        aTempFolder,
+        aCommBuff );
+    CleanupClosePushL( *self );
+    self->ConstructL( );
+    return self;
+    }
+
+
+// Destructor
+CPEngStorageFolder::~CPEngStorageFolder()
+    {
+    // clean tree, ignore error, since thread will be closed anyway
+    TRAP_IGNORE( CleanTreeFromAllEntriesL() );
+
+    delete iSessionState;
+    delete iPool;
+
+    if ( iObservers )
+        {
+        for ( TInt x( iObservers->Count() - 1 ) ; x >= 0  ; --x )
+            {
+            ( *iObservers )[ x ]->Close();
+            }
+        }
+
+    delete iObservers;
+    delete iSessionFolder;
+
+
+#if _BullseyeCoverage
+    cov_write();
+#endif
+    }
+
+
+
+// =============================================================================
+// =============== Functions from CObject base class ===========================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::Close()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::Close ()
+    {
+    if ( iSessionState->SessionSlotState() == EPEngNWPresenceSessionClosed )
+        {
+        CObject::Close();
+        }
+    else
+        {
+        Dec();
+        }
+    }
+
+
+// =============================================================================
+// =============== Functions from MPEngStorageFolder ===========================
+// =============================================================================
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::DataEntryL()
+// -----------------------------------------------------------------------------
+//
+CPEngDataEntry* CPEngStorageFolder::DataEntryL(
+    const TDesC& aSId )
+    {
+    TBtreePos pos;
+    if ( !iTreeConnected )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    CPEngDataEntry* entry = CheckBufferedDataEntries( aSId );
+    if ( entry )
+        {
+        return entry;
+        }
+
+    if ( !iDataEntryTree.FindL( pos, const_cast<TDesC*> ( &aSId ) ) )
+        {
+        return NULL;
+        }
+    else
+        {
+        iDataEntryTree.ExtractAtL( pos, entry );
+        }
+    AddBufferedDataEntry( entry );
+    return entry;
+    }
+
+
+// =============================================================================
+// =============== New Public Functions/ Server used ===========================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::SessionSlotState()
+// -----------------------------------------------------------------------------
+//
+CPEngSessionSlotState& CPEngStorageFolder::SessionSlotState()
+    {
+    return *iSessionState;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::SetSessionSlotState()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::SetSessionSlotState( CPEngSessionSlotState& aState )
+    {
+    delete iSessionState;
+    iSessionState = &aState;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::SetSessionFolder()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::SetSessionFolder( HBufC& aFolder )
+    {
+    delete iSessionFolder;
+    iSessionFolder = &aFolder;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::CommiteStateUpdate()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::CommiteStateUpdate()
+    {
+    if ( iSessionState->SessionSlotState() != EPEngNWPresenceSessionClosed )
+        {
+        // nothing to do, session is active
+        return;
+        }
+    // session is closed, check reference count and clean cached data
+    // inform all observers about change
+    NofifyAllAboutAll();
+    if ( 0 == AccessCount() )
+        {
+        delete this;
+        }
+    else
+        {
+        TRAP_IGNORE( CleanTreeFromAllEntriesL() );
+        }
+    }
+
+// =============================================================================
+// =============== New public Functions / Store Engine =========================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::WriteStoreEntry()
+// -----------------------------------------------------------------------------
+//
+const CPEngDataEntry* CPEngStorageFolder::WriteStoreEntryL(
+    const RPEngMessage& aMessage,
+    TBool aNotifyActive,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    PENG_DP( D_PENG_LIT( "CPEngStorageFolder::WriteStoreEntryL()" ) );
+    // Etrue, that it should be created if it does not exists
+    TBtreePos pos;
+    CPEngDataEntry* storeEntry = GetStoreEntryL( aMessage, ETrue, pos );
+    HBufC8* clientData = aMessage.ReadOneDescriptor8LC( KMessageSlot2 );
+
+    return storeEntry->SetDataLX( clientData,
+                                  static_cast<TPEngStorageType>( aMessage.Int1() ),
+                                  aNotifyActive,
+                                  aSessionId,
+                                  aSubSessionId );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::ReadStoreEntry()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::ReadStoreEntryL(
+    const RPEngMessage& aMessage )
+    {
+    PENG_DP( D_PENG_LIT( "CPEngStorageFolder::ReadStoreEntryL()" ) );
+
+    // get store entry
+    // do not create if does not exists
+    TBtreePos pos;
+    CPEngDataEntry* storeEntry = GetStoreEntryL( aMessage, EFalse, pos );
+
+    storeEntry->AssertStorageTypeL( static_cast<TPEngStorageType>( aMessage.Int1() ) );
+
+    //  write data to the client side, trap error
+    //  if not enough space on client side
+    TInt e ( aMessage.WriteOneDescriptor( KMessageSlot2, storeEntry->DataL() ) );
+    if ( e == KErrOverflow )
+        {
+        // complete message with the length
+        aMessage.Complete( storeEntry->DataL().Length() );
+        // return so message is not completed twice
+        return;
+        }
+
+    // leave if any error
+    User::LeaveIfError( e );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::GetStoryLength()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::GetStoreEntryLengthL(
+    const RPEngMessage& aMessage )
+    {
+    // do not create story entry if it does not exist
+    TBtreePos pos;
+    aMessage.Complete( GetStoreEntryL( aMessage, EFalse, pos )->DataL().Length() );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::RemoveStoreEntry()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::RemoveStoreEntryL(
+    const RPEngMessage& aMessage )
+    {
+    // load if exists, do not create
+    TBtreePos pos;
+    // we actually need position from tree, so true search
+    CPEngDataEntry* storeEntry = GetStoreEntryL( aMessage, EFalse, pos, ETrue );
+    storeEntry->DeleteStoreEntry();
+    // remove store entry from tree
+    iDataEntryTree.DeleteAtL( pos );
+    // removed from tree, not delete instance
+    delete storeEntry;
+    // remove buffered pointers of deleted store entry
+    if ( iBuffDataEntry0 == iBuffDataEntry1 )
+        {
+        iBuffDataEntry1 = NULL;
+        }
+    if ( iBuffDataEntry0 == iBuffDataEntry2 )
+        {
+        iBuffDataEntry2 = NULL;
+        }
+    iBuffDataEntry0 = NULL;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::LockStoreEntry()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::LockStoreEntryL(
+    const RPEngMessage& aMessage,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    // load if exists, or create if does not exists
+    TBtreePos pos;
+    TInt priorityInt( aMessage.Int2() );
+    TBool createEntry = priorityInt & KLockEntryCreateMask;
+    CPEngDataEntry* storeEntry = GetStoreEntryL( aMessage, createEntry, pos );
+    priorityInt &= ~KLockEntryCreateMask;
+    TPengStorageLockPriority priority (
+        static_cast<TPengStorageLockPriority> ( priorityInt ) );
+
+    aMessage.Complete( storeEntry->IncreaseLockCountL( aSessionId,
+                                                       aSubSessionId,
+                                                       priority ) );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::UnlockStoreEntry()
+// -----------------------------------------------------------------------------
+//
+const CPEngDataEntry* CPEngStorageFolder::UnlockStoreEntryL(
+    const RPEngMessage& aMessage,
+    TBool aNotifyActive,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    // load if exists, do not create if does not exists
+    TBtreePos pos;
+    CPEngDataEntry* storeEntry = GetStoreEntryL( aMessage, EFalse, pos );
+
+    // check current lock count, so we avoid hasty notifications
+    if ( !storeEntry->LockCount() )
+        {
+        // item is not locked at all, complete with zero
+        aMessage.Complete( 0 );
+        return NULL;
+        }
+
+    // release lock by one
+    CPEngDataEntry* notifEntry = NULL;
+    TInt lockCount( storeEntry->DecreaseLockCountL( aNotifyActive,
+                                                    aSessionId,
+                                                    aSubSessionId,
+                                                    notifEntry ) );
+    aMessage.Complete( lockCount );
+    return NULL;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::IsStoreEntryLocked()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::IsStoreEntryLockedL(
+    const RPEngMessage& aMessage )
+    {
+    TBtreePos pos;
+    CPEngDataEntry* volatile storeEntry = NULL;
+    TRAPD( e, storeEntry = GetStoreEntryL( aMessage, EFalse, pos ) );
+    if ( e == KErrNotFound )
+        {
+        // if does not exists in store, also not locked
+        aMessage.Complete( KErrNone );
+        return;
+        }
+    // other error leave
+    User::LeaveIfError( e );
+    aMessage.Complete( storeEntry->LockStatus(
+                           static_cast<TPengStorageLockPriority>( aMessage.Int2() ) ) );
+    }
+
+
+
+// =============================================================================
+// =============== New public Functions / Notify Engine ========================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::StartListenSIDsChanges()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::ListenSIDsChangesL(
+    const RPEngMessage& aMessage,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, aSubSessionId,
+                                                          EFolderSubSessListenSIDsChanges );
+    if ( reqHandler )
+        {
+        // this handler already exists, not allowed by multiple
+        User::Leave( KErrAlreadyExists );
+        }
+
+    // create new handler
+    reqHandler = CPEngHandlerListenSIDs::NewLC( *this,
+                                                aMessage,
+                                                aSessionId,
+                                                aSubSessionId );
+    // store new handler
+    iObservers->AddL( reqHandler );
+    CleanupStack::Pop(); // newHandler
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::UpdateListenSIDsScout()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::UpdateListenSIDsScoutL(
+    const RPEngMessage& aMessage,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, aSubSessionId,
+                                                          static_cast<TPEngStorageServerMessages> ( aMessage.Int0() ) );
+    if ( !reqHandler )
+        {
+        // there is not such a request to be reloaded
+        User::Leave( KErrArgument );
+        }
+    reqHandler->ReloadScoutWithNewMessageL( aMessage );
+    }
+
+void CPEngStorageFolder::FetchChangedIdsIndexesL(
+    const RPEngMessage& aMessage,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, aSubSessionId,
+                                                          static_cast<TPEngStorageServerMessages> ( aMessage.Int0() ) );
+    if ( !reqHandler )
+        {
+        // there is not such a request to be reloaded
+        User::Leave( KErrArgument );
+        }
+    reqHandler->ReloadScoutWithNewMessageL( aMessage );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::ReloadAsyncScout()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::ReloadAsyncScoutL(
+    const RPEngMessage& aMessage,
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, aSubSessionId,
+                                                          static_cast<TPEngStorageServerMessages> ( aMessage.Int0() ) );
+    if ( !reqHandler )
+        {
+        // there is not such a request to be reloaded
+        User::Leave( KErrArgument );
+        }
+    reqHandler->ReloadScoutWithNewMessageL( aMessage );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::CancelSubSessionScouts()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::CancelSubSessionRequests(
+    TUint32 aSessionId,
+    TInt aSubSessionId )
+    {
+    for ( TInt x( iObservers->Count() - 1 ) ; x >= 0 ; --x )
+        {
+        CPEngRequestHandler* reqHandler =
+            static_cast<CPEngRequestHandler*>( ( *iObservers )[ x ] );
+        if (
+            ( reqHandler->SessionId() == aSessionId )
+            &&
+            ( reqHandler->SubSessionId() == aSubSessionId )
+        )
+            {
+            reqHandler->CancelRequestD();
+            }
+        }
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::CancelRequest()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::CancelRequest(
+    const RPEngMessage& aMessage,
+    TUint32  aSessionId,
+    TInt aSubSessionId )
+    {
+    CPEngRequestHandler* reqHandler = FindRequestHandler( aSessionId, aSubSessionId,
+                                                          static_cast<TPEngStorageServerMessages> ( aMessage.Int0() ) );
+    // ignore if such a request does not exists
+    if ( reqHandler )
+        {
+        reqHandler->CancelRequestD();
+        }
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::NotifyChangedStorageIdL()
+// -----------------------------------------------------------------------------
+//
+const CPEngDataEntry* CPEngStorageFolder::NotifyChangedStorageIdL(
+    const RPEngMessage& aMessage,
+    TBool aNotifyActive )
+    {
+    // find entry
+    TBtreePos pos;
+    CPEngDataEntry* storeEntry = GetStoreEntryL( aMessage, ETrue, pos );
+
+    if ( aNotifyActive )
+        {
+        // better to go through array from end
+        for ( TInt x( iObservers->Count() - 1 ) ; x >= 0 ; --x )
+            {
+            static_cast<CPEngHandlerListenSIDs*>
+            ( ( *iObservers )[ x ] )->EntryUpdated( *storeEntry );
+            }
+        storeEntry = NULL;
+        }
+
+    //In other cases let the caller to do the notification delayed
+    return storeEntry;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::NotifySIDChanges()
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::NotifySIDChanges(
+    const RPointerArray<CPEngDataEntry>& aEntries )
+    {
+    // better to go through array from end
+    for ( TInt x( iObservers->Count() - 1 ) ; x >= 0 ; --x )
+        {
+        static_cast<CPEngHandlerListenSIDs*>
+        ( ( *iObservers )[ x ] )->NotifyChangedSIDs( aEntries ) ;
+        }
+    }
+
+
+// =============================================================================
+// =============== New private Functions of the class ==========================
+// =============================================================================
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::FindRequestHandler()
+// Find Request Handler
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngRequestHandler* CPEngStorageFolder::FindRequestHandler(
+    TUint32 aSessionId,
+    TInt aSubSession,
+    TPEngStorageServerMessages aFunction )
+    {
+    TInt count( iObservers->Count() );
+    for ( TInt x( 0 ) ; x < count ; x++ )
+        {
+        CPEngRequestHandler* reqHandler = static_cast<CPEngRequestHandler*>( ( *iObservers )[ x ] );
+        if ( ( reqHandler->SessionId() == aSessionId )
+             && ( reqHandler->SubSessionId() == aSubSession )
+             && ( reqHandler->RequestFunction() == aFunction ) )
+            {
+            return reqHandler;
+            }
+        }
+    return NULL;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::GetStoreEntryL()
+// Get Store Entry instance
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngDataEntry* CPEngStorageFolder::GetStoreEntryL(
+    const RPEngMessage& aMessage,
+    TBool aCreateIfNotPressent,
+    TBtreePos& aPos,
+    TBool aTrueSearch /* = EFalse */ )
+    {
+    // read Store ID and type from message
+    aMessage.ReadOneDescriptorL( KMessageSlot0, iBuffer );
+    PENG_DP( D_PENG_LIT( "CPEngStorageFolder::GetStoreEntryL():%S" ), &iBuffer );
+
+    if ( !iTreeConnected )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    CPEngDataEntry* entry = NULL;
+    if ( !aTrueSearch )
+        {
+        entry = CheckBufferedDataEntries( iBuffer );
+        }
+
+    if ( entry )
+        {
+        return entry;
+        }
+
+    if ( !iDataEntryTree.FindL( aPos, &iBuffer ) )
+        {
+        // not in the tree, try to load it, it will be also added to the tree
+        entry = LoadStoreEntryL( iBuffer, aCreateIfNotPressent, aPos, aMessage );
+        }
+    else
+        {
+        iDataEntryTree.ExtractAtL( aPos, entry );
+        }
+    AddBufferedDataEntry( entry );
+    return entry;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::LoadStoreEntryL()
+// Load Store Entry from disc if it exists
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPEngDataEntry* CPEngStorageFolder::LoadStoreEntryL(
+    TDesC& aKey,
+    TBool aCreateIfNotPressent,
+    TBtreePos& aPos,
+    const RPEngMessage& aMessage )
+    {
+    // add it into the tree if entry will be created
+    TPEngStorageType type( static_cast<TPEngStorageType>( aMessage.Int1() ) );
+
+    CPEngDataEntry* entry = CPEngDataEntry::NewLC(
+                                iFs,
+                                iTempFolder,
+                                aKey,
+                                type );
+
+    HBufC* path = NULL;
+    if ( type & EPEngStorageBasicPermanent )
+        {
+        // create Hashed path for the file
+        path = PEngHashTool::HashDescriptorL( aKey );
+        CleanupStack::PushL( path );
+
+        path = path->ReAllocL( path->Length() +
+                               iSessionFolder->Length() );
+
+        CleanupStack::Pop(); // new pointer was received, old buffer deleted
+        // folder delimiter was already there
+        path->Des().Insert( 0, *iSessionFolder );
+        entry->SetHashedPath( path );
+        }
+
+    if ( !( entry->InitializeStoreEntryL() || aCreateIfNotPressent ) )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    // add entry to the tree
+    if ( !iDataEntryTree.InsertL( aPos, entry ) )
+        {
+        User::Leave( KErrGeneral );
+        }
+
+    // notify SIDs observers about new added entry
+    // better to go through array from end
+    for ( TInt x( iObservers->Count() - 1 ) ; x >= 0 ; --x )
+        {
+        static_cast<CPEngHandlerListenSIDs*>
+        ( ( *iObservers )[ x ] )->EntryCreatedL( *entry );
+        }
+
+    CleanupStack::Pop( entry );
+
+    return entry;
+    }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::NofifyAllAboutAll()
+// Notify observer that all observer SIds changed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::NofifyAllAboutAll()
+    {
+    // better to go through array from end
+    for ( TInt x( iObservers->Count() - 1 ) ; x >= 0 ; --x )
+        {
+        static_cast<CPEngHandlerListenSIDs*>
+        ( ( *iObservers )[ x ] )->NotifyAllSIdsChanged();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::NofifyAllAboutAll()
+// Look in buffered data entries for data entry with desired key
+// -----------------------------------------------------------------------------
+//
+CPEngDataEntry* CPEngStorageFolder::CheckBufferedDataEntries(
+    const TDesC& aKey )
+    {
+    if ( iBuffDataEntry0 && KErrNone == iBuffDataEntry0->Key().CompareF( aKey ) )
+        {
+        PENG_DP( D_PENG_LIT(
+                     "CPEngStorageFolder::CheckBufferedDataEntries(0) Search skipped:%S" ),
+                 &aKey );
+        return iBuffDataEntry0;
+        }
+
+    if ( iBuffDataEntry1 && KErrNone == iBuffDataEntry1->Key().CompareF( aKey ) )
+        {
+        PENG_DP( D_PENG_LIT(
+                     "CPEngStorageFolder::CheckBufferedDataEntries(1) Search skipped:%S" ),
+                 &aKey );
+        CPEngDataEntry* entry = iBuffDataEntry1;
+        iBuffDataEntry1 = iBuffDataEntry0;
+        iBuffDataEntry0 = entry;
+        return entry;
+        }
+
+    if ( iBuffDataEntry2 && KErrNone == iBuffDataEntry2->Key().CompareF( aKey ) )
+        {
+        PENG_DP( D_PENG_LIT(
+                     "CPEngStorageFolder::CheckBufferedDataEntries(2) Search skipped:%S" ),
+                 &aKey );
+        AddBufferedDataEntry( iBuffDataEntry2 );
+        return iBuffDataEntry0;
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::AddBufferedDataEntry()
+// Add buffered data entry pointer
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::AddBufferedDataEntry(
+    CPEngDataEntry* aDataEntry )
+    {
+    iBuffDataEntry2 = iBuffDataEntry1;
+    iBuffDataEntry1 = iBuffDataEntry0;
+    iBuffDataEntry0 = aDataEntry;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngStorageFolder::CleanTreeFromAllEntriesL()
+// Clean B tree from all entries
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CPEngStorageFolder::CleanTreeFromAllEntriesL()
+    {
+    if ( !iTreeConnected )
+        {
+        User::Leave( KErrNotReady );
+        }
+    TBtreeMark pos;
+    TBool b = iDataEntryTree.ResetL( pos );
+    iBuffDataEntry0 = NULL;
+    iBuffDataEntry1 = NULL;
+    iBuffDataEntry2 = NULL;
+    while ( b )
+        {
+        CPEngDataEntry* entry;
+        iDataEntryTree.ExtractAtL( pos, entry );
+        if ( entry )
+            {
+            delete entry;
+            }
+        b = iDataEntryTree.NextL( pos );
+        }
+    iDataEntryTree.ClearL();
+    }
+
+
+//  End of File