ncdengine/provider/storage/src/ncdstoragebase.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 12 Mar 2010 15:43:14 +0200
branchRCL_3
changeset 18 3ba40be8e484
parent 0 ba25891c3a9e
permissions -rw-r--r--
Revision: 201007 Kit: 201008

/*
* Copyright (c) 2006 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 "ncdstoragebase.h"

#include <s32buf.h>

#include "ncddatabasestorageimpl.h"
#include "ncdstoragedataitem.h"
#include "ncdstoragepanics.pan"
#include "catalogsutils.h"

#include "catalogsdebug.h"


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageBase::~CNcdStorageBase()
    {
    DLTRACEIN(( "" ));
    delete iUid;
    delete iStorageFolder;
    delete iName;
    iOpenItems.Reset();
    iRemovedItems.Reset();
    iItems.ResetAndDestroy();
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageBase::CNcdStorageBase( HBufC* aUid, HBufC* aStorageFolder, 
        HBufC* aName ) :
    iUid( aUid ),
    iStorageFolder( aStorageFolder ),
    iName( aName ),
    iOpen( EFalse ),
    iListener( NULL )
    {
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageBase* CNcdStorageBase::NewL(
    RFs& aFs,
    const TDesC& aUid,
    const TDesC& aStorageFolder,
    const TDesC& aStorageName )
    {
    DLTRACE( ( _L("Path: %S"), &aStorageFolder ) );
    CNcdStorageBase* storage = 
        storage = CNcdDatabaseStorage::NewL( 
            aFs, aUid, aStorageFolder, 
            aStorageName ); 

    return storage;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
const TDesC& CNcdStorageBase::Uid() const
    {
    DASSERT( iUid );
    DLTRACE( ( _L("Uid: %S"), iUid ) );
    
    return *iUid;
    }

// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
const TDesC& CNcdStorageBase::StorageFolder() const
    {
    DASSERT( iStorageFolder );
    return *iStorageFolder;
    }

// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
const TDesC& CNcdStorageBase::Name() const
    {
    DASSERT( iName );
    return *iName;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TInt CNcdStorageBase::Open()
    {
    DLTRACEIN(("this: %x", this));
    if( IsOpen() )
        {
        User::Panic( KNcdStoragePanic, ENcdStoragePanicAlreadyOpen );
        }
    
    TRAPD( err, DoOpenL() );

    if( err == KErrNone )
        {
        iOpen = ETrue;
        }

    return err;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::Close()
    {
    DLTRACEIN(("this: %x", this));
    if( IsOpen() )
        {
        DoClose();
        iOpen = EFalse;
        }

    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TBool CNcdStorageBase::IsOpen() const
    {
    return iOpen;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItem* CNcdStorageBase::StorageItemL( const TDesC& aUid, TInt aType )
    {
    DLTRACEIN( (_L("aUid: %S, aType: %d"), &aUid, aType ) );
    DPROFILING_BEGIN( x );
    CNcdStorageItem* item = FindStorageItem( aUid, aType );

    if ( !item )
        {
        TRAPD( err,
            {
            // Create item
            item = CreateStorageItemLC( aUid, aType );            

            // Store item to array
            iItems.InsertInAddressOrderL( item );
            DLTRACE(("Items: %d", iItems.Count() ));
            CleanupStack::Pop( item );
            });

        if( err == KErrNone )
            {
            iListener->CacheOpened();
            TRAP( err, iListener->CacheReadyL() );
            }

        if( err != KErrNone )
            {
            if( !ItemsOpen() )
                {
                DoRollback();
                }

            User::Leave( err );
            }
        }

    DPROFILING_END( x );
    DLTRACEOUT((""));
    return item;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::StorageItemsL( RPointerArray<MNcdStorageItem>& aItems )
    {
    RPointerArray<CNcdStorageItemIdentifier> items;
    CleanupResetAndDestroyPushL( items );

    // Get storage item identifiers from storage
    GetAllItemsFromStorageL( items );

    // Get storage items
    TInt count = items.Count();
    aItems.ReserveL( aItems.Count() + count );
    
    for( TInt i = 0; i < count; i++ )
        {
        aItems.AppendL( StorageItemL( items[i]->Id(), items[i]->Type() ) );
        }

    CleanupStack::PopAndDestroy( &items );    
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::RemoveItemsL( 
    const RArray<RNcdDatabaseItems>& aDoNotRemoveItems )
    {
    DLTRACEIN((""));
    DoRemoveItemsL( aDoNotRemoveItems );
    
    // reset arrays so that removed items are not left hanging aroung
    iOpenItems.Reset();
    iRemovedItems.Reset();
    iItems.ResetAndDestroy();
    }



// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::OpenItemL( CNcdStorageItem* aItem )
    {
    DLTRACEIN(("this: %x", this));
    iOpenItems.ReserveL( iOpenItems.Count() + 1 );

    DoOpenItemL( aItem );

    // Same item can't be opened multiple times (CNcdStorageItem::OpenL)
    // so we don't have to worry about adding it many times to the open item
    // array. Also we can't run out of memory because we already reserved 
    // memory for the item so we can ignore the error
    iOpenItems.InsertInAddressOrder( aItem );
    
    if( iListener && iOpenItems.Count() == 1 )
        {
        iListener->CacheOpened();
        }
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::SaveItemL( CNcdStorageItem* aItem )
    {
    DLTRACEIN(("this: %x", this));
    TInt index = iOpenItems.FindInAddressOrder( aItem );

    if( index < 0 )
        {
        User::Panic( KNcdStoragePanic, ENcdStoragePanicItemNotOpen );
        }

    iOpenItems.Remove( index );

    if( iListener && iOpenItems.Count() == 0 )
        {
        iListener->CacheReadyL();
        }
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::RollbackItems()
    {
    DLTRACEIN((""));
    Rollback();

    iListener->NotifyRollback();
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TInt CNcdStorageBase::Commit()
    {
    DLTRACEIN((""));
    TInt err = DoCommit();

    if( err == KErrNone )
        {
        TInt count = iRemovedItems.Count();
        TInt index = 0;
        for( TInt i = 0; i < count; i++ )
            {
            index = iItems.FindInAddressOrder( iRemovedItems[i] );
            if( index >= 0 )
                {
                iItems.Remove( index );
                }
            DLTRACE(("Items: %d", iItems.Count() ));
            delete iRemovedItems[i];
            iRemovedItems[i] = NULL;
            }
        }

    iRemovedItems.Reset();    
    return err;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::RemoveItemL( CNcdStorageItem* aItem )
    {
    DLTRACEIN(("this: %x", this));
    TInt insertError( iRemovedItems.InsertInAddressOrder( aItem ) );
    if ( insertError == KErrAlreadyExists )
        {
        DLINFO(("Remove item was already in the array."));
        return;
        }
    User::LeaveIfError( insertError );

    TRAPD( err, DoRemoveItemL( aItem ) );

    if( err != KErrNone )
        {
        TInt index = iRemovedItems.FindInAddressOrder( aItem );
        if( index >= 0 )
            {
            iRemovedItems.Remove( index );
            }
        DLERROR(("Error: %d occurred when removing", err));
        User::Leave( err );
        }
    }

// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::Rollback()
    {
    DoRollback();

    TInt count = iOpenItems.Count();
    for( TInt i = 0; i < count; i++ )
        {
        iOpenItems[i]->SetOpen( EFalse );
        }

    iOpenItems.Reset();
    iRemovedItems.Reset();
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::ReadDataL( CNcdStorageItem* aItem, 
    MNcdStorageDataItem& aDataItem )
    {
    DoReadDataL( aItem, aDataItem );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::WriteDataL( CNcdStorageItem* aItem, 
    MNcdStorageDataItem& aDataItem )
    {
    DoWriteDataL( aItem, aDataItem );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TBool CNcdStorageBase::ItemsOpen() const
    {
    DLTRACEIN(("this: %x, items open: %d", this, iOpenItems.Count() ));
    return ( iOpenItems.Count() > 0 );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
HBufC8* CNcdStorageBase::GetDataL( CNcdStorageItem* aItem )
    {
    return DoGetDataL( aItem );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItem* CNcdStorageBase::FindStorageItem( const TDesC& aUid, 
    TInt aType )
    {
    TInt count = iItems.Count();
    CNcdStorageItem* item = NULL;

    for( TInt i = 0; i < count; i++ )
        {
        item = iItems[i];

        if( item->Type() == aType && 
            item->Uid().Compare( aUid ) == 0 )
            {
            return item;
            }
        }    
        
    return NULL;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageBase::SetListener( CNcdStorageBaseListener* aListener )
    {
    iListener = aListener;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TBool CNcdStorageBase::ItemExistsInStorageL( const TDesC& aUid, TInt aType )
    {
    return ItemExistsL( aUid, aType );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
HBufC8* CNcdStorageBase::GetAllDataLC( RReadStream& aStream )
    {
    MStreamBuf* streamBuf = aStream.Source();
    TInt size = streamBuf->SizeL();

    HBufC8* dataBuffer = HBufC8::NewLC( size );
    TPtr8 data = dataBuffer->Des();

    aStream.ReadL( data, size );

    return dataBuffer;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
HBufC8* CNcdStorageBase::GetAllDataL( RReadStream& aStream )
    {
    HBufC8* dataBuffer = GetAllDataLC( aStream );
    CleanupStack::Pop( dataBuffer );    
    return dataBuffer;
    }



// ********************************
//         CNcdStorageItem
// ********************************


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItem* CNcdStorageItem::NewL( CNcdStorageBase* aStorage, 
    const TDesC& aUid, TInt aType )
    {
    CNcdStorageItem* item = new (ELeave) CNcdStorageItem( aStorage );
    CleanupStack::PushL( item );
    item->ConstructL( aUid, aType );
    CleanupStack::Pop( item );
    return item;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItem::~CNcdStorageItem()
    {
    DLTRACEIN((""));
    delete iIdentifier;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItem::CNcdStorageItem( CNcdStorageBase* aStorage ) :
    iStorage( aStorage ),
    iOpen( EFalse )
    {
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::ConstructL( const TDesC& aUid, TInt aType  )
    {
    DLTRACEIN(("this: %x", this));
    iIdentifier = CNcdStorageItemIdentifier::NewL( aUid, aType );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::SetOpen( TBool aOpen )
    {
    iOpen = aOpen;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TBool CNcdStorageItem::IsOpen() const
    {
    return iOpen;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
const TDesC& CNcdStorageItem::Uid() const
    {
    return iIdentifier->Id();
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TInt CNcdStorageItem::Type() const
    {
    return iIdentifier->Type();
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::OpenL()
    {
    DLTRACEIN(("this: %x", this));
    if( iOpen )
        {
        User::Panic( KNcdStoragePanic, ENcdStoragePanicItemAlreadyOpen );
        }

    iStorage->OpenItemL( this );
    iOpen = ETrue;
    DLTRACEOUT(("Opened %x", this));
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::SaveL()
    {
    DLTRACEIN(("this: %x", this));
    if( !iOpen )
        {
        User::Panic( KNcdStoragePanic, ENcdStoragePanicItemNotOpen );
        }

    TRAPD( err, iStorage->SaveItemL( this ) );
    if( err != KErrNone )
        {
        Rollback();
        User::Leave( err );
        }
    iOpen = EFalse;
    DLTRACEOUT(("closed: %x", this));
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::Rollback()
    {
    DLTRACEIN(("this: %x", this));
    if( iOpen )
        {
        iOpen = EFalse;
        iStorage->RollbackItems();
        }
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::RemoveFromStorageL()
    {
    DLTRACEIN(("this: %x", this));
    if( iOpen )
        {
        User::Panic( KNcdStoragePanic, ENcdStoragePanicItemAlreadyOpen );
        }

    iStorage->RemoveItemL( this );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::SetDataItem( MNcdStorageDataItem* aDataItem )
    {
    iDataItem = aDataItem;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::ReadDataL()
    {
    iStorage->ReadDataL( this, *iDataItem );
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItem::WriteDataL()
    {
    DLTRACEIN(("this: %x", this));
    if( iOpen )
        {
        TRAPD( err, iStorage->WriteDataL( this, *iDataItem ) );
        if ( err != KErrNone ) 
            {
            Rollback();
            User::Leave( err );
            }
        }
    else
        {
        User::Panic( KNcdStoragePanic, ENcdStoragePanicItemNotOpen );
        }
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
HBufC8* CNcdStorageItem::GetDataLC()
    {
    HBufC8* data = iStorage->GetDataL( this );
    CleanupStack::PushL( data );
    return data;
    }


// ********************************
//     CNcdStorageItemIdentifier
// ********************************

// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItemIdentifier* CNcdStorageItemIdentifier::NewLC( 
    const TDesC8& aId, TInt aType )
    {
    CNcdStorageItemIdentifier* identifier = new (ELeave) 
        CNcdStorageItemIdentifier( aType );
    CleanupStack::PushL( identifier );
    identifier->ConstructL( aId );
    return identifier;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItemIdentifier* CNcdStorageItemIdentifier::NewL( 
    const TDesC16& aId, TInt aType )
    {
    CNcdStorageItemIdentifier* identifier = 
        CNcdStorageItemIdentifier::NewLC( aId, aType );
    CleanupStack::Pop( identifier );
    return identifier;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItemIdentifier* CNcdStorageItemIdentifier::NewLC( 
    const TDesC16& aId, TInt aType )
    {
    CNcdStorageItemIdentifier* identifier = new (ELeave) 
        CNcdStorageItemIdentifier( aType );
    CleanupStack::PushL( identifier );
    identifier->ConstructL( aId );
    return identifier;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItemIdentifier::CNcdStorageItemIdentifier( TInt aType ) :
    iType( aType )
    {
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
CNcdStorageItemIdentifier::~CNcdStorageItemIdentifier()
    {
    delete iId;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
const TDesC& CNcdStorageItemIdentifier::Id() const
    {
    return *iId;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TInt CNcdStorageItemIdentifier::Type() const
    {
    return iType;
    }


// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
void CNcdStorageItemIdentifier::ConstructL( const TDesC16& aId )
    {
    iId = aId.AllocL();
    }


void CNcdStorageItemIdentifier::ConstructL( const TDesC8& aId )
    {  
    TInt length = aId.Length();

    if( length % 2 != 0 )
      {
      User::Panic( KNcdStoragePanic, ENcdStoragePanicIdDescAlign );
      }

    iId = HBufC16::NewL( length / 2 );
    iId->Des().Copy( (const TUint16*)aId.Ptr(), length / 2 );
    }