diff -r 000000000000 -r af10295192d8 linklayercontrol/networkinterfacemgr/src/EventLogger.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linklayercontrol/networkinterfacemgr/src/EventLogger.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,324 @@ +// Copyright (c) 1997-2009 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: +// + +/** + @file + @internalTechnology +*/ + +#include "EventLogger.h" +#include "SLogger.h" +#include "AgentPanic.h" +#include + +EXPORT_C CEventLogger* CEventLogger::NewL() + { + CEventLogger* eventLogger = new(ELeave) CEventLogger; + CleanupStack::PushL(eventLogger); + eventLogger->ConstructL(); + CleanupStack::Pop(); + return eventLogger; + } + +CEventLogger::CEventLogger(): CActive(EPriorityIdle) + { + CActiveScheduler::Add(this); + } + +void CEventLogger::ConstructL() + { + User::LeaveIfError(iFsEventLog.Connect()); + iLogWrap = CLogWrapper::NewL(iFsEventLog,CActive::EPriorityStandard); + iCurrentLogEvent = CLogEvent::NewL(); + iLogEventQueue = new(ELeave) CArrayPtrFlat(KEventStateMaxCount); + } + +EXPORT_C CEventLogger::~CEventLogger() + { + Cancel(); + // the queue could be not empty if the active object is aborted and destructed + while (iLogEventQueue && (iLogEventQueue->Count() > 0)) + { + CLogEvent* eventPtr = iLogEventQueue->At(0); + // delete the CLogEvent object + delete eventPtr; + //remove the pointer from the queue + iLogEventQueue->Delete(0); + } + delete iLogWrap; + iLogWrap=NULL; + delete iCurrentLogEvent; + iCurrentLogEvent=NULL; + delete iLogEventQueue; + iLogEventQueue = NULL; + iFsEventLog.Close(); + } + +EXPORT_C void CEventLogger::Cancel() + { + if(iLogWrap) + { + iLogWrap->Log().Cancel(); + } + //this method written before CEventLogger moved to a CActive is hiding the access to Cactive version of Cancel() + // The only time cancel should be called is when there is a Panic and we need to destroy the whole object) + CActive::Cancel(); + } + +EXPORT_C void CEventLogger::LogCallStart(const TDesC& aRemote,TInt aLogDir,const TDesC& aTelNum,TUid aDataEventType, TRequestStatus& aStatus) +/** +DEPRECATED, use LogDataAddEvent instead +*/ + { + LOGSTRING2("GenConn:\tCEventLogger LogCallStart aRemote:%S", &aRemote); + LogDataAddEvent(R_LOG_CON_CONNECTED, aRemote, aLogDir, aTelNum, aDataEventType); + // we could complete the TRequestStatus right now. We go safer way and let istatus complete when logg evnt has been added + LogDataNotifyLastEventUpdate(&aStatus); + } + +EXPORT_C void CEventLogger::LogCallEnd(TRequestStatus& aStatus) +/** +DEPRECATED, use LogDataUpdateEvent instead +some code may rely on aStatus being triggered when the logger has completed doing +the last update so that we destroy everything +*/ + { + LOGSTRING("GenConn:\tCEventLogger LogCallEnd"); + LogDataUpdateEvent( R_LOG_CON_DISCONNECTED, TUid::Null()); + LogDataNotifyLastEventUpdate(&aStatus); + } + +EXPORT_C void CEventLogger::LogDataTransferred(TInt64 aBytesSent, TInt64 aBytesReceived,TUid aDataEventType, TRequestStatus& aStatus) +/** +DEPRECATED, use LogDataUpdateEvent instead +*/ + { + LogDataUpdateEvent(KConnectionStatusIdNotAvailable , aDataEventType, aBytesSent, aBytesReceived); + // we complete the aStatus right now even if the log might be updated later + TRequestStatus* st = &aStatus; + User::RequestComplete(st, KErrNone); + } +EXPORT_C void CEventLogger::LogDataAddEvent(TInt aRConnectionStatusId, const TDesC& aRemote, TInt aLogDir, const TDesC& aTelNum, TUid aDataEventType) + { + LOGSTRING2("GenConn:\tCEventLogger LogDataAddEvent aRConnectionStatusId:%d", aRConnectionStatusId); + //It is possible to add a new logevent with a new log id for the same connection (reconnect case) + // assuming that all the next updates will be for the new event and not the old one. + + // [NeilMa 140403]: This method cannot leave and has no return value, but + // performs memory allocations if the event cannot be logged immediately. + // Therefore, if the memory alloc fails for any reason, the event is + // currently discarded with no record. This method should be replaced by + // one which can Leave or returns an error code. See Typhoon DEF022946. + TTime time; + time.UniversalTime(); + + if (!IsActive() && (iLogEventQueue->Count() ==0)) + { + iCurrentLogEvent->SetId(KGenconnLogWaitingForLogId); + iCurrentLogEvent->SetTime(time); + TBuf logStatusBuf; + iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok + iCurrentLogEvent->SetStatus(logStatusBuf); + iCurrentLogEvent->SetRemoteParty(aRemote); + TBuf logDirBuf; + iLogWrap->Log().GetString(logDirBuf, aLogDir); // Ignore error - string blank on error which is ok + iCurrentLogEvent->SetDirection(logDirBuf); + iCurrentLogEvent->SetNumber(aTelNum); + iCurrentLogEvent->SetEventType(aDataEventType); + iCurrentLogEvent->SetDurationType(KLogDurationValid); + iStatus=KRequestPending; + iLogWrap->Log().AddEvent(*iCurrentLogEvent, iStatus); + SetActive(); + } + else + { + // add the request to the queue, it will be processed asap + CLogEvent* eventUpdate = 0; + TRAPD(error, eventUpdate = CLogEvent::NewL()); + if (KErrNone != error) + { + return; // event is discarded! + } + eventUpdate->SetId(KGenconnLogWaitingForLogId); + eventUpdate->SetTime(time); + TBuf logStatusBuf; + iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok + eventUpdate->SetStatus(logStatusBuf); + eventUpdate->SetRemoteParty(aRemote); + TBuf logDirBuf; + iLogWrap->Log().GetString(logDirBuf, aLogDir); // Ignore error - string blank on error which is ok + eventUpdate->SetDirection(logDirBuf); + eventUpdate->SetNumber(aTelNum); + eventUpdate->SetEventType(aDataEventType); + eventUpdate->SetDurationType(KLogDurationValid); + // add to the queue + TRAP(error, iLogEventQueue->AppendL(eventUpdate)); + if (KErrNone != error) + { + delete eventUpdate; // event is discarded! + return; + } + } + } + +TInt CEventLogger::UpdateLogEventParam(CLogEvent& aLogEvent, TInt aRConnectionStatusId, const TUid& aDataEventType, const TInt64& aBytesSent, const TInt64& aBytesReceived) + { + + TTime time; + TInt ret =KErrNone; + time.UniversalTime(); + TTimeIntervalSeconds interval(0); + if (time.SecondsFrom(iCurrentLogEvent->Time(),interval) != KErrNone) + { + interval = 0; // no duration available ->error + } + if (KConnectionStatusIdNotAvailable != aRConnectionStatusId) + { + //status needs to be updated + TBuf logStatusBuf; + iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok + aLogEvent.SetStatus(logStatusBuf); + } + if ( aDataEventType != TUid::Null()) + { + aLogEvent.SetEventType(aDataEventType); + } + aLogEvent.SetDuration(interval.Int()); //0 or not + //check if data metrics need to be updated + TInt64 byteInfoNotAvailable(KBytesInfoNotAvailable); + if ((aBytesReceived != byteInfoNotAvailable) && (aBytesSent != byteInfoNotAvailable)) + { + TBuf8 dataBuffer; + dataBuffer.Num(aBytesSent); + dataBuffer.Append(TChar(',')); + dataBuffer.AppendNum(aBytesReceived); + TRAP(ret, aLogEvent.SetDataL(dataBuffer)); + } + return ret; + } +EXPORT_C TInt CEventLogger::LogDataUpdateEvent(TInt aRConnectionStatusId, const TUid& aDataEventType) + { + return LogDataUpdateEvent(aRConnectionStatusId, aDataEventType, KBytesInfoNotAvailable, KBytesInfoNotAvailable); + } + +EXPORT_C TInt CEventLogger::LogDataUpdateEvent(TInt aRConnectionStatusId, const TUid& aDataEventType, const TInt64& aBytesSent, const TInt64& aBytesReceived) + { + LOGSTRING("GenConn:\tCEventLogger LogDataUpdateEvent"); + TInt ret = KErrNone; + // check if there is a request ongoing on the current event + // check if no request pending then start it otherwise wait until the previous request is finished and keep going on. + //PROBLEM HERE: + // if LogDataAddEvent has not been called then iCurrentLogEvent->Id() == KLogNullId we do nothing, we should assert + // if id is not ready yet, iCurrentLogEvent->Id() is equal to KGenconnLogWaitingForLogId and the active object is active. + // So it is put as a request and it will be updated when the event is ready to be processed otherwise if we don't log at all, we should do nothing. + if (iCurrentLogEvent->Id() != KLogNullId) + { + if (!IsActive() && (iLogEventQueue->Count() ==0)) + { + // request update straight on + UpdateLogEventParam(*iCurrentLogEvent, aRConnectionStatusId, aDataEventType, aBytesSent, aBytesReceived); + iLogWrap->Log().ChangeEvent(*iCurrentLogEvent, iStatus); + SetActive(); + } + else + { + // add the request to the queue, it will be processed asap + CLogEvent* eventUpdate = 0; + TRAP(ret, eventUpdate = CLogEvent::NewL()); + if(KErrNone != ret) + { + return ret; + } + TRAP(ret, eventUpdate->CopyL(*iCurrentLogEvent)); + if(KErrNone != ret) + { + delete eventUpdate; + return ret; + } + + ret = UpdateLogEventParam(*eventUpdate, aRConnectionStatusId, aDataEventType, aBytesSent, aBytesReceived); + if(KErrNone != ret) + { + delete eventUpdate; + return ret; + } + + // add to the queue + TRAP(ret, iLogEventQueue->AppendL(eventUpdate)); + if(KErrNone != ret) + { + delete eventUpdate; + return ret; + } + } + } + return ret; + } + +EXPORT_C void CEventLogger::LogDataNotifyLastEventUpdate(TRequestStatus* aStatus) + { + //only 1 listener for the notification supported + __ASSERT_DEBUG((iNotificationRequestStatus == NULL), AgentPanic(Agent::EEventLoggerMoreThanOneListenerForNotifyLastUpdate)); + iNotificationRequestStatus = aStatus; + if (!IsActive() && (iLogEventQueue->Count() ==0)) + { + //already finished processing all the log event updates in the queue + // we can complete straight on + User::RequestComplete(iNotificationRequestStatus, KErrNone); + iNotificationRequestStatus = NULL; // did the job, so do need the pointer anymore. + } + } + +void CEventLogger::RunL() + { + // request has completed + // delete completed event and check if there is a next event pending + // If LogEng is not supported, a dummy logeng just returns error straight on. + // but we carry on doing all the requests + if (iLogEventQueue->Count() >0) + { + CLogEvent* nextEventPtr = iLogEventQueue->At(0); + __ASSERT_DEBUG((nextEventPtr != NULL), AgentPanic(Agent::ENullCLogEventPointerPresentInLogEventQueue)); + if (nextEventPtr->Id() == KGenconnLogWaitingForLogId) + { + //Id was not available when the update has been entered because addEvent did not return at that time + nextEventPtr->SetId(iCurrentLogEvent->Id()); + } + iCurrentLogEvent->CopyL(*nextEventPtr); + iLogWrap->Log().ChangeEvent(*iCurrentLogEvent, iStatus); + SetActive(); + // delete the ongoing CLogEvent we just copied to currentLogEvent + delete nextEventPtr; + //remove the pointer from the queue + iLogEventQueue->Delete(0); + } + else if (iNotificationRequestStatus!=NULL) + { + // We have finished processing all the log event updates in the queue + User::RequestComplete(iNotificationRequestStatus, KErrNone); + iNotificationRequestStatus = NULL; // did the job, so do need the pointer anymore. + } + } + +void CEventLogger::DoCancel() + { + if(iLogWrap) + { + iLogWrap->Log().Cancel(); + } + // usually you do not need to cancel an update on events, just let them go and be removed from the queue when update is done + // if we cancel the logger, most likely the whole Logger Object will be destroyed +} +