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 "LogViewObserver.h"
sl@0: 
sl@0: // System includes
sl@0: #include <s32mem.h>
sl@0: 
sl@0: // User includes
sl@0: #include <logwrap.h>
sl@0: #include <logcli.h>
sl@0: #include "logclipanic.h"
sl@0: #include "logservcli.h"
sl@0: #include "LogChangeDefinition.h"
sl@0: #include "LogViewChangeObserverInternal.h"
sl@0: 
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: // -----> CLogViewObserver (source)
sl@0: /////////////////////////////////////////////////////////////////////////////////////////
sl@0: CLogViewObserver::CLogViewObserver(CLogView& aView, CLogClient& aClient, MLogViewChangeObserverInternal& aObserver, TLogViewId aViewId, TInt aPriority)
sl@0: :	CActive(aPriority), iClient(aClient), iObserver(aObserver), iViewId(aViewId), iView(aView)
sl@0: 	{
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	}
sl@0: 
sl@0: CLogViewObserver::~CLogViewObserver()
sl@0: 	{
sl@0: 	Cancel();
sl@0: 	//
sl@0: 	delete iChanges;
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::ConstructL()
sl@0: 	{
sl@0: 	iChanges = CLogChangeDefinition::NewL();
sl@0: 	RequestChanges();
sl@0: 	}
sl@0: 
sl@0: CLogViewObserver* CLogViewObserver::NewL(CLogView& aView, CLogClient& aClient, MLogViewChangeObserverInternal& aObserver, TLogViewId aViewId, TInt aPriority)
sl@0: 	{
sl@0: 	CLogViewObserver* self = new(ELeave) CLogViewObserver(aView, aClient, aObserver, aViewId, aPriority);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::RequestChanges()
sl@0: 	{
sl@0: 	iClient.Session().Send(ELogViewChangeNotificationsRequest, TIpcArgs(iViewId), iStatus);
sl@0: 	SetActive();
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::RunL()
sl@0: 	{
sl@0: 	const TInt error = iStatus.Int();
sl@0: 	if (error == KErrServerTerminated)
sl@0: 		{
sl@0: 		// Effectively does a "delete this"
sl@0: 		iView.NotifyLogServerTerminatedL();
sl@0: 		}
sl@0: 	else if (error < KErrNone)
sl@0: 		{
sl@0: 		// Don't request any further changes.
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		const TInt changesSize = iStatus.Int();
sl@0: 		User::LeaveIfError(changesSize);
sl@0: 		FetchChangesL(changesSize);
sl@0: 		RequestChanges();
sl@0: 		NotifyObserverL();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: TInt CLogViewObserver::RunError(TInt /*aError*/)
sl@0: 	{
sl@0: 	
sl@0: 	// This point can be reached when RequestChanges has already been 
sl@0: 	// called, for example when an observer leaves when it is notified of 
sl@0: 	// a change.
sl@0: 	// Check IsActive() before calling RequestChanges to avoid calling it 
sl@0: 	// twice in a row and causing a E32USER-CBase:42 panic.
sl@0:  
sl@0: 	if (!IsActive())
sl@0: 		{
sl@0: 		RequestChanges();	
sl@0: 		}
sl@0:  	 
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::DoCancel()
sl@0: 	{
sl@0: 	RequestChangesCancel();
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::RequestChangesCancel()
sl@0: 	{
sl@0: 	iClient.Session().Send(ELogViewChangeNotificationsCancel, TIpcArgs(iViewId));
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::FetchChangesL(TInt aBufferSizeRequired)
sl@0: 	{
sl@0: 	HBufC8* buffer = HBufC8::NewLC(aBufferSizeRequired);
sl@0: 	TPtr8 pBuffer(buffer->Des());
sl@0: 	//
sl@0: 	User::LeaveIfError(iClient.Session().Send(ELogViewFetchChanges, TIpcArgs(iViewId,aBufferSizeRequired,&pBuffer)));
sl@0: 	//
sl@0: 	iChanges->Reset();
sl@0: 	RDesReadStream stream(*buffer);
sl@0: 	stream >> *iChanges;
sl@0: 	CleanupStack::PopAndDestroy(buffer);
sl@0: 	}
sl@0: 
sl@0: void CLogViewObserver::NotifyObserverL()
sl@0: 	{
sl@0: 	TLogId id;
sl@0: 	TInt viewIndex;
sl@0: 
sl@0: 	// Copy the changes
sl@0: 	const TInt count = iChanges->Count();
sl@0: 	if	(!count)
sl@0: 		return;
sl@0: 	//
sl@0: 	CLogChangeDefinition* changes = CLogChangeDefinition::NewL(*iChanges);
sl@0: 	CleanupStack::PushL(changes);
sl@0: 	iChanges->Reset();
sl@0: 	//
sl@0: 	for(TInt i=0; i<count; i++)
sl@0: 		{
sl@0: 		const TLogDatabaseChangeType type = changes->At(i, id, viewIndex);
sl@0: 		//
sl@0: 		switch(type)
sl@0: 			{
sl@0: 		case ELogChangeTypeEventAdded:
sl@0: 			iObserver.HandleLogViewChangeEventAddedL(id, viewIndex, i, count);
sl@0: 			break;
sl@0: 		case ELogChangeTypeEventChanged:
sl@0: 			iObserver.HandleLogViewChangeEventChangedL(id, viewIndex, i, count);
sl@0: 			break;
sl@0: 		case ELogChangeTypeEventDeleted:
sl@0: 			iObserver.HandleLogViewChangeEventDeletedL(id, viewIndex, i, count);
sl@0: 			break;
sl@0: 		case ELogChangeTypeLogCleared:
sl@0: 			iObserver.HandleLogViewChangeEventLogClearedL();
sl@0: 			break;
sl@0: 		default:
sl@0: 		case ELogChangeTypeUndefined:
sl@0: 			__ASSERT_DEBUG(EFalse, Panic(ELogUnexpectedChangeType));
sl@0: 			}
sl@0: 		}
sl@0: 	CleanupStack::PopAndDestroy(changes);
sl@0: 	}