|
1 // CloggerClient.cpp |
|
2 // |
|
3 // Copyright (c) 2006 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include "clogger.h" |
|
14 #include "cliserv.h" |
|
15 #include "SensibleClient_Internals.h" |
|
16 #include "common.h" |
|
17 #include <badesca.h> |
|
18 #include <s32mem.h> |
|
19 #include <e32property.h> |
|
20 |
|
21 #define KFlagsMask 0x0FFFFFFF |
|
22 #define KTestTagEnabled 0x10000000 |
|
23 #define KNoLogMask 0x80000000 // This is the log mask used internally if you call an overload which doesn't specify one |
|
24 |
|
25 #define iBody (*reinterpret_cast<RCloggerBody*>(&iPimpl)) |
|
26 |
|
27 #ifndef PERFORMANCE_CRITICAL |
|
28 |
|
29 // declares RClogger* clogger |
|
30 #define CheckConnected() \ |
|
31 RClogger _cloggerHandle; \ |
|
32 RClogger* clogger = &_cloggerHandle; \ |
|
33 GetTls(clogger, ETrue); \ |
|
34 if (!clogger) return |
|
35 |
|
36 #define GetTlsOrConnect(aTag) \ |
|
37 RClogger _cloggerHandle; \ |
|
38 RClogger* clogger = &_cloggerHandle; \ |
|
39 TInt err; \ |
|
40 TBool isHandle = GetTls(clogger, ETrue, &aTag, &err) |
|
41 |
|
42 #define GetTlsOrNull() \ |
|
43 RClogger _cloggerHandle; \ |
|
44 RClogger* clogger = &_cloggerHandle; \ |
|
45 TBool isHandle = GetTls(clogger, EFalse) |
|
46 |
|
47 TBool RClogger::GetTls(RClogger*& aClogger, TBool aAutoConnect, const TDesC* aTag, TInt* aError) |
|
48 { |
|
49 TAny* tls = Dll::Tls(); |
|
50 if ((TUint)tls & 1) |
|
51 { |
|
52 // Then it's a handle |
|
53 aClogger->SetHandle((TInt)((TUint)tls >> 1)); |
|
54 return ETrue; |
|
55 } |
|
56 else if (tls) |
|
57 { |
|
58 // Then it's a pointer |
|
59 aClogger = (RClogger*)tls; |
|
60 return EFalse; |
|
61 } |
|
62 else if (aAutoConnect) |
|
63 { |
|
64 TInt err = aClogger->Connect(aTag ? *aTag : KNullDesC); |
|
65 aClogger->iFlags &= ~EUseHeapBuffer; // Don't (by default) use a buffer for static connections because we can't track it without upgrading TLS |
|
66 if (err) |
|
67 { |
|
68 if (aError) *aError = err; |
|
69 aClogger = NULL; |
|
70 return ETrue; |
|
71 } |
|
72 __ASSERT_DEBUG((aClogger->Handle() & 0x80000000) == 0, User::Panic(_L("HandleTooBig"), 0)); |
|
73 |
|
74 err = Dll::SetTls((TAny*) ((aClogger->Handle() << 1) | 1)); |
|
75 if (err) |
|
76 { |
|
77 aClogger->Close(); |
|
78 if (aError) *aError = err; |
|
79 aClogger = NULL; |
|
80 } |
|
81 return ETrue; |
|
82 } |
|
83 else |
|
84 { |
|
85 aClogger = NULL; |
|
86 return ETrue; |
|
87 } |
|
88 } |
|
89 |
|
90 #endif // PERFORMANCE_CRITICAL |
|
91 |
|
92 NONSHARABLE_CLASS(RCloggerBody) : public RSensibleSessionBody |
|
93 { |
|
94 public: |
|
95 RCloggerBody(RClogger& aSession); |
|
96 TInt DoCreateSession(const TDesC &aServer, const TVersion &aVersion, TInt aAsyncMessageSlots); |
|
97 TInt DoSendReceive(TInt aFunction, const TIpcArgs &aArgs) const; |
|
98 void DoSendReceive(TInt aFunction, const TIpcArgs &aArgs, TRequestStatus& aStatus) const; |
|
99 void ServerDiedL(); |
|
100 void DispatchCallbackL(TServerCallback& aCallback, TCallbackParser& aParser); |
|
101 |
|
102 private: |
|
103 friend class RClogger; |
|
104 //RClogger& iSession; // No need to store this, we can calculate it from our this pointer since we know we are always embedded in an RClogger |
|
105 }; |
|
106 |
|
107 #define iSession (*(RClogger*)((TUint8*)this - _FOFF(RClogger, iPimpl))) |
|
108 |
|
109 RCloggerBody::RCloggerBody(RClogger& /*aSession*/) |
|
110 : RSensibleSessionBody() //, iSession(aSession) |
|
111 {} |
|
112 |
|
113 TInt RCloggerBody::DoCreateSession(const TDesC &aServer, const TVersion &aVersion, TInt aAsyncMessageSlots) |
|
114 { |
|
115 return iSession.CreateSession(aServer, aVersion, aAsyncMessageSlots); |
|
116 } |
|
117 |
|
118 TInt RCloggerBody::DoSendReceive(TInt aFunction, const TIpcArgs &aArgs) const |
|
119 { |
|
120 return iSession.SendReceive(aFunction, aArgs); |
|
121 } |
|
122 |
|
123 void RCloggerBody::DoSendReceive(TInt aFunction, const TIpcArgs &aArgs, TRequestStatus& aStatus) const |
|
124 { |
|
125 iSession.SendReceive(aFunction, aArgs, aStatus); |
|
126 } |
|
127 |
|
128 EXPORT_C RClogger::RClogger() |
|
129 : iFlags(0), iEnabled(EAllEnabled), iBuf(), iSequence(0) |
|
130 { |
|
131 __ASSERT_COMPILE(sizeof(iPimpl) >= sizeof(RCloggerBody)); |
|
132 __ASSERT_COMPILE(sizeof(RClogger) == 10*4); // This is the size we've published, it CANNOT change |
|
133 |
|
134 // Initialise the body using placement new |
|
135 new(iPimpl) RCloggerBody(*this); |
|
136 } |
|
137 |
|
138 EXPORT_C RClogger::RClogger(TAny* aTls) |
|
139 : iFlags(0), iEnabled(EAllEnabled), iBuf(), iSequence(0) |
|
140 { |
|
141 // This overload is only ever supposed to be used by the TlsLog inline functions, hence why it's private but still |
|
142 // exported. |
|
143 new(iPimpl) RCloggerBody(*this); |
|
144 SetHandle(reinterpret_cast<TInt>(aTls)); |
|
145 } |
|
146 |
|
147 EXPORT_C TInt RClogger::Connect() |
|
148 { |
|
149 return Connect(KNullDesC); |
|
150 } |
|
151 |
|
152 EXPORT_C TInt RClogger::Connect(const TDesC& aTag) |
|
153 { |
|
154 iFlags |= EUseHeapBuffer; // Set by default |
|
155 |
|
156 TInt err = iBody.Connect(1, EFalse); // Only need 1 slot as we only have one async function (which is hidden within RSensibleSession) |
|
157 if (!err) |
|
158 { |
|
159 err = ShareAuto(); |
|
160 } |
|
161 if (!err) |
|
162 { |
|
163 TPckg<TUint32> enabledPkg(iEnabled); |
|
164 TInt res = SendReceive(ESetTag, TIpcArgs(&aTag, NULL, &enabledPkg)); |
|
165 if (res >= 0) |
|
166 { |
|
167 iSequence = res; |
|
168 } |
|
169 else |
|
170 { |
|
171 err = res; |
|
172 } |
|
173 } |
|
174 if (err) |
|
175 { |
|
176 Close(); |
|
177 } |
|
178 return err; |
|
179 } |
|
180 |
|
181 EXPORT_C TInt RClogger::StaticConnect() |
|
182 { |
|
183 return StaticConnect(KNullDesC); |
|
184 } |
|
185 |
|
186 #ifndef PERFORMANCE_CRITICAL |
|
187 |
|
188 EXPORT_C TInt RClogger::StaticConnect(const TDesC& aTag) |
|
189 { |
|
190 GetTlsOrConnect(aTag); |
|
191 if (clogger) return KErrNone; |
|
192 else return err; |
|
193 } |
|
194 |
|
195 EXPORT_C void RClogger::StaticClose() |
|
196 { |
|
197 GetTlsOrNull(); |
|
198 if (clogger) |
|
199 { |
|
200 clogger->Close(); |
|
201 if (!isHandle) |
|
202 { |
|
203 delete clogger; |
|
204 } |
|
205 Dll::SetTls(NULL); |
|
206 Dll::FreeTls(); |
|
207 } |
|
208 } |
|
209 |
|
210 #endif // PERFORMANCE_CRITICAL |
|
211 |
|
212 |
|
213 EXPORT_C void RClogger::Log(TRefByValue<const TDesC> aFmt, ...) |
|
214 { |
|
215 VA_LIST args; |
|
216 VA_START(args, aFmt); |
|
217 LogList(KNoLogMask, aFmt, args); |
|
218 VA_END(args); |
|
219 } |
|
220 |
|
221 EXPORT_C void RClogger::Log(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, ...) |
|
222 { |
|
223 VA_LIST args; |
|
224 VA_START(args, aFmt); |
|
225 LogList(aLogMask, aFmt, args); |
|
226 VA_END(args); |
|
227 } |
|
228 |
|
229 EXPORT_C void RClogger::Log(TRefByValue<const TDesC8> aFmt, ...) |
|
230 { |
|
231 VA_LIST args; |
|
232 VA_START(args, aFmt); |
|
233 LogList(KNoLogMask, aFmt, args); |
|
234 VA_END(args); |
|
235 } |
|
236 |
|
237 EXPORT_C void RClogger::Log(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, ...) |
|
238 { |
|
239 VA_LIST args; |
|
240 VA_START(args, aFmt); |
|
241 LogList(aLogMask, aFmt, args); |
|
242 VA_END(args); |
|
243 } |
|
244 |
|
245 EXPORT_C void RClogger::Log(const char* aFmt, ...) |
|
246 { |
|
247 VA_LIST args; |
|
248 VA_START(args, aFmt); |
|
249 LogList(KNoLogMask, aFmt, args); |
|
250 VA_END(args); |
|
251 } |
|
252 |
|
253 EXPORT_C void RClogger::Log(TUint32 aLogMask, const char* aFmt, ...) |
|
254 { |
|
255 VA_LIST args; |
|
256 VA_START(args, aFmt); |
|
257 LogList(aLogMask, aFmt, args); |
|
258 VA_END(args); |
|
259 } |
|
260 |
|
261 EXPORT_C void RClogger::LogList(TRefByValue<const TDesC> aFmt, VA_LIST aList) |
|
262 { |
|
263 LogList(KNoLogMask, aFmt, aList); |
|
264 } |
|
265 |
|
266 EXPORT_C void RClogger::LogList(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, VA_LIST aList) |
|
267 { |
|
268 if (!Enabled(aLogMask)) return; |
|
269 TUint32 tickCount = User::NTickCount(); |
|
270 |
|
271 TPtrC fmt(aFmt); |
|
272 if (iFlags & ETrimTrailingNewlines) |
|
273 { |
|
274 TInt len = fmt.Length(); |
|
275 if (len && fmt[len-1] == '\n') fmt.Set(fmt.Left(len-1)); |
|
276 len = fmt.Length(); |
|
277 if (len && fmt[len-1] == '\r') fmt.Set(fmt.Left(len-1)); |
|
278 } |
|
279 #define SF_FORMAT fmt |
|
280 #define SF_LIST aList |
|
281 #define SF_BUF iBuf |
|
282 #define SF_ACTION(buf) SendReceive(ELog8, TIpcArgs(&buf, tickCount, aLogMask)) |
|
283 #define SF_WIDE |
|
284 #define SF_STACKONLY (!(iFlags & EUseHeapBuffer)) |
|
285 #include "SensibleFormat.h" |
|
286 |
|
287 //if (!(iFlags&ECacheClientBuffers)) iBuf.Close(); |
|
288 } |
|
289 |
|
290 EXPORT_C void RClogger::LogList(TRefByValue<const TDesC8> aFmt, VA_LIST aList) |
|
291 { |
|
292 LogList(KNoLogMask, aFmt, aList); |
|
293 } |
|
294 |
|
295 EXPORT_C void RClogger::LogList(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, VA_LIST aList) |
|
296 { |
|
297 if (!Enabled(aLogMask)) return; |
|
298 TUint32 tickCount = User::NTickCount(); |
|
299 |
|
300 TPtrC8 fmt(aFmt); |
|
301 if (iFlags & ETrimTrailingNewlines) |
|
302 { |
|
303 TInt len = fmt.Length(); |
|
304 if (len && fmt[len-1] == '\n') fmt.Set(fmt.Left(len-1)); |
|
305 len = fmt.Length(); |
|
306 if (len && fmt[len-1] == '\r') fmt.Set(fmt.Left(len-1)); |
|
307 } |
|
308 #define SF_FORMAT fmt |
|
309 #define SF_LIST aList |
|
310 #define SF_BUF iBuf |
|
311 #define SF_ACTION(buf) SendReceive(ELog8, TIpcArgs(&buf, tickCount, aLogMask)) |
|
312 #define SF_STACKONLY (!(iFlags & EUseHeapBuffer)) |
|
313 #include "SensibleFormat.h" |
|
314 |
|
315 //if (!(iFlags&ECacheClientBuffers)) iBuf.Close(); |
|
316 } |
|
317 |
|
318 EXPORT_C void RClogger::LogList(const char* aFmt, VA_LIST aList) |
|
319 { |
|
320 TPtrC8 ptr((const TUint8*)aFmt); |
|
321 LogList(KNoLogMask, ptr, aList); |
|
322 } |
|
323 |
|
324 EXPORT_C void RClogger::LogList(TUint32 aLogMask, const char* aFmt, VA_LIST aList) |
|
325 { |
|
326 TPtrC8 ptr((const TUint8*)aFmt); |
|
327 LogList(aLogMask, ptr, aList); |
|
328 } |
|
329 |
|
330 #ifndef PERFORMANCE_CRITICAL |
|
331 |
|
332 EXPORT_C void RClogger::Slog(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, ...) |
|
333 { |
|
334 CheckConnected(); |
|
335 VA_LIST args; |
|
336 VA_START(args, aFmt); |
|
337 clogger->LogList(aLogMask, aFmt, args); |
|
338 VA_END(args); |
|
339 } |
|
340 |
|
341 EXPORT_C void RClogger::Slog(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, ...) |
|
342 { |
|
343 CheckConnected(); |
|
344 VA_LIST args; |
|
345 VA_START(args, aFmt); |
|
346 clogger->LogList(aLogMask, aFmt, args); |
|
347 VA_END(args); |
|
348 } |
|
349 |
|
350 EXPORT_C void RClogger::Slog(TUint32 aLogMask, const char* aFmt, ...) |
|
351 { |
|
352 CheckConnected(); |
|
353 VA_LIST args; |
|
354 VA_START(args, aFmt); |
|
355 clogger->LogList(aLogMask, aFmt, args); |
|
356 VA_END(args); |
|
357 } |
|
358 |
|
359 EXPORT_C void RClogger::Slog(TRefByValue<const TDesC> aFmt, ...) |
|
360 { |
|
361 CheckConnected(); |
|
362 VA_LIST args; |
|
363 VA_START(args, aFmt); |
|
364 clogger->LogList(KNoLogMask, aFmt, args); |
|
365 VA_END(args); |
|
366 } |
|
367 |
|
368 EXPORT_C void RClogger::Slog(TRefByValue<const TDesC8> aFmt, ...) |
|
369 { |
|
370 CheckConnected(); |
|
371 VA_LIST args; |
|
372 VA_START(args, aFmt); |
|
373 clogger->LogList(KNoLogMask, aFmt, args); |
|
374 VA_END(args); |
|
375 } |
|
376 |
|
377 EXPORT_C void RClogger::Slog(const char* aFmt, ...) |
|
378 { |
|
379 CheckConnected(); |
|
380 VA_LIST args; |
|
381 VA_START(args, aFmt); |
|
382 clogger->LogList(KNoLogMask, aFmt, args); |
|
383 VA_END(args); |
|
384 } |
|
385 |
|
386 EXPORT_C void RClogger::SlogList(TUint32 aLogMask, TRefByValue<const TDesC> aFmt, VA_LIST aList) |
|
387 { |
|
388 CheckConnected(); |
|
389 clogger->LogList(aLogMask, aFmt, aList); |
|
390 } |
|
391 |
|
392 EXPORT_C void RClogger::SlogList(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, VA_LIST aList) |
|
393 { |
|
394 CheckConnected(); |
|
395 clogger->LogList(aLogMask, aFmt, aList); |
|
396 } |
|
397 |
|
398 EXPORT_C void RClogger::SlogList(TUint32 aLogMask, const char* aFmt, VA_LIST aList) |
|
399 { |
|
400 CheckConnected(); |
|
401 clogger->LogList(aLogMask, aFmt, aList); |
|
402 } |
|
403 |
|
404 EXPORT_C void RClogger::SlogList(TRefByValue<const TDesC> aFmt, VA_LIST aList) |
|
405 { |
|
406 CheckConnected(); |
|
407 clogger->LogList(KNoLogMask, aFmt, aList); |
|
408 } |
|
409 |
|
410 EXPORT_C void RClogger::SlogList(TRefByValue<const TDesC8> aFmt, VA_LIST aList) |
|
411 { |
|
412 CheckConnected(); |
|
413 clogger->LogList(KNoLogMask, aFmt, aList); |
|
414 } |
|
415 |
|
416 EXPORT_C void RClogger::SlogList(const char* aFmt, VA_LIST aList) |
|
417 { |
|
418 CheckConnected(); |
|
419 clogger->LogList(KNoLogMask, aFmt, aList); |
|
420 } |
|
421 |
|
422 EXPORT_C void RClogger::SetStaticLogBehaviour(TUint aLogBehaviour) |
|
423 { |
|
424 GetTlsOrConnect(KNullDesC); |
|
425 if (isHandle && (aLogBehaviour != 0)) |
|
426 { |
|
427 // Then we need to upgrade from handle to pointer |
|
428 TInt err = KErrNoMemory; |
|
429 RClogger* ptr = new RClogger(); |
|
430 if (ptr) |
|
431 { |
|
432 ptr->SetHandle(clogger->Handle()); |
|
433 err = Dll::SetTls(ptr); |
|
434 if (err) delete ptr; |
|
435 } |
|
436 if (err) |
|
437 { |
|
438 // Then log it. |
|
439 _LIT(KErr, "RClogger couldn't upgrade handle to pointer, err %i"); |
|
440 clogger->Log(KErr(), err); |
|
441 |
|
442 aLogBehaviour = 0; // Don't update flags if we failed to honour them |
|
443 } |
|
444 else |
|
445 { |
|
446 clogger = ptr; |
|
447 } |
|
448 } |
|
449 |
|
450 clogger->SetLogBehaviour(aLogBehaviour); |
|
451 } |
|
452 |
|
453 #endif // PERFORMANCE_CRITICAL |
|
454 |
|
455 EXPORT_C void RClogger::SetLogBehaviour(TUint aLogBehaviour) |
|
456 { |
|
457 iFlags = (iFlags & ~KFlagsMask) | (aLogBehaviour & KFlagsMask); |
|
458 |
|
459 if (!(iFlags & EUseHeapBuffer)) iBuf.Close(); |
|
460 |
|
461 /* This is not needed any more |
|
462 if (iFlags & EMonitorTagState) |
|
463 { |
|
464 iBody.StartCallbackDispatcher(); |
|
465 } |
|
466 else |
|
467 { |
|
468 iBody.StopCallbackDispatcher(); |
|
469 } |
|
470 */ |
|
471 } |
|
472 |
|
473 EXPORT_C TInt RClogger::SetEnabled(const TDesC& aTag, TUint32 aEnabledMask) |
|
474 { |
|
475 return SendReceive(ESetEnabled, TIpcArgs(&aTag, aEnabledMask)); |
|
476 } |
|
477 |
|
478 EXPORT_C TUint32 RClogger::IsEnabled(const TDesC& aTag) |
|
479 { |
|
480 TPckgBuf<TUint32> logMask; |
|
481 TInt res = SendReceive(EIsEnabled, TIpcArgs(&aTag, &logMask)); |
|
482 return res < 0 ? EFalse : logMask(); |
|
483 } |
|
484 |
|
485 /* |
|
486 EXPORT_C void RClogger::TailLogFile(TInt aNumberOfChars) |
|
487 { |
|
488 SendReceive(ETailLogToRDebug, TIpcArgs(aNumberOfChars)); |
|
489 } |
|
490 |
|
491 EXPORT_C void RClogger::TailLogFile(TDes8& aBuf) |
|
492 { |
|
493 SendReceive(ETailLogToBuf, TIpcArgs(&aBuf)); |
|
494 } |
|
495 */ |
|
496 |
|
497 EXPORT_C void RClogger::SetGlobalOptions(TUint aGlobalOptions) |
|
498 { |
|
499 SendReceive(ESetGlobalOptions, TIpcArgs(aGlobalOptions)); |
|
500 } |
|
501 |
|
502 EXPORT_C TUint RClogger::GetGlobalOptions() |
|
503 { |
|
504 return SendReceive(EGetGlobalOptions, TIpcArgs()); |
|
505 } |
|
506 |
|
507 EXPORT_C TInt RClogger::GetRamBufferSize(TInt* aNumberOfBuffers) |
|
508 { |
|
509 TBuf8<8> buf; |
|
510 buf.SetLength(8); |
|
511 SendReceive(EGetRamBufferSize, TIpcArgs(&buf)); |
|
512 TInt* ptr = (TInt*)buf.Ptr(); |
|
513 TInt size = ptr[0]; |
|
514 if (aNumberOfBuffers) |
|
515 { |
|
516 *aNumberOfBuffers = ptr[1]; |
|
517 } |
|
518 return size; |
|
519 } |
|
520 |
|
521 EXPORT_C void RClogger::SetRamBufferSize(TInt aSize, TInt aNum) |
|
522 { |
|
523 SendReceive(ESetRamBufferSize, TIpcArgs(aSize, aNum)); |
|
524 } |
|
525 |
|
526 EXPORT_C TInt RClogger::Rotate() |
|
527 { |
|
528 return SendReceive(ERotate, TIpcArgs()); |
|
529 } |
|
530 |
|
531 EXPORT_C TInt RClogger::Rotate(TDes& aFileName) |
|
532 { |
|
533 aFileName.Zero(); |
|
534 return SendReceive(ERotate, TIpcArgs(&aFileName)); |
|
535 } |
|
536 |
|
537 EXPORT_C void RClogger::SetRotateBehaviour(TInt aNumberOfOldLogsToKeep, TUint aRotateBehaviour) |
|
538 { |
|
539 SendReceive(ESetRotateBehaviour, TIpcArgs(aNumberOfOldLogsToKeep, aRotateBehaviour)); |
|
540 } |
|
541 |
|
542 EXPORT_C TUint RClogger::GetRotateBehaviour(TInt* aNumberOfOldLogsToKeep) |
|
543 { |
|
544 TBuf8<8> buf; |
|
545 buf.SetLength(8); |
|
546 SendReceive(EGetRotateBehaviour, TIpcArgs(&buf)); |
|
547 TInt* ptr = (TInt*)buf.Ptr(); |
|
548 TUint behav = ptr[0]; |
|
549 if (aNumberOfOldLogsToKeep) |
|
550 { |
|
551 *aNumberOfOldLogsToKeep = ptr[1]; |
|
552 } |
|
553 return behav; |
|
554 } |
|
555 |
|
556 EXPORT_C void RClogger::PersistSettings() |
|
557 { |
|
558 SendReceive(EPersistSettings, TIpcArgs()); |
|
559 } |
|
560 |
|
561 EXPORT_C void RClogger::ResetSettings() |
|
562 { |
|
563 SendReceive(EResetSettings, TIpcArgs()); |
|
564 } |
|
565 |
|
566 EXPORT_C void RClogger::Close() |
|
567 { |
|
568 iBuf.Close(); |
|
569 iBody.Close(); |
|
570 RSessionBase::Close(); |
|
571 } |
|
572 |
|
573 void RCloggerBody::DispatchCallbackL(TServerCallback& aCallback, TCallbackParser& aParser) |
|
574 { |
|
575 switch (aCallback.iCode) |
|
576 { |
|
577 case ETagEnabledChanged: |
|
578 { |
|
579 iSession.iEnabled = aParser.NextUint(); |
|
580 |
|
581 /* |
|
582 if (iSession.iFlags & KTestTagEnabled) |
|
583 { |
|
584 iSession.iFlags &= ~KTestTagEnabled; |
|
585 CActiveScheduler::Stop(); |
|
586 } |
|
587 */ |
|
588 break; |
|
589 } |
|
590 } |
|
591 } |
|
592 |
|
593 void RCloggerBody::ServerDiedL() |
|
594 { |
|
595 } |
|
596 |
|
597 EXPORT_C void RClogger::GetTagStatesL(CDesCArray*& aTagNames, RBuf8& aEnabled) |
|
598 { |
|
599 aTagNames = NULL; |
|
600 aEnabled.Close(); |
|
601 |
|
602 TServerCallback cb; |
|
603 TPckg<TServerCallback> cbPkg(cb); |
|
604 User::LeaveIfError(SendReceive(EGetTagStates1, TIpcArgs(&cbPkg))); |
|
605 |
|
606 RBuf8 context; |
|
607 CleanupClosePushL(context); |
|
608 if (cb.iContextLength) |
|
609 { |
|
610 context.CreateL(cb.iContextLength); |
|
611 User::LeaveIfError(SendReceive(EGetTagStates2, TIpcArgs(&context))); |
|
612 } |
|
613 TCallbackParser parser(cb); |
|
614 parser.SetContext(context); |
|
615 |
|
616 TPtrC8 enabledBuf = parser.NextDesC8(); |
|
617 TInt numTags = enabledBuf.Length() / 4; // 32 bits per tag |
|
618 |
|
619 CDesCArrayFlat* tags = new(ELeave) CDesCArrayFlat(numTags); |
|
620 CleanupStack::PushL(tags); |
|
621 while (numTags--) |
|
622 { |
|
623 tags->AppendL(parser.NextDesC()); |
|
624 } |
|
625 |
|
626 aEnabled.CreateL(enabledBuf); |
|
627 CleanupStack::Pop(tags); |
|
628 CleanupStack::PopAndDestroy(&context); |
|
629 aTagNames = tags; |
|
630 } |
|
631 |
|
632 EXPORT_C void RClogger::SetTagStatesL(const CDesCArray* aTagNames, const TDesC8& aEnabled) |
|
633 { |
|
634 __ASSERT_ALWAYS(aTagNames, User::Leave(KErrArgument)); |
|
635 TInt count = aTagNames->MdcaCount(); |
|
636 __ASSERT_ALWAYS(count * 4 == aEnabled.Size(), User::Leave(KErrArgument)); // Number of tags must equal the number of 4-byte entries in aEnabled |
|
637 |
|
638 CBufFlat* buf = CBufFlat::NewL(4096); |
|
639 CleanupStack::PushL(buf); |
|
640 RBufWriteStream stream(*buf); |
|
641 CleanupClosePushL(stream); |
|
642 stream.WriteInt32L(count); |
|
643 //stream.WriteL(aEnabled); |
|
644 stream << aEnabled; |
|
645 for (TInt i = 0; i < count; i++) |
|
646 { |
|
647 const TPtrC name = aTagNames->MdcaPoint(i); |
|
648 stream << name; |
|
649 } |
|
650 CleanupStack::PopAndDestroy(&stream); // Calls close, flushes buffer (probably not necessary with a RBufWriteStream) |
|
651 TPtrC8 bufPtr = buf->Ptr(0); |
|
652 User::LeaveIfError(SendReceive(ESetTagStates, TIpcArgs(&bufPtr))); |
|
653 CleanupStack::PopAndDestroy(buf); |
|
654 } |
|
655 |
|
656 EXPORT_C TInt RClogger::Reserved(TInt aCode, TAny*& aArg, TAny* aArg2) |
|
657 { |
|
658 TInt res = KErrNone; |
|
659 if (aCode == 0xF10C10) |
|
660 { |
|
661 res = iBody.Connect(2, EFalse); // Used by flogger shim to access internals of clogger that would otherwise be hidden to it |
|
662 } |
|
663 else if (aCode == 0xC0FFEE) |
|
664 { |
|
665 RChunk*& chunk = reinterpret_cast<RChunk*&>(aArg); |
|
666 TInt size = reinterpret_cast<TInt>(aArg2); |
|
667 res = SendReceive(ECreatePerformanceLoggingChunk, TIpcArgs(size)); |
|
668 if (res > 0) |
|
669 { |
|
670 chunk->SetHandle(res); |
|
671 res = KErrNone; |
|
672 } |
|
673 if (res == KErrNotSupported) |
|
674 { |
|
675 // Getting the chunk from the server is only possible if the debug router LDD is included, because there's no API |
|
676 // to pass a chunk from a server to a client (without doing it kernel side). So if the LDD isn't present, we need |
|
677 // to fall back to constructing it on our side and passing it to the server. |
|
678 res = chunk->CreateGlobal(KNullDesC, size, size); |
|
679 if (res == KErrNone) |
|
680 { |
|
681 res = SendReceive(ERegisterPerformanceLoggingChunk, TIpcArgs(*chunk)); |
|
682 } |
|
683 } |
|
684 } |
|
685 else if (aCode == 0x5e55) |
|
686 { |
|
687 res = SendReceive(EStartSessionWriterServer); |
|
688 } |
|
689 else |
|
690 { |
|
691 User::Panic(_L("CloggerClient"), 0); |
|
692 } |
|
693 return res; |
|
694 } |
|
695 |
|
696 EXPORT_C TInt RClogger::StaticReserved(TInt aCode, TAny*& aArg, TAny* aArg2) |
|
697 { |
|
698 TInt res = KErrNone; |
|
699 if (aCode == 0xD0715) |
|
700 { |
|
701 RClogger clogger; |
|
702 res = clogger.Connect(*reinterpret_cast<const TDesC*>(aArg2)); |
|
703 if (res == KErrNone) |
|
704 { |
|
705 aArg = reinterpret_cast<TAny*>(clogger.Handle()); |
|
706 } |
|
707 } |
|
708 else |
|
709 { |
|
710 User::Panic(_L("CloggerClient"), 0); |
|
711 } |
|
712 return res; |
|
713 } |
|
714 |
|
715 EXPORT_C void RClogger::HexDump(TUint32 aLogMask, const TDesC8& aHeader, const TDesC8& aData) |
|
716 { |
|
717 if (!(iEnabled & aLogMask)) return; |
|
718 |
|
719 SendReceive(EHexDump, TIpcArgs(&aHeader, &aData, User::NTickCount(), aLogMask)); |
|
720 } |
|
721 |
|
722 EXPORT_C void RClogger::HexDump(const TDesC8& aHeader, const TDesC8& aData) |
|
723 { |
|
724 HexDump(KNoLogMask, aHeader, aData); |
|
725 } |
|
726 |
|
727 #ifndef PERFORMANCE_CRITICAL |
|
728 |
|
729 EXPORT_C void RClogger::StaticHexDump(TUint32 aLogMask, const TDesC8& aHeader, const TDesC8& aData) |
|
730 { |
|
731 CheckConnected(); |
|
732 clogger->HexDump(aLogMask, aHeader, aData); |
|
733 } |
|
734 |
|
735 EXPORT_C void RClogger::StaticHexDump(const TDesC8& aHeader, const TDesC8& aData) |
|
736 { |
|
737 CheckConnected(); |
|
738 clogger->HexDump(KNoLogMask, aHeader, aData); |
|
739 } |
|
740 |
|
741 #endif // PERFORMANCE_CRITICAL |
|
742 |
|
743 inline TBool RClogger::Enabled(TUint32 aMask) |
|
744 { |
|
745 // First check if anything's changed |
|
746 TInt seq = 0; |
|
747 TInt err = RProperty::Get(KCloggerUid, ESequenceNumber, seq); |
|
748 if (err == KErrNone && seq > iSequence) |
|
749 { |
|
750 UpdateEnabled(seq); |
|
751 } |
|
752 |
|
753 if (!(iEnabled & aMask)) return EFalse; |
|
754 |
|
755 return ETrue; |
|
756 } |
|
757 |
|
758 void RClogger::UpdateEnabled(TInt aSequence) |
|
759 { |
|
760 iSequence = aSequence; |
|
761 TPckg<TUint32> buf(iEnabled); |
|
762 SendReceive(EUpdateEnabledMask, TIpcArgs(&buf)); |
|
763 iFlags &= ~KTestTagEnabled; |
|
764 } |
|
765 |
|
766 EXPORT_C RCloggerLogConsumer::RCloggerLogConsumer() |
|
767 : iResultBufferPtr(NULL, 0) |
|
768 { |
|
769 } |
|
770 |
|
771 EXPORT_C TInt RCloggerLogConsumer::Connect() |
|
772 { |
|
773 RClogger clogger; |
|
774 TInt res = clogger.Connect(); |
|
775 if (res) return res; |
|
776 |
|
777 TAny* arg1 = NULL; |
|
778 res = clogger.Reserved(0x5E55, arg1, NULL); // This requests clogger to start the session writer server |
|
779 clogger.Close(); |
|
780 if (res != KErrNone && res != KErrAlreadyExists) |
|
781 { |
|
782 return res; |
|
783 } |
|
784 |
|
785 res = CreateSession(KSessionLogServer, TVersion(0,0,0), 2); |
|
786 if (res) return res; |
|
787 |
|
788 res = SendReceive(ERegisterForLogMessages); |
|
789 if (res < 0) return res; |
|
790 iSharedChunk.SetHandle(res); |
|
791 return KErrNone; |
|
792 } |
|
793 |
|
794 EXPORT_C void RCloggerLogConsumer::GetNextLog(TRequestStatus& aStatus, TPtrC8& aResultBuffer) |
|
795 { |
|
796 // Server will update aResultBuffer to point to the appropriate location in iSharedChunk. |
|
797 // It can do this because we pass in effectively TPckg<TPtrC8>(aResultBuffer) and tell the server |
|
798 // what the shared chunk's Base address is in our address space. The server then computes what |
|
799 // aResultBuffer should look like and writes it back |
|
800 iResultBufferPtr.Set((TUint8*)&aResultBuffer, sizeof(TPtrC8), sizeof(TPtrC8)); |
|
801 SendReceive(EGetNextLog, TIpcArgs(&iResultBufferPtr, iSharedChunk.Base()), aStatus); |
|
802 } |
|
803 |
|
804 EXPORT_C void RCloggerLogConsumer::CancelGetNextLog() |
|
805 { |
|
806 SendReceive(ECancelGetNextLog); |
|
807 } |
|
808 |
|
809 EXPORT_C void RCloggerLogConsumer::Close() |
|
810 { |
|
811 iSharedChunk.Close(); |
|
812 RSessionBase::Close(); |
|
813 } |
|
814 |
|
815 EXPORT_C void Clogger_Slog(const char* aFmt, ...) |
|
816 { |
|
817 VA_LIST list; |
|
818 VA_START(list, aFmt); |
|
819 TPtrC8 fmt((const TUint8*)aFmt); |
|
820 RClogger::SlogList(fmt, list); |
|
821 VA_END(list); |
|
822 } |