/*
* 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: Message store search handler client implementation.
*
*/
#include "msgstoresearchhandler.h"
//<cmail>
#include "msgstoretypes.h"
#include "msgstoremailbox.h"
//</cmail>
#include "rmessagestoresession.h"
const TInt KInitialPropertiesTransferBufferLength = 10000;
// ----------------------
// CMsgStoreSearchHandler
// ----------------------
// ==========================================================================
// FUNCTION: NewL
// ==========================================================================
CMsgStoreSearchHandler* CMsgStoreSearchHandler::NewL( RMessageStoreSession& aSession,
RMsgStoreSearchCriteria& aSearchCriteria,
MMsgStoreSearchClient& aSearchClient )
{
CMsgStoreSearchHandler* self = new(ELeave) CMsgStoreSearchHandler( aSession, aSearchCriteria, aSearchClient );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
} // end NewL
// ==========================================================================
// FUNCTION: Constructor
// ==========================================================================
CMsgStoreSearchHandler::CMsgStoreSearchHandler( RMessageStoreSession& aSession,
RMsgStoreSearchCriteria& aSearchCriteria,
MMsgStoreSearchClient& aSearchClient ) :
CActive( EPriorityStandard ),
iSession( aSession ),
iSearchCriteria( aSearchCriteria ),
iSearchClient( aSearchClient )
{
__LOG_CONSTRUCT( "MsgClient", "CMsgStoreSearchHandler" )
CActiveScheduler::Add(this);
} // end constructor
// ==========================================================================
// FUNCTION: ConstructL
// ==========================================================================
void CMsgStoreSearchHandler::ConstructL()
{
iMatchBuffer[0].CreateL( KInitialPropertiesTransferBufferLength );
iMatchBuffer[1].CreateL( KInitialPropertiesTransferBufferLength );
iSession.PrepareSearchL( iSearchCriteria );
iSession.GetMatchesL( iStatus, iMatchBuffer[iMatchBufferIndex] );
SetActive();
} // end ConstructL
// ==========================================================================
// FUNCTION: Destructor
// ==========================================================================
CMsgStoreSearchHandler::~CMsgStoreSearchHandler()
{
Cancel();
iMatchBuffer[0].Close();
iMatchBuffer[1].Close();
if( iThisObjectHasBeenDeleted )
{
*iThisObjectHasBeenDeleted = ETrue;
} // end if
__LOG_DESTRUCT
} // end destructor
// ==========================================================================
// FUNCTION: CancelSearch
// ==========================================================================
void CMsgStoreSearchHandler::CancelSearch()
{
__LOG_ENTER( "CancelSearch" )
iSession.CancelSearch();
Cancel();
__LOG_EXIT
}
// ==========================================================================
// FUNCTION: RunL
// ==========================================================================
void CMsgStoreSearchHandler::RunL()
{
__LOG_ENTER( "RunL" )
RBuf8& currentMatchBuffer = iMatchBuffer[iMatchBufferIndex];
if( iStatus == KErrNone && currentMatchBuffer.Length() > 0 )
{
// Switch to the other match buffer for the next call to the session. Make this call before
// calling the search client with matches, just in case the client cancels the search during
// the callback. This will cause DoCancel to be called during this object's destruction, which
// will cancel the server-side search.
iMatchBufferIndex = (iMatchBufferIndex + 1) % 2;
iSession.GetMatchesL( iStatus, iMatchBuffer[iMatchBufferIndex] );
SetActive();
// Client's may cancel the search during callbacks. This flag mechanism is used to detect that case,
// and avoid using any heap variables that may no longer be valid.
TBool thisObjectHasBeenDeleted = EFalse;
iThisObjectHasBeenDeleted = &thisObjectHasBeenDeleted;
TBool atEndOfIds = (currentMatchBuffer.Length() == 0);
TUint offset = 0;
while( !thisObjectHasBeenDeleted && !atEndOfIds )
{
const TMsgStoreId& msgId = *reinterpret_cast<const TMsgStoreId *>( currentMatchBuffer.Ptr() + offset );
offset += sizeof(TMsgStoreId);
const TMsgStoreId& folderId = *reinterpret_cast<const TMsgStoreId *>( currentMatchBuffer.Ptr() + offset );
offset += sizeof(TMsgStoreId);
const TUint length = *reinterpret_cast<const TUint *>( currentMatchBuffer.Ptr() + offset );
offset += sizeof(TUint);
TPtrC8 propertyBuf( KNullDesC8 );
if ( length > 0 )
{
propertyBuf.Set( currentMatchBuffer.Ptr() + offset, length );
offset += length;
}
__LOG_WRITE8_FORMAT1_INFO( "match found (%i)", msgId )
if( offset >= currentMatchBuffer.Length() )
{
atEndOfIds = ETrue;
} // end if
// Note that the client may cancel the search during this callback.
CMsgStorePropertyContainer* matchMessage = CMsgStorePropertyContainer::NewL();
CleanupStack::PushL( matchMessage );
matchMessage->SetIds( msgId, folderId );
matchMessage->DeserializeL( propertyBuf );
CleanupStack::Pop( matchMessage );
iSearchClient.MatchFound( matchMessage );
//need to delete the message, the observer should take ownership of this pointer
//and set the original to NULL
delete matchMessage;
} // end while
if( !thisObjectHasBeenDeleted )
{
iThisObjectHasBeenDeleted = NULL;
} // end if
}
else
{
__LOG_WRITE8_FORMAT1_INFO( "Search completed, iStatus=%d", iStatus.Int() );
iSearchClient.SearchCompleted();
} // end if
// __LOG_EXIT was removed because it crashes in cases where thisObjectHasBeenDeleted is true
} // end RunL
// ==========================================================================
// FUNCTION: RunError
// ==========================================================================
TInt CMsgStoreSearchHandler::RunError( TInt __LOG_BLOCK(aError) )
{
__LOG_ENTER_SUPPRESS( "RunError" )
__LOG_WRITE8_FORMAT1_ERROR( "aError=%i", aError )
// Something unexpected failed. Notify the client that search is complete.
iSearchClient.SearchCompleted();
return KErrNone;
} // end RunError
// ==========================================================================
// FUNCTION: DoCancel
// ==========================================================================
void CMsgStoreSearchHandler::DoCancel()
{
//do not call iSession.CancelSearch() here because these object are deleted
//later than the time searches are canceled. If we call it here
//iSession.CancelSearch() will be sent to server again which may have side effects.
} // end