|
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 |