|
1 // CloggerServer.h |
|
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 #ifndef CLOGGERSERVER_H |
|
14 #define CLOGGERSERVER_H |
|
15 |
|
16 #include "SensibleServer.h" |
|
17 #include <babitflags.h> |
|
18 #include <e32hashtab.h> |
|
19 #include <e32msgqueue.h> |
|
20 #include "debugrouter.h" |
|
21 |
|
22 class CCloggerServer; |
|
23 class MWriter; |
|
24 class CLogsDirWatcher; |
|
25 class CSyncWriterWrapper; |
|
26 class CDebugRouterClient; |
|
27 class CSessionWriter; |
|
28 class CSessionWriterSession; |
|
29 class CSessionWriterServer; |
|
30 |
|
31 class CCloggerSession : public CSensibleSession |
|
32 { |
|
33 public: |
|
34 CCloggerSession(); |
|
35 |
|
36 private: |
|
37 TBool DoServiceL(const RMessage& aMessage); |
|
38 |
|
39 inline CCloggerServer& Server(); |
|
40 ~CCloggerSession(); |
|
41 |
|
42 public: |
|
43 TAny* iContext; |
|
44 RBuf8 iGetTagStatesContext; |
|
45 RChunk iPerformanceLoggingChunk; // Only used by the high performance logging library clogger-buffered.dll |
|
46 }; |
|
47 |
|
48 class CCloggerServer : public CSensibleServer |
|
49 { |
|
50 public: |
|
51 CCloggerServer(); |
|
52 ~CCloggerServer(); |
|
53 void ConstructL(); |
|
54 |
|
55 TBool DoServiceL(const RMessage& aMessage); |
|
56 |
|
57 // Functions to be called by the session |
|
58 inline RBuf8& SessionTempBuf() { iSessionTempBuf.Zero(); return iSessionTempBuf; } |
|
59 void Log(TAny* aContext, const TDesC8& aLine, TUint32 aTickCount); // aContext can be NULL to indicate KCloggerTag |
|
60 TUint32 TagEnabled(const TAny* aContext, TInt* aCurrentSequenceNumber = NULL); |
|
61 void WriteCallbackForGetTagStatesL(TCallbackWriter& aWriter); |
|
62 TAny* NewSessionForTagL(HBufC8* aTag); // Takes ownership at end. Returns an opaque identifier for this tag (which may have been shared with other sessions) |
|
63 TAny* NewSessionForTag(HBufC8* aTag); |
|
64 void ReplaceTagL(TAny*& aCurrentContext, HBufC8* aNewTag); // If the tag for aCurrentContext hasn't been used yet, deletes it from the tag list. In either case, it then calls NewSessionForTagL. Takes ownership of both arguments if nothing leaves |
|
65 void DropSession(CCloggerSession* aSession); |
|
66 void HexDumpL(TAny* aContext, const TDesC8& aHeader, const TDesC8& aData, TUint32 aTickCount); |
|
67 void RegisterDisabledLog(TAny* aContext); |
|
68 void UpdatedBuffers(TBool aAboutToCloseBuffers=EFalse); // Registers the log buffers with the debug router, so they can be recorded in a crash log (if supported by the baseport) |
|
69 TInt CreateKernChunkForClient(RThread* aClient, TInt aMaxSize, TInt aCommittedSize, RChunk& aOurChunk); |
|
70 CSessionWriter* RegisterSessionWithSessionWriter(CSessionWriterSession* aSession); |
|
71 RChunk& GetBufChunk(); |
|
72 static void ThreadPrettyName(TDes8& aName); |
|
73 TBool ForceBreakpointRequested() const; |
|
74 |
|
75 void LogsDirHasBeenCreated(); |
|
76 void ResetIdleWriteTimer(); |
|
77 |
|
78 // Functions to be called by writers (eg CLogFile, RDebug::Print thingy) |
|
79 const TDesC8& GetBuf(TInt aIdx); // Increments ref count. May be called from other threads |
|
80 void CompletedWritingBuf(MWriter* aWriter, TInt aBuf); // Tells the server that aWriter has finished writing aBuf. If all writers have finished with this buffer then the buffer is marked ready to use. Must be called from main thread. |
|
81 TDes& GetFilenameToRotate(); // Should only be called by iCompressor, but may be called from its SyncWriter thread. iCompressor should update the name to indicate the new file it has created (so that ECopyRotatedToExternalMedia will work) |
|
82 |
|
83 void LogKernMessage(TUint8 aWhere, TUint32 aTickCount, TUint aThreadId, const TDesC8& aMsg); // Should only be called by CDebugRouterClient |
|
84 void LogHighPerformanceBuffer(const TDesC8& aBuf); |
|
85 void LogError(TRefByValue<const TDesC8> aFmt, ...); |
|
86 |
|
87 private: |
|
88 TInt TransientServerShutdownTime() const; |
|
89 CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; |
|
90 void LogLine(const TDesC8& aLine); |
|
91 void CloseBuffers(); // Deletes all buffers and removes them from iBufs |
|
92 void FlushBuffers(); |
|
93 void GotoNextBufL(); // Sets iCurrent to the next empty buffer, or allocates one if there isn't a free one. Also tells writers to get cracking if they aren't already busy |
|
94 void GetSettingsL(); |
|
95 void DoGetSettingsL(); |
|
96 void PersistSettingsL(); |
|
97 void ResetSettingsL(); |
|
98 void UpdateBufferSizeL(TInt aSize, TInt aNum); |
|
99 static TInt StaticIdleTimerExpired(TAny* aThis); |
|
100 void IdleTimerExpired(); |
|
101 TUint GetEnabledWriters() const; |
|
102 void Rotate(const RMessage* aMessage = NULL); |
|
103 void LogNote(TUint32 aLogMask, TRefByValue<const TDesC8> aFmt, ...); |
|
104 void DoLogErrorOrNote(TUint32 aLogMask, const TDesC8 &aFmt, VA_LIST args); |
|
105 void CopyLogToExternalMediaL(TDes& aFile); |
|
106 class TTagData; // I see now why the coding standards say declare inner classes etc at the start of the class declaration... |
|
107 void NotifySessionsOfChangedTag(TTagData* aTag); |
|
108 void SetKernelLoggingL(TBool aEnable); |
|
109 void UpdatedGlobalOptionsL(TUint aOldOptions); |
|
110 void TellAllWritersToWriteBuf(TInt aBuf); |
|
111 void TellWriterToWriteBuf(TInt aWriterId, TInt aBuf); |
|
112 void ReCalculateFileAlignment(); |
|
113 TInt OpenLogFile(); |
|
114 TInt AdjustBufferChunk(TInt aNewSize); |
|
115 inline TTime TickCountToTime(TUint32 aTickCount) const; |
|
116 |
|
117 private: |
|
118 // Buffers |
|
119 class TBufEntry { |
|
120 public: |
|
121 TBufEntry() : iBuf(NULL, 0), iArrayIdx(-1), iNext(NULL), iBufferBusy(0) {} |
|
122 |
|
123 //RBuf8 iBuf; |
|
124 TPtr8 iBuf; |
|
125 TInt iArrayIdx; |
|
126 TBufEntry* iNext; |
|
127 TUint iBufferBusy; // This is used to track when all the different consumers of the buffer (RDebug, Bluetooth, File etc) are finished with it |
|
128 }; |
|
129 RPointerArray<TBufEntry> iBufs; |
|
130 TBufEntry* iCurrent; |
|
131 TInt iSubtractSizeOfNextBuffer; |
|
132 RBuf8 iSessionTempBuf; // Used by sessions for reading descriptor from client |
|
133 RBuf8 iTempBuf; // Used for formatting line with timestamp and tag |
|
134 RChunk iChunkForBufs; // Use a separate chunk so we can map into crashlogs |
|
135 |
|
136 // Miscellaneous stuff used when doing flushes and sync writes |
|
137 CActiveSchedulerWait iFlushBufferWait; |
|
138 const TDesC8* iSyncWriteBuffer; // This is only used when doing synchronous writing. If not for the OOM handling behaviour of LogLine, it would always be equal to &iTempBuf |
|
139 TUint iSyncWriteBufferBusy; |
|
140 CPeriodic* iIdleWriteTimer; |
|
141 |
|
142 // Log file |
|
143 RFs iFs; // A couple of things assume the session path is always in the log directory on the c drive |
|
144 RFile iLogFile; |
|
145 CLogsDirWatcher* iLogsDirWatcher; |
|
146 RPointerArray<MWriter> iWriters; |
|
147 TFileName iFileBeingRotated; // This is used to temporarily store the name of a file while it's being rotated and possibly compressed |
|
148 CSyncWriterWrapper* iCompressor; |
|
149 RMessagePtr2 iRotationMessage; // To be completed when the log file compression finishes |
|
150 |
|
151 // Settings |
|
152 TUint iOptions; // TGlobalOptions |
|
153 TBitFlags32 iFlags; |
|
154 TInt iBufferSize; |
|
155 TInt iNumBuffers; |
|
156 TInt iNumRotates; |
|
157 TUint iRotateBehaviour; |
|
158 TInt64 iStartupTickInMicroseconds; |
|
159 TTime iTimeAtStartup; |
|
160 TInt iTickFreq; |
|
161 // Tags |
|
162 class TTagData |
|
163 { |
|
164 public: |
|
165 TTagData(HBufC8* aName) : iTagName(aName), iRefCount(0), iEnabled(0), iThreadIdForRDebugger(0), iFlags() {} |
|
166 void SetShouldDisplay() { iFlags.Set(EShouldDisplay); } |
|
167 TBool ShouldDisplay() const { return iFlags.IsSet(EShouldDisplay); } |
|
168 |
|
169 HBufC8* iTagName; |
|
170 TInt iRefCount; |
|
171 TUint32 iEnabled; // bitmask |
|
172 TUint iThreadIdForRDebugger; |
|
173 private: |
|
174 enum TFlags { |
|
175 EShouldDisplay, // Indicates this tag should be exposed to the client via GetTagStatesL |
|
176 }; |
|
177 TBitFlags32 iFlags; |
|
178 }; |
|
179 |
|
180 RPtrHashMap<TDesC8, TTagData> iTags; // Keys are the tag names, values are TTagDatas |
|
181 RHashMap<TUint, TTagData*> iRDebugTags; |
|
182 CDebugRouterClient* iKernDebugRouter; |
|
183 TTagData* iRDebugTag; // Is always set. Only used in OOM conditions when we can't create a threadid&name tag |
|
184 TTagData* iFallbackTag; // Always set. This tag represents the default enabled state for any new tags that appear while we're running |
|
185 TTagData* iCloggerTag; // Always set. Used to figure out the internal logging mask (previously used iInternalLoggingMask) |
|
186 |
|
187 CSessionWriterServer* iSessionWriterServer; // Support for the session writer |
|
188 TInt iEnabledStatesSequenceNumber; |
|
189 }; |
|
190 |
|
191 #define MINTAGSTART "---------- --:--:--.---: [Clogger] " // Writers can use this too, if they want to |
|
192 |
|
193 class MSyncWriter |
|
194 { |
|
195 public: |
|
196 /* |
|
197 * Synchronously writes aBuf. Can leave to indicate failure (although the failure may well be ignored) |
|
198 */ |
|
199 virtual void WriteBufL(const TDesC8& aBuf) =0; |
|
200 |
|
201 /* |
|
202 * delete writer and all resources. |
|
203 */ |
|
204 virtual void CloseWriter() =0; |
|
205 }; |
|
206 |
|
207 class MWriter |
|
208 { |
|
209 public: |
|
210 /* |
|
211 * Start writing aBuf. The server guarantees not to call this if the plugin is not enabled (as defined by a call |
|
212 * to IsEnabled()) or if the plugin is already busy writing something else (as defined by IsBusyWriting()). |
|
213 * If the writer is enabled and not currently writing something else, but is unable to perform the write, |
|
214 * then it should call CompletedWritingBuf before returning, to indicate that the server shouldn't wait for it. |
|
215 * |
|
216 * All calls to WriteBuf must be matched by a call to CompletedWritingBuf. |
|
217 */ |
|
218 virtual void WriteBuf(TInt aBuf) =0; |
|
219 |
|
220 virtual void CloseWriter() =0; // delete writer and all resources. Will never be called while a write is in progress. |
|
221 |
|
222 /* |
|
223 * Enables complex writers to take action when they are disabled. |
|
224 * Writers must honour this setting by returning immediately when a write function is called when they are disabled. |
|
225 * This may be called when a write is in progess - if so the write of the current buffer should complete as normal, it |
|
226 * should just update its internal flag so that next time the server calls WriteBuf it returns immediately |
|
227 * |
|
228 * Generally though SetEnabled will simply update an iEnabled member variable |
|
229 * |
|
230 * Writers will get a call to SetEnabled after they are constructed, before WriteBuf is called for the first time. |
|
231 */ |
|
232 virtual void SetEnabled(TBool aEnabled) =0; |
|
233 virtual TBool IsEnabled() =0; |
|
234 |
|
235 virtual TBool IsBusyWriting() =0; |
|
236 }; |
|
237 |
|
238 class CLogWriter : public CActive, public MWriter |
|
239 { |
|
240 public: |
|
241 CLogWriter(CCloggerServer& aServer, RFile& aFile) |
|
242 : CActive(EPriorityHigh), // It's more important to keep writing than to handle clientserver calls |
|
243 iServer(aServer), iFile(aFile), iBuf(-1), iEnabled(EFalse) |
|
244 { |
|
245 CActiveScheduler::Add(this); |
|
246 } |
|
247 |
|
248 void WriteBuf(TInt aBuf); |
|
249 void DoCancel(); |
|
250 void RunL(); |
|
251 void SetEnabled(TBool aEnabled); |
|
252 TBool IsEnabled() { return iEnabled; } |
|
253 void CloseWriter(); |
|
254 ~CLogWriter(); |
|
255 TBool IsBusyWriting(); |
|
256 |
|
257 private: |
|
258 CCloggerServer& iServer; |
|
259 RFile& iFile; |
|
260 TInt iBuf; |
|
261 TBool iEnabled; |
|
262 }; |
|
263 |
|
264 class CRDebugWriter : public CBase, public MSyncWriter |
|
265 { |
|
266 public: |
|
267 CRDebugWriter(CCloggerServer& aServer); |
|
268 void WriteBufL(const TDesC8& aBuf); |
|
269 void CloseWriter(); |
|
270 |
|
271 private: |
|
272 CCloggerServer& iServer; |
|
273 }; |
|
274 |
|
275 class CMessageQueueWriter : public CBase, public MSyncWriter |
|
276 { |
|
277 public: |
|
278 static CMessageQueueWriter* NewL(); |
|
279 void WriteBufL(const TDesC8& aBuf); |
|
280 void CloseWriter(); |
|
281 |
|
282 private: |
|
283 CMessageQueueWriter(); |
|
284 ~CMessageQueueWriter(); |
|
285 |
|
286 private: |
|
287 RMsgQueue<TBuf8<128> > iQ; |
|
288 }; |
|
289 |
|
290 class CSessionWriter : public CBase, public MWriter |
|
291 { |
|
292 public: |
|
293 CSessionWriter(CCloggerServer& aServer); |
|
294 ~CSessionWriter(); |
|
295 |
|
296 void WriteBuf(TInt aBuf); |
|
297 void DoCancel(); |
|
298 void RunL(); |
|
299 void SetEnabled(TBool aEnabled); |
|
300 TBool IsEnabled() { return iEnabled; } |
|
301 void CloseWriter(); |
|
302 TBool IsBusyWriting(); |
|
303 |
|
304 void Completed(); |
|
305 |
|
306 public: |
|
307 CSessionWriterSession* iSession; // Support only one session |
|
308 |
|
309 private: |
|
310 CCloggerServer& iServer; |
|
311 TInt iBuf; |
|
312 TBool iEnabled; |
|
313 }; |
|
314 |
|
315 class CSyncWriterWrapper : public CActive, public MWriter |
|
316 { |
|
317 public: |
|
318 static CSyncWriterWrapper* NewL(CCloggerServer& aServer, MSyncWriter& aWriter, TInt aWriterId); // Takes ownership of aWriter at end |
|
319 void WriteBuf(TInt aBuf); |
|
320 void DoCancel(); |
|
321 void RunL(); |
|
322 void SetEnabled(TBool aEnabled); |
|
323 TBool IsEnabled() { return iEnabled; } |
|
324 void CloseWriter(); |
|
325 ~CSyncWriterWrapper(); |
|
326 TBool IsBusyWriting(); |
|
327 |
|
328 private: |
|
329 CSyncWriterWrapper(CCloggerServer& aServer, MSyncWriter& aWriter); |
|
330 void ConstructL(TInt aWriterId); |
|
331 static TInt ThreadFunction(TAny* aSelf); |
|
332 private: |
|
333 CCloggerServer& iServer; |
|
334 MSyncWriter& iWriter; |
|
335 TInt iBuf; |
|
336 TBool iEnabled; |
|
337 RThread iMainThread; |
|
338 RThread iWorkerThread; |
|
339 TRequestStatus iThreadStatus; |
|
340 TBool iOwnWriter; // Bit of a cludge to ensure ownership of aWriter is correct |
|
341 }; |
|
342 |
|
343 class CLogCompressor : public CBase, public MSyncWriter |
|
344 { |
|
345 public: |
|
346 static CLogCompressor* NewLC(CCloggerServer& aServer); |
|
347 ~CLogCompressor(); |
|
348 void WriteBufL(const TDesC8& aBuf); |
|
349 void CloseWriter(); |
|
350 |
|
351 private: |
|
352 CLogCompressor(CCloggerServer& aServer); |
|
353 void DoGzipL(RFile& aInput, const TDesC& aOutput); |
|
354 |
|
355 private: |
|
356 CCloggerServer& iServer; |
|
357 RFs iFs; |
|
358 }; |
|
359 |
|
360 class CDebugRouterClient : public CActive |
|
361 { |
|
362 public: |
|
363 static CDebugRouterClient* NewL(CCloggerServer& aServer); |
|
364 ~CDebugRouterClient(); |
|
365 void RunL(); |
|
366 void DoCancel(); |
|
367 void StartRouting(TBool aConsumeLogs); |
|
368 void StopRouting(); |
|
369 void OpenChunkL(); |
|
370 TInt RegisterCrashDumpAreas(const TDesC8& aCrashDumpAreas); |
|
371 TInt CreateKernChunkForClient(RThread* aClient, TInt aMaxSize, TInt aCommittedSize, RChunk& aOurChunk); |
|
372 TInt AdjustChunk(RChunk& aChunk, TInt aNewSize); |
|
373 |
|
374 private: |
|
375 CDebugRouterClient(CCloggerServer& aServer); |
|
376 void ConstructL(); |
|
377 |
|
378 private: |
|
379 CCloggerServer& iServer; |
|
380 RCloggerDebugRouter iDebugRouter; |
|
381 RChunk iSharedChunk; |
|
382 RBuf8 iTempBuf; |
|
383 }; |
|
384 |
|
385 #endif |