linklayercontrol/networkinterfacemgr/src/EventLogger.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalTechnology
       
    19 */
       
    20 
       
    21 #include "EventLogger.h"
       
    22 #include "SLogger.h"
       
    23 #include "AgentPanic.h"
       
    24 #include <logengdurations.h>
       
    25 
       
    26 EXPORT_C CEventLogger* CEventLogger::NewL()
       
    27 	{
       
    28 	CEventLogger* eventLogger = new(ELeave) CEventLogger;
       
    29 	CleanupStack::PushL(eventLogger);
       
    30 	eventLogger->ConstructL();
       
    31 	CleanupStack::Pop();
       
    32 	return eventLogger;
       
    33 	}
       
    34 
       
    35 CEventLogger::CEventLogger(): CActive(EPriorityIdle)
       
    36 	{
       
    37 	CActiveScheduler::Add(this);
       
    38 	}
       
    39 
       
    40 void CEventLogger::ConstructL()
       
    41 	{
       
    42 	User::LeaveIfError(iFsEventLog.Connect());
       
    43 	iLogWrap = CLogWrapper::NewL(iFsEventLog,CActive::EPriorityStandard);
       
    44 	iCurrentLogEvent = CLogEvent::NewL();
       
    45 	iLogEventQueue = new(ELeave) CArrayPtrFlat<CLogEvent>(KEventStateMaxCount);
       
    46 	}
       
    47 
       
    48 EXPORT_C CEventLogger::~CEventLogger()
       
    49 	{
       
    50 	Cancel();
       
    51 	// the queue could be not empty if the active object is aborted and destructed
       
    52 	while (iLogEventQueue && (iLogEventQueue->Count() > 0))
       
    53 		{
       
    54 		CLogEvent* eventPtr = iLogEventQueue->At(0);
       
    55 		// delete the CLogEvent object
       
    56 		delete eventPtr;
       
    57 		//remove the pointer from the queue
       
    58 		iLogEventQueue->Delete(0);
       
    59 		}
       
    60 	delete iLogWrap;
       
    61 	iLogWrap=NULL;
       
    62 	delete iCurrentLogEvent;
       
    63 	iCurrentLogEvent=NULL;
       
    64 	delete iLogEventQueue;
       
    65 	iLogEventQueue = NULL;
       
    66 	iFsEventLog.Close();
       
    67 	}
       
    68 
       
    69 EXPORT_C void CEventLogger::Cancel()
       
    70 	{
       
    71 	if(iLogWrap)
       
    72 		{
       
    73 		iLogWrap->Log().Cancel();
       
    74 		}
       
    75 	//this method written before CEventLogger moved to a CActive is hiding the access to Cactive version of Cancel()
       
    76 	// The only time cancel should be called is when there is a Panic and we need to destroy the whole object)
       
    77 	CActive::Cancel();
       
    78 	}
       
    79 
       
    80 EXPORT_C void CEventLogger::LogCallStart(const TDesC& aRemote,TInt aLogDir,const TDesC& aTelNum,TUid aDataEventType, TRequestStatus& aStatus)
       
    81 /**
       
    82 DEPRECATED, use LogDataAddEvent instead
       
    83 */
       
    84 	{
       
    85 	LOGSTRING2("GenConn:\tCEventLogger LogCallStart aRemote:%S", &aRemote);
       
    86 	LogDataAddEvent(R_LOG_CON_CONNECTED, aRemote, aLogDir, aTelNum, aDataEventType);
       
    87 	// we could complete the TRequestStatus right now. We go safer way and let istatus complete when logg evnt has been added
       
    88 	LogDataNotifyLastEventUpdate(&aStatus);
       
    89 	}
       
    90 
       
    91 EXPORT_C void CEventLogger::LogCallEnd(TRequestStatus& aStatus)
       
    92 /**
       
    93 DEPRECATED, use  LogDataUpdateEvent instead
       
    94 some code may rely on aStatus being triggered when the logger has completed doing 
       
    95 the last update so that we destroy everything
       
    96 */
       
    97 	{
       
    98 	LOGSTRING("GenConn:\tCEventLogger LogCallEnd");
       
    99 	LogDataUpdateEvent( R_LOG_CON_DISCONNECTED, TUid::Null());
       
   100 	LogDataNotifyLastEventUpdate(&aStatus);	
       
   101 	}
       
   102 
       
   103 EXPORT_C void CEventLogger::LogDataTransferred(TInt64 aBytesSent, TInt64 aBytesReceived,TUid aDataEventType, TRequestStatus& aStatus)
       
   104 /**
       
   105 DEPRECATED, use  LogDataUpdateEvent instead
       
   106 */
       
   107 	{
       
   108 	LogDataUpdateEvent(KConnectionStatusIdNotAvailable , aDataEventType, aBytesSent, aBytesReceived);
       
   109 	// we complete the aStatus right now even if the log might be updated later
       
   110 	TRequestStatus* st = &aStatus;
       
   111 	User::RequestComplete(st, KErrNone);
       
   112 	}
       
   113 EXPORT_C void CEventLogger::LogDataAddEvent(TInt aRConnectionStatusId, const TDesC& aRemote, TInt aLogDir, const TDesC& aTelNum, TUid aDataEventType)
       
   114 	{
       
   115 	LOGSTRING2("GenConn:\tCEventLogger LogDataAddEvent aRConnectionStatusId:%d", aRConnectionStatusId);
       
   116 	//It is possible to add a new logevent with a new log id for the same connection (reconnect case)
       
   117 	// assuming that all the next updates will be for the new event and not the old one.
       
   118 
       
   119 	// [NeilMa 140403]: This method cannot leave and has no return value, but 
       
   120 	// performs memory allocations if the event cannot be logged immediately. 
       
   121 	// Therefore, if the memory alloc fails for any reason, the event is 
       
   122 	// currently discarded with no record. This method should be replaced by 
       
   123 	// one which can Leave or returns an error code. See Typhoon DEF022946.
       
   124 	TTime time;
       
   125 	time.UniversalTime();
       
   126 
       
   127 	if (!IsActive() && (iLogEventQueue->Count() ==0))
       
   128 		{
       
   129 	    iCurrentLogEvent->SetId(KGenconnLogWaitingForLogId);
       
   130 		iCurrentLogEvent->SetTime(time);
       
   131 		TBuf<KLogMaxStatusLength > logStatusBuf;
       
   132 		iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok
       
   133 		iCurrentLogEvent->SetStatus(logStatusBuf);
       
   134 		iCurrentLogEvent->SetRemoteParty(aRemote);
       
   135 		TBuf<KLogMaxDirectionLength> logDirBuf;
       
   136 		iLogWrap->Log().GetString(logDirBuf, aLogDir); // Ignore error - string blank on error which is ok
       
   137 		iCurrentLogEvent->SetDirection(logDirBuf);
       
   138 		iCurrentLogEvent->SetNumber(aTelNum);
       
   139 		iCurrentLogEvent->SetEventType(aDataEventType);
       
   140 		iCurrentLogEvent->SetDurationType(KLogDurationValid);
       
   141 		iStatus=KRequestPending;
       
   142 		iLogWrap->Log().AddEvent(*iCurrentLogEvent, iStatus);
       
   143 		SetActive();
       
   144 		}
       
   145 	else
       
   146 		{
       
   147 		// add the request to the queue, it will be processed asap
       
   148 		CLogEvent* eventUpdate = 0;
       
   149 		TRAPD(error, eventUpdate = CLogEvent::NewL());
       
   150 		if (KErrNone != error)
       
   151 			{
       
   152 			return; // event is discarded!
       
   153 			}
       
   154 	    eventUpdate->SetId(KGenconnLogWaitingForLogId);
       
   155 		eventUpdate->SetTime(time);
       
   156 		TBuf<KLogMaxStatusLength > logStatusBuf;
       
   157 		iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok
       
   158 		eventUpdate->SetStatus(logStatusBuf);
       
   159 		eventUpdate->SetRemoteParty(aRemote);
       
   160 		TBuf<KLogMaxDirectionLength> logDirBuf;
       
   161 		iLogWrap->Log().GetString(logDirBuf, aLogDir); // Ignore error - string blank on error which is ok
       
   162 		eventUpdate->SetDirection(logDirBuf);
       
   163 		eventUpdate->SetNumber(aTelNum);
       
   164 		eventUpdate->SetEventType(aDataEventType);
       
   165 		eventUpdate->SetDurationType(KLogDurationValid);
       
   166 		// add to the queue
       
   167 		TRAP(error, iLogEventQueue->AppendL(eventUpdate));
       
   168 		if (KErrNone != error)
       
   169 			{
       
   170 			delete eventUpdate; // event is discarded!
       
   171 			return;
       
   172 			}
       
   173 		}
       
   174 	}
       
   175 
       
   176 TInt CEventLogger::UpdateLogEventParam(CLogEvent& aLogEvent, TInt aRConnectionStatusId, const TUid& aDataEventType, const TInt64& aBytesSent, const TInt64& aBytesReceived)
       
   177 	{
       
   178 	
       
   179 	TTime time;
       
   180 	TInt ret =KErrNone;
       
   181 	time.UniversalTime();
       
   182 	TTimeIntervalSeconds interval(0);
       
   183 	if (time.SecondsFrom(iCurrentLogEvent->Time(),interval) != KErrNone)
       
   184 		{
       
   185 		interval = 0;	// no duration available ->error
       
   186 		}
       
   187 	if (KConnectionStatusIdNotAvailable != aRConnectionStatusId)
       
   188 		{
       
   189 		//status needs to be updated
       
   190 		TBuf<KLogMaxStatusLength > logStatusBuf;
       
   191 		iLogWrap->Log().GetString(logStatusBuf, aRConnectionStatusId); // Ignore error - string blank on error which is ok
       
   192 		aLogEvent.SetStatus(logStatusBuf);
       
   193 		}
       
   194 	if ( aDataEventType != TUid::Null())
       
   195 		{
       
   196 		aLogEvent.SetEventType(aDataEventType);
       
   197 		}
       
   198 	aLogEvent.SetDuration(interval.Int());		//0 or not
       
   199 	//check if data metrics need to be updated
       
   200 	TInt64 byteInfoNotAvailable(KBytesInfoNotAvailable);
       
   201 	if ((aBytesReceived != byteInfoNotAvailable) && (aBytesSent != byteInfoNotAvailable))
       
   202 		{
       
   203 		TBuf8<KDatabufferSize> dataBuffer;
       
   204 		dataBuffer.Num(aBytesSent);
       
   205 		dataBuffer.Append(TChar(','));
       
   206 		dataBuffer.AppendNum(aBytesReceived);
       
   207 		TRAP(ret, aLogEvent.SetDataL(dataBuffer));
       
   208 		}
       
   209 	return ret;
       
   210 	}
       
   211 EXPORT_C TInt CEventLogger::LogDataUpdateEvent(TInt aRConnectionStatusId, const TUid& aDataEventType)
       
   212 	{
       
   213 	return LogDataUpdateEvent(aRConnectionStatusId, aDataEventType, KBytesInfoNotAvailable, KBytesInfoNotAvailable);
       
   214 	}
       
   215 
       
   216 EXPORT_C TInt CEventLogger::LogDataUpdateEvent(TInt aRConnectionStatusId, const TUid& aDataEventType, const TInt64& aBytesSent, const TInt64& aBytesReceived)
       
   217 	{
       
   218 	LOGSTRING("GenConn:\tCEventLogger LogDataUpdateEvent");
       
   219 	TInt ret = KErrNone;
       
   220 	// check if there is a request ongoing on the current event
       
   221 	// check if no request pending then start it otherwise wait until the previous request is finished and keep going on.
       
   222 	//PROBLEM HERE: 
       
   223 	// if LogDataAddEvent has not been called then iCurrentLogEvent->Id() == KLogNullId we do nothing, we should assert
       
   224 	// if id is not ready yet, iCurrentLogEvent->Id() is equal to KGenconnLogWaitingForLogId and the active object is active.
       
   225 	// 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.
       
   226 	if (iCurrentLogEvent->Id() != KLogNullId)
       
   227 		{
       
   228 		if (!IsActive() && (iLogEventQueue->Count() ==0))
       
   229 			{
       
   230 			// request update straight on
       
   231 			UpdateLogEventParam(*iCurrentLogEvent, aRConnectionStatusId, aDataEventType, aBytesSent, aBytesReceived);
       
   232 			iLogWrap->Log().ChangeEvent(*iCurrentLogEvent, iStatus);
       
   233 			SetActive();
       
   234 			}
       
   235 		else
       
   236 			{
       
   237 			// add the request to the queue, it will be processed asap
       
   238 			CLogEvent* eventUpdate = 0;
       
   239 			TRAP(ret, eventUpdate = CLogEvent::NewL());
       
   240 			if(KErrNone != ret)
       
   241 				{
       
   242 				return ret;
       
   243 				}
       
   244 			TRAP(ret, eventUpdate->CopyL(*iCurrentLogEvent));
       
   245 			if(KErrNone != ret)
       
   246 				{
       
   247 				delete eventUpdate;
       
   248 				return ret;
       
   249 				}
       
   250 
       
   251 			ret = UpdateLogEventParam(*eventUpdate, aRConnectionStatusId, aDataEventType, aBytesSent, aBytesReceived);
       
   252 			if(KErrNone != ret)
       
   253 				{
       
   254 				delete eventUpdate;
       
   255 				return ret;
       
   256 				}
       
   257 
       
   258 			// add to the queue
       
   259 			TRAP(ret, iLogEventQueue->AppendL(eventUpdate));
       
   260 			if(KErrNone != ret)
       
   261 				{
       
   262 				delete eventUpdate;
       
   263 				return ret;
       
   264 				}
       
   265 			}
       
   266 		}
       
   267 	return ret;
       
   268 	}
       
   269 
       
   270 EXPORT_C void CEventLogger::LogDataNotifyLastEventUpdate(TRequestStatus* aStatus)
       
   271 	{
       
   272 	//only 1 listener for the notification supported
       
   273 	__ASSERT_DEBUG((iNotificationRequestStatus == NULL), AgentPanic(Agent::EEventLoggerMoreThanOneListenerForNotifyLastUpdate));
       
   274 	iNotificationRequestStatus = aStatus;
       
   275 	if (!IsActive() && (iLogEventQueue->Count() ==0))
       
   276 		{
       
   277 		//already finished processing all the log event updates in the queue
       
   278 		// we can complete straight on
       
   279 		User::RequestComplete(iNotificationRequestStatus, KErrNone);
       
   280 		iNotificationRequestStatus = NULL;	// did the job, so do need the pointer anymore.
       
   281 		}
       
   282 	}
       
   283 
       
   284 void CEventLogger::RunL()
       
   285 	{
       
   286 	// request has completed
       
   287 	// delete completed event and check if there is a next event pending
       
   288 	// If LogEng is not supported, a dummy logeng just returns error straight on.
       
   289 	// but we carry on doing all the requests
       
   290 	if (iLogEventQueue->Count() >0)
       
   291 		{
       
   292 		CLogEvent* nextEventPtr = iLogEventQueue->At(0);
       
   293 		__ASSERT_DEBUG((nextEventPtr != NULL), AgentPanic(Agent::ENullCLogEventPointerPresentInLogEventQueue));
       
   294 		if (nextEventPtr->Id() == KGenconnLogWaitingForLogId)
       
   295 			{
       
   296 			//Id was not available when the update has been entered because addEvent did not return at that time
       
   297 			nextEventPtr->SetId(iCurrentLogEvent->Id());
       
   298 			}
       
   299 		iCurrentLogEvent->CopyL(*nextEventPtr);
       
   300 		iLogWrap->Log().ChangeEvent(*iCurrentLogEvent, iStatus);
       
   301 		SetActive();
       
   302 		// delete the ongoing CLogEvent we just copied to currentLogEvent
       
   303 		delete nextEventPtr;
       
   304 		//remove the pointer from the queue
       
   305 		iLogEventQueue->Delete(0);
       
   306 		}
       
   307 	else if (iNotificationRequestStatus!=NULL)
       
   308 		{
       
   309 		// We have finished processing all the log event updates in the queue
       
   310 		User::RequestComplete(iNotificationRequestStatus, KErrNone);
       
   311 		iNotificationRequestStatus = NULL;	// did the job, so do need the pointer anymore.
       
   312 		}
       
   313 	}
       
   314 
       
   315 void CEventLogger::DoCancel()
       
   316 	{
       
   317 	if(iLogWrap)
       
   318 		{
       
   319 		iLogWrap->Log().Cancel();
       
   320 		}
       
   321 	// 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
       
   322 	// if we cancel the logger, most likely the whole Logger Object will be destroyed
       
   323 }
       
   324