sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include "LogViewWindowFetcher.h"
sl@0: 
sl@0: // System includes
sl@0: #include <s32mem.h>
sl@0: 
sl@0: // User includes
sl@0: #include "logservcli.h"
sl@0: 
sl@0: // Constants
sl@0: const TInt KLogSizeOfEventGuess = 200;
sl@0: const TInt KLogWindowFetchBufferGranularity = KLogSizeOfEventGuess * 2;
sl@0: const TInt KLogWindowFetchBufferMinimumBufferSize = 4;
sl@0: 
sl@0: 
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: // -----> CLogViewWindowFetcher (source)
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: CLogViewWindowFetcher::CLogViewWindowFetcher(RLogSession& aSession, TLogViewId aViewId, MLogViewWindowFetcherObserver& aObserver, TInt aPriority)
sl@0: :	CActive(aPriority), iSession(aSession), iViewId(aViewId), iObserver(aObserver), iBufferPointer(NULL, 0)
sl@0: 	{
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	iData().iOperationType = ELogOperationViewWindowFetch;
sl@0: 	}
sl@0: 
sl@0: CLogViewWindowFetcher::~CLogViewWindowFetcher()
sl@0: 	{
sl@0: 	Cancel();
sl@0: 	//
sl@0: 	delete iBuffer;
sl@0: 	}
sl@0: 
sl@0: void CLogViewWindowFetcher::ConstructL()
sl@0: 	{
sl@0: 	iBuffer = CBufFlat::NewL(KLogWindowFetchBufferGranularity);
sl@0: 	}
sl@0: 
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: void CLogViewWindowFetcher::PrepareToFetchWindowL(const TLogWindowAndCursor& aRequestedWindow)
sl@0: 	{
sl@0: 	iRequestedWindow = aRequestedWindow;
sl@0: 	iRequestedWindow.iValid = EFalse;
sl@0: 	iWindowReq = iRequestedWindow; // Initialise window
sl@0: 	// Setup the buffer so that its the right size to receive the events
sl@0: 	const TInt range = Max(1, iRequestedWindow.iUpper - iRequestedWindow.iLower + 1);
sl@0: 	const TInt size = KLogSizeOfEventGuess * range;
sl@0: 	iBuffer->ResizeL(size);
sl@0: 	iBufferPointer.Set(iBuffer->Ptr(0));
sl@0: 	//
sl@0: 	iFetchWindowData().iBufferSize = size;
sl@0: 	}
sl@0: 
sl@0: void CLogViewWindowFetcher::Start(TRequestStatus& aObserver)
sl@0: 	{
sl@0: 	iObserverRequestStatus = &aObserver;
sl@0: 	*iObserverRequestStatus = KRequestPending;
sl@0: 	if	(iRequestedWindow.Range())
sl@0: 		Fetch(iRequestedWindow);
sl@0: 	else
sl@0: 		{
sl@0: 		// Nothing to fetch
sl@0: 		iRequestedWindow.NormalizeWindowAndCursor();
sl@0: 		User::RequestComplete(iObserverRequestStatus, KErrNone);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void CLogViewWindowFetcher::SilentCancel()
sl@0: 	{
sl@0: 	if	(iObserverRequestStatus)
sl@0: 		User::RequestComplete(iObserverRequestStatus, KErrNone);
sl@0: 	Cancel();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: void CLogViewWindowFetcher::RunL()
sl@0: 	{
sl@0: 	const TInt sentByServer = iStatus.Int();
sl@0: 	User::LeaveIfError(sentByServer);
sl@0: 	//The server has completed the operation without any error, but there is no returned data
sl@0: 	//(sentByServer == 0). Then the client has to check if iFetchWindowData().iServerDataSize
sl@0: 	//data member is set, which means that the server wants to send more data than the client
sl@0: 	//side buffer can accept. The client has to increase the buffer size and then execute 
sl@0: 	//the operation again.
sl@0: 	TInt newSize = iFetchWindowData().iServerDataSize;
sl@0: 	//newSize was initialized, so iFetchWindowData().iServerDataSize can be set to 0.
sl@0: 	iFetchWindowData().iServerDataSize = 0;
sl@0: 	if(sentByServer == 0 && newSize > 0)
sl@0: 		{
sl@0: 		iBuffer->ResizeL(newSize);
sl@0: 		iBufferPointer.Set(iBuffer->Ptr(0));
sl@0: 		iFetchWindowData().iBufferSize = newSize;
sl@0: 		//The operation will be executed again later - see "Fetch(iWindowReq)" call.
sl@0: 		}
sl@0: 	RBufReadStream stream(*iBuffer);
sl@0: 	for(TInt i=0; i<sentByServer; i++)
sl@0: 		{
sl@0: 		// Give the event to the observer
sl@0: 		CLogEvent* event = CLogEvent::NewL();
sl@0: 		CleanupStack::PushL(event);
sl@0: 		//
sl@0: 		stream >> *event;
sl@0: 		iObserver.HandleFetchedWindowItemL(i, event);
sl@0: 		CleanupStack::Pop(event);
sl@0: 		}
sl@0: 
sl@0: 	// Do we need to fetch the next batch?
sl@0: 	iWindowReq.iLower += sentByServer; // the lower array index for next request
sl@0: 
sl@0: 	if(iWindowReq.iLower <= iWindowReq.iUpper)
sl@0: 		{
sl@0: 		// Fetch some more
sl@0: 		Fetch(iWindowReq);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		// All done?
sl@0: 		iBuffer->ResizeL(KLogWindowFetchBufferMinimumBufferSize);
sl@0: 		iRequestedWindow.iValid = ETrue;
sl@0: 		CompleteObserver(KErrNone);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void CLogViewWindowFetcher::DoCancel()
sl@0: 	{
sl@0: 	if	(iData().iOperationId > 0)
sl@0: 		{
sl@0: 		const TInt errorIgnored = iSession.Send(ELogOperationCancel, TIpcArgs(&iData));
sl@0: 		(void) errorIgnored;
sl@0: 		//
sl@0: 		iData().iOperationId = KLogNullOperationId;
sl@0: 		}
sl@0: 
sl@0: 	CompleteObserver(KErrCancel);
sl@0: 	}
sl@0: 
sl@0: TInt CLogViewWindowFetcher::RunError(TInt aError)
sl@0: 	{
sl@0: 	CompleteObserver(aError);
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: 
sl@0: void CLogViewWindowFetcher::Fetch(const TLogWindow& aWindow)
sl@0: 	{
sl@0: 	iFetchWindowData().iLower = aWindow.iLower;
sl@0: 	iFetchWindowData().iUpper = aWindow.iUpper;
sl@0: 	//
sl@0: 	iData().iOperationId = iSession.AllocateIdOperation();
sl@0: 	//
sl@0: 	iSession.Send(ELogViewOperationInitiate, TIpcArgs(&iData,iViewId,&iFetchWindowData,&iBufferPointer), iStatus);
sl@0: 	SetActive();
sl@0: 	}
sl@0: 
sl@0: void CLogViewWindowFetcher::CompleteObserver(TInt aError)
sl@0: 	{
sl@0: 	if	(iObserverRequestStatus)
sl@0: 		User::RequestComplete(iObserverRequestStatus, aError);
sl@0: 	}