--- /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 <logengdurations.h>
+
+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<CLogEvent>(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<KLogMaxStatusLength > logStatusBuf;
+ iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok
+ iCurrentLogEvent->SetStatus(logStatusBuf);
+ iCurrentLogEvent->SetRemoteParty(aRemote);
+ TBuf<KLogMaxDirectionLength> 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<KLogMaxStatusLength > logStatusBuf;
+ iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok
+ eventUpdate->SetStatus(logStatusBuf);
+ eventUpdate->SetRemoteParty(aRemote);
+ TBuf<KLogMaxDirectionLength> 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<KLogMaxStatusLength > 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<KDatabufferSize> 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
+}
+