diff -r 000000000000 -r e686773b3f54 phonebookengines/VirtualPhonebook/VPbkSimStoreImpl/src/CMultipleReadCmd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/VirtualPhonebook/VPbkSimStoreImpl/src/CMultipleReadCmd.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,454 @@ +/* +* Copyright (c) 2002-2007 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: A class that can read multiple contacts from ETel store +* Uses ETel RMobilePhoneBookStore Read +* +*/ + + + +// INCLUDE FILES +#include "CMultipleReadCmd.h" + +#include "CVPbkETelCntConverter.h" +#include "CVPbkSimContactBuf.h" +#include "CVPbkSimCntField.h" +#include "VPbkSimStoreImplError.h" +#include "CBasicStore.h" +#include "CContactArray.h" +#include "VPbkDebug.h" + +namespace VPbkSimStoreImpl { + +// CONSTANTS + +// Define some default size of one contact for buffer creation +const TInt KDefaultSizeForOneContact = 256; +// Define a maximum size for the read buffer. 20 contacts at one request is +// a pretty good base for maximum. +const TInt KMaxSizeForBuffer = 20 * KDefaultSizeForOneContact; + +// ============================= LOCAL FUNCTIONS =============================== + +namespace { +// ----------------------------------------------------------------------------- +// Return the number of indexes +// ----------------------------------------------------------------------------- +// +inline TInt AmountOfIndexes( TInt aLastIndex, TInt aFirstIndex ) + { + return aLastIndex - aFirstIndex + 1; + } +} // unnamed namespace + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::CMultipleReadCmd +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMultipleReadCmd::CMultipleReadCmd( CBasicStore& aBasicStore, + TInt aFirstIndexToRead, TInt aLastIndexToRead ) + : CActive( EPriorityStandard ), + iBasicStore( aBasicStore ), + iFirstIndexToRead( aFirstIndexToRead ), + iLastIndexToRead( aLastIndexToRead ), + iIndexToRead( KVPbkSimStoreInvalidETelIndex ), + iBufferPtr( 0, NULL ) + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::CMultipleReadCmd +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CMultipleReadCmd::CMultipleReadCmd( CBasicStore& aBasicStore, + TInt& aIndexToRead ) + : CActive( EPriorityStandard ), + iBasicStore( aBasicStore ), + iFirstIndexToRead( KVPbkSimStoreInvalidETelIndex ), + iLastIndexToRead( KVPbkSimStoreInvalidETelIndex ), + iIndexToRead( aIndexToRead ), + iBufferPtr( 0, NULL ) + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::ConstructL() + { + iCntConverter = CVPbkETelCntConverter::NewL(); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMultipleReadCmd* CMultipleReadCmd::NewLC( CBasicStore& aBasicStore ) + { + CMultipleReadCmd* self = new( ELeave ) CMultipleReadCmd( aBasicStore, + KVPbkSimStoreFirstETelIndex, KVPbkSimStoreInvalidETelIndex ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMultipleReadCmd* CMultipleReadCmd::NewLC( CBasicStore& aBasicStore, + TInt aFirstIndexToRead, TInt aLastIndexToRead ) + { + CMultipleReadCmd* self = new( ELeave ) CMultipleReadCmd( aBasicStore, + aFirstIndexToRead, aLastIndexToRead ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMultipleReadCmd* CMultipleReadCmd::NewLC( CBasicStore& aBasicStore, + TInt& aIndexToRead ) + { + CMultipleReadCmd* self = new( ELeave ) CMultipleReadCmd( aBasicStore, + aIndexToRead ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// Destructor +CMultipleReadCmd::~CMultipleReadCmd() + { + CancelCmd(); + delete iCntConverter; + delete iBuffer; + iCntArray.ResetAndDestroy(); + iCntArray.Close(); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::Execute +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::Execute() + { + __ASSERT_DEBUG( iObserver, + VPbkSimStoreImpl::Panic( EPreCondCMultipleReadCmdExecute ) ); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING( + "VPbkSimStoreImpl: CMultipleReadCmd::Execute Request") ); + + if ( iIndexToRead != KVPbkSimStoreInvalidETelIndex ) + { + iFirstIndexToRead = iIndexToRead; + iLastIndexToRead = iIndexToRead; + } + else if ( iLastIndexToRead == KVPbkSimStoreInvalidETelIndex ) + { + iLastIndexToRead = iBasicStore.ETelStoreInfo().iTotalEntries; + } + + // Define the size of the buffer. ETel iTotalEntries can not be trusted. + TInt amountOfIndexes = + AmountOfIndexes( iLastIndexToRead, iFirstIndexToRead ); + if ( amountOfIndexes > 0 ) + { + // Create a buffer according to amount of possible contacts to read. + // There must be a limit for the size. + TInt size = Min( KMaxSizeForBuffer, + amountOfIndexes * KDefaultSizeForOneContact ); + TRAPD( result, iBuffer = HBufC8::NewL( size ) ); + if ( result != KErrNone ) + { + DoDummyRequest( result ); + } + else + { + iBufferPtr.Set( iBuffer->Des() ); + DoRequest(); + } + } + else + { + // There was probably a problem with ETel iTotalEntries. + // Behave same as iTotalEntries would be zero. Completing with + // KErrNotFound from ETel means that there were no contacts + // in given index range. + DoDummyRequest( KErrNotFound ); + } + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::AddObserverL +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::AddObserverL( MVPbkSimCommandObserver& aObserver ) + { + __ASSERT_DEBUG( !iObserver, + VPbkSimStoreImpl::Panic( EPreCondCMultipleReadCmdAddObserverL ) ); + iObserver = &aObserver; + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::CancelCmd +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::CancelCmd() + { + CActive::Cancel(); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::RunL +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::RunL() + { + TInt result = iStatus.Int(); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING( + "VPbkSimStoreImpl: RMobilePhoneBooStore::Read h%d complete %d"), + iBasicStore.ETelStore().SubSessionHandle(), result); + + switch ( result ) + { + case KErrNone: + { + // Convert from ETel to own contacts + ConvertContactsL(); + // Check that was the buffer big enough + if ( WasBufferBigEnough() ) + { + // Contacts were found -> update contact array + UpdateContactArrayL(); + } + // Buffer wasn't big enough -> Check that it's not growing + // for ever. + else if ( !IsBufferSizeInSane() ) + { + // Make buffer bigger and read again + EnlargeBufferL(); + } + else + { + // Stop trying -> there is something wrong in ETel + result = KErrOverflow; + } + + // Stop if error + if ( result != KErrNone ) + { + iObserver->CommandError( *this, result ); + } + // If all the indexes have been read and we are done. + else if ( AmountOfIndexes( + iLastIndexToRead, iFirstIndexToRead ) <= 0 ) + { + iObserver->CommandDone( *this ); + } + // There are still contacts to read + else + { + DoRequest(); + } + break; + } + case KErrNotFound: + { + // If nothing found update the array and complete command. + iBasicStore.Contacts().Delete( iFirstIndexToRead, iLastIndexToRead ); + iObserver->CommandDone( *this ); + break; + } + default: + { + iObserver->CommandError( *this, result ); + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::DoCancel +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::DoCancel() + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING( + "VPbkSimStoreImpl: RMobilePhoneBooStore::Read h%d Cancel"), + iBasicStore.ETelStore().SubSessionHandle()); + iBasicStore.ETelStore().CancelAsyncRequest( EMobilePhoneStoreRead ); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::RunError +// ----------------------------------------------------------------------------- +// +TInt CMultipleReadCmd::RunError( TInt aError ) + { + iObserver->CommandError( *this, aError ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::DoDummyRequest +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::DoDummyRequest( TInt aResult ) + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING( + "VPbkSimStoreImpl: CMultipleReadCmd dummy request")); + TRequestStatus* status = &iStatus; + User::RequestComplete( status, aResult ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::DoRequest +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::DoRequest() + { + ResetBuffer(); + + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING( + "VPbkSimStoreImpl: RMobilePhoneBooStore::Read h%d request\ + firstslot=%d,lastslot=%d"), + iBasicStore.ETelStore().SubSessionHandle(), + iFirstIndexToRead, iLastIndexToRead); + + iBasicStore.ETelStore().Read( iStatus, iFirstIndexToRead, + AmountOfIndexes( iLastIndexToRead, iFirstIndexToRead ), iBufferPtr ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::IsBufferSizeInSane +// ----------------------------------------------------------------------------- +// +TBool CMultipleReadCmd::IsBufferSizeInSane() + { + __ASSERT_DEBUG( iBuffer, + Panic( EPreCond_CMultipleReadCmd_IsBufferSizeInSane ) ); + + if ( iBuffer->Size() >= KMaxSizeForBuffer ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::EnlargeBufferL +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::EnlargeBufferL() + { + __ASSERT_DEBUG( iBuffer, + Panic( EPreCond_CMultipleReadCmd_EnlargeBufferL ) ); + + const TInt doubleFactor = 2; + TInt newSize = iBufferPtr.MaxSize() * doubleFactor; + + HBufC8* buffer = HBufC8::NewL( newSize ); + delete iBuffer; + iBuffer = buffer; + iBufferPtr.Set( iBuffer->Des() ); + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::ConvertContactsL +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::ConvertContactsL() + { + // Make sure that there are no old contacts + iCntArray.ResetAndDestroy(); + + if ( iBufferPtr.Length() > 0 ) + { + iCntConverter->ConvertFromETelToVPbkSimContactsL( + iCntArray, iBufferPtr, iBasicStore ); + } + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::WasBufferBigEnough +// ----------------------------------------------------------------------------- +// +TBool CMultipleReadCmd::WasBufferBigEnough() + { + // ConvertContactsL must be called before this. The logic is that if + // ETel retuned KErrNone from Read request but there are not contacts + // in iBuffer then the buffer was too small. + return iCntArray.Count() > 0; + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::UpdateContactArrayL +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::UpdateContactArrayL() + { + VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING( + "VPbkSimStoreImpl: CMultipleReadCmd::UpdateContactArrayL ")); + + __ASSERT_DEBUG( iCntArray.Count() > 0, Panic( EReadingFromETelFailed ) ); + + // Get amount of contacts + TInt cntCount = iCntArray.Count(); + for ( TInt i = cntCount - 1; i >= 0; --i ) + { + // Check the biggest sim index that was read + TInt simIndex = iCntArray[i]->SimIndex(); + if ( simIndex >= iFirstIndexToRead ) + { + // iFirstIndexToRead must be the first sim index that was not read. + iFirstIndexToRead = simIndex + 1; + } + + // Add contacts to contact array. Ownership changes. + iBasicStore.Contacts().AddOrReplaceL( iCntArray[i] ); + iCntArray.Remove( i ); + } + } + +// ----------------------------------------------------------------------------- +// CMultipleReadCmd::ResetBuffer +// ----------------------------------------------------------------------------- +// +void CMultipleReadCmd::ResetBuffer() + { + iBufferPtr.FillZ( iBufferPtr.MaxLength() ); + iBufferPtr.Zero(); + } +} // namespace VPbkSimStoreImpl +// End of File