1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32cons.h> |
|
20 #include <e32base.h> |
|
21 #include <f32file.h> |
|
22 #include <c32comm.h> |
|
23 #include <s32file.h> |
|
24 #include <pathinfo.h> |
|
25 #include <s32mem.h> |
|
26 #include <bautils.h> |
|
27 #include <sysutil.h> |
|
28 #include <piprofiler/ProfilerConfig.h> |
|
29 #include "ProfilerEngine.h" |
|
30 #include <piprofiler/ProfilerTraces.h> |
|
31 #include <piprofiler/EngineUIDs.h> |
|
32 |
|
33 // properties |
|
34 const TUid KEngineStatusPropertyCat={0x2001E5AD}; |
|
35 enum TEnginePropertyKeys |
|
36 { |
|
37 EProfilerEngineStatus = 8, |
|
38 EProfilerErrorStatus |
|
39 }; |
|
40 |
|
41 static _LIT_SECURITY_POLICY_PASS( KAllowAllPolicy ); |
|
42 |
|
43 // CONSTANTS |
|
44 const TInt KStreamBufferSize = 32768; |
|
45 const TInt KSavedLineCount = 64; |
|
46 const TInt KFileNameBufSize = 128; |
|
47 |
|
48 // LITERALS |
|
49 _LIT8(KGenericTraceOutput, "output_type"); |
|
50 _LIT8(KGenericTraceFilePrefix, "file_prefix"); |
|
51 _LIT8(KGenericTraceFileSaveDrive, "save_file_location"); |
|
52 _LIT8(KEquals, "="); |
|
53 _LIT8(KNewLineSeparator, "\n"); |
|
54 _LIT8(KProfilerVersionTag, "version"); |
|
55 _LIT8(KEndMark, "[end]"); |
|
56 _LIT8(KOutputToDebugOutput, "debug_output"); |
|
57 |
|
58 /** |
|
59 * |
|
60 * The controller class used to provide the Profiler functions. |
|
61 * This runs as a server in the engine thread |
|
62 * |
|
63 */ |
|
64 class CPServer : public CServer2, public MProfilerController |
|
65 { |
|
66 public: |
|
67 static MProfilerController* NewL(TInt aPriority, MProfilerEngine& aEngine); |
|
68 |
|
69 private: |
|
70 CPServer(TInt aPriority, MProfilerEngine& aEngine); |
|
71 void Release(); |
|
72 CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const; |
|
73 }; |
|
74 |
|
75 // The session class used by the server controller |
|
76 class CPSession : public CSession2 |
|
77 { |
|
78 private: |
|
79 inline const CPServer& Server() const; |
|
80 void ServiceL(const RMessage2& aMessage); |
|
81 }; |
|
82 |
|
83 /* |
|
84 * |
|
85 * CProfiler class implementation |
|
86 * |
|
87 */ |
|
88 // -------------------------------------------------------------------------------------------- |
|
89 CProfiler* CProfiler::NewLC(const TDesC& aSettingsFile) |
|
90 { |
|
91 CProfiler* self = new(ELeave) CProfiler(aSettingsFile); |
|
92 CleanupStack::PushL(self); |
|
93 self->ConstructL(); |
|
94 return self; |
|
95 } |
|
96 |
|
97 // -------------------------------------------------------------------------------------------- |
|
98 CProfiler::CProfiler(const TDesC& aSettingsFile) : |
|
99 iSettingsFileLocation(aSettingsFile) |
|
100 { |
|
101 // define property for Profiler Engine status, UI may read it for control purposes |
|
102 if ( RProperty::Define(KEngineStatusPropertyCat, |
|
103 EProfilerEngineStatus, |
|
104 RProperty::EInt, |
|
105 KAllowAllPolicy, |
|
106 KAllowAllPolicy, |
|
107 0) != KErrAlreadyExists ) |
|
108 { |
|
109 LOGTEXT(_L("CProfiler::CProfiler - status property already defined")); |
|
110 } |
|
111 |
|
112 if ( RProperty::Define(KEngineStatusPropertyCat, |
|
113 EProfilerErrorStatus, |
|
114 RProperty::EInt, |
|
115 KAllowAllPolicy, |
|
116 KAllowAllPolicy, |
|
117 0) != KErrAlreadyExists ) |
|
118 { |
|
119 LOGTEXT(_L("CProfiler::CProfiler - status property already defined")); |
|
120 } |
|
121 |
|
122 // attach to own property |
|
123 iEngineStatus.Attach(KEngineStatusPropertyCat, EProfilerEngineStatus); |
|
124 // set status idle |
|
125 iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, RProfiler::EIdle); |
|
126 |
|
127 // attach to own property |
|
128 iUpdateStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus); |
|
129 // set status idle |
|
130 iUpdateStatus.Set(KEngineStatusPropertyCat, EProfilerErrorStatus, EFalse); |
|
131 } |
|
132 |
|
133 // -------------------------------------------------------------------------------------------- |
|
134 CProfiler::~CProfiler() |
|
135 { |
|
136 LOGTEXT(_L("CProfiler::~CProfiler - Enter")); |
|
137 |
|
138 // delete error checker |
|
139 if(iErrorChecker) |
|
140 { |
|
141 iErrorChecker->Cancel(); |
|
142 delete iErrorChecker; |
|
143 iErrorChecker = NULL; |
|
144 } |
|
145 |
|
146 // delete settings array |
|
147 if(iDefaultSamplerAttributesArray) |
|
148 { |
|
149 iDefaultSamplerAttributesArray->Reset(); |
|
150 delete iDefaultSamplerAttributesArray; |
|
151 iDefaultSamplerAttributesArray = NULL; |
|
152 } |
|
153 |
|
154 // delete settings file raw line array |
|
155 if(iSavedLineArray) |
|
156 { |
|
157 iSavedLineArray->Reset(); |
|
158 delete iSavedLineArray; |
|
159 iSavedLineArray = NULL; |
|
160 } |
|
161 |
|
162 // delete sampler controller, cleans up the sampler plugin instances |
|
163 if(iSamplerHandler) |
|
164 { |
|
165 delete iSamplerHandler; |
|
166 iSamplerHandler = NULL; |
|
167 } |
|
168 // delete writer controller, cleans up the writer plugin instances |
|
169 if(iWriterHandler) |
|
170 { |
|
171 delete iWriterHandler; |
|
172 iWriterHandler = NULL; |
|
173 } |
|
174 |
|
175 // delete user side sampler stream |
|
176 if(iUserStream) |
|
177 { |
|
178 delete iUserStream; |
|
179 iUserStream = NULL; |
|
180 } |
|
181 |
|
182 // close engine status property |
|
183 iEngineStatus.Close(); |
|
184 if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerEngineStatus) != KErrNotFound) |
|
185 { |
|
186 LOGTEXT(_L("CProfiler::~CProfiler - cannot close status property")); |
|
187 } |
|
188 // close engine update property |
|
189 iUpdateStatus.Close(); |
|
190 if (RProperty::Delete(KEngineStatusPropertyCat, EProfilerErrorStatus) != KErrNotFound) |
|
191 { |
|
192 LOGTEXT(_L("CProfiler::~CProfiler - cannot close update property")); |
|
193 } |
|
194 |
|
195 // close server process |
|
196 if (iServer) |
|
197 { |
|
198 LOGTEXT(_L("CProfiler::~CProfiler - Releasing server")); |
|
199 iServer->Release(); |
|
200 } |
|
201 |
|
202 LOGTEXT(_L("CProfiler::~CProfiler - Finished")); |
|
203 } |
|
204 |
|
205 // -------------------------------------------------------------------------------------------- |
|
206 void CProfiler::ConstructL() |
|
207 { |
|
208 LOGTEXT(_L("CProfiler::ConstructL - Enter")); |
|
209 TInt err(0); |
|
210 |
|
211 // create new sampler stream instance |
|
212 iUserStream = CProfilerSampleStream::NewL(KStreamBufferSize); |
|
213 if(!iUserStream) |
|
214 { |
|
215 LOGTEXT(_L("Profiler engine cannot reserve memory")); |
|
216 User::Leave(KErrCancel); // operation cancelled |
|
217 } |
|
218 |
|
219 // engine status checker |
|
220 iErrorChecker = CProfilerErrorChecker::NewL(); |
|
221 iErrorChecker->SetObserver(this); |
|
222 |
|
223 // create and initiate plug-in controller instances |
|
224 iSamplerHandler = CSamplerController::NewL(*iUserStream); |
|
225 iWriterHandler = CWriterController::NewL(*iUserStream); |
|
226 |
|
227 iWriterHandler->InitialiseWriterListL(); |
|
228 |
|
229 // set engine as an observer to sampler controller to get the notification of plugin load has ended |
|
230 iSamplerHandler->SetObserver(this); |
|
231 |
|
232 // default settings from sampler plugins, maximum 20 sampler plugins |
|
233 iDefaultSamplerAttributesArray = new(ELeave) CArrayFixFlat<TSamplerAttributes>(20); |
|
234 |
|
235 // set profiler status to initializing |
|
236 iState = RProfiler::EInitializing; |
|
237 iEngineStatus.Set(RProfiler::EInitializing); |
|
238 |
|
239 // set default general settings, will be overdriven if changed in settings file |
|
240 iGeneralAttributes.iTraceOutput.Copy(KDefaultTraceOutput); |
|
241 iGeneralAttributes.iTraceFilePrefix.Copy(KDefaultTraceFilePrefix); |
|
242 iGeneralAttributes.iSaveFileDrive.Copy(KDefaultTraceFileSaveDrive); |
|
243 |
|
244 RThread me; |
|
245 |
|
246 me.SetPriority(EPriorityRealTime); |
|
247 |
|
248 err = KErrGeneral; |
|
249 TInt count = 0; |
|
250 |
|
251 while(err != KErrNone && count < 30) |
|
252 { |
|
253 err = User::RenameThread(KProfilerName); |
|
254 if(err != KErrNone) |
|
255 { |
|
256 User::Leave(err); |
|
257 } |
|
258 else break; |
|
259 } |
|
260 |
|
261 if(err != KErrNone) |
|
262 { |
|
263 User::Leave(err); |
|
264 } |
|
265 |
|
266 // set settings file loading preferences |
|
267 iSettingsFileLoaded = EFalse; |
|
268 |
|
269 // change status property to idle since initialization successfull |
|
270 iState = RProfiler::EIdle; |
|
271 if( iEngineStatus.Set((TInt)RProfiler::EIdle) != KErrNone ) |
|
272 { |
|
273 LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed")); |
|
274 } |
|
275 |
|
276 if( iUpdateStatus.Set(EFalse) != KErrNone ) |
|
277 { |
|
278 LOGTEXT(_L("CProfiler::ConstructL - engine status property change failed")); |
|
279 } |
|
280 |
|
281 // create a server instance for clients to communicate with |
|
282 iServer = CPServer::NewL(10,*this); |
|
283 |
|
284 // close the handle |
|
285 me.Close(); |
|
286 |
|
287 LOGTEXT(_L("CProfiler::ConstructL - Exit")); |
|
288 |
|
289 } |
|
290 |
|
291 CProfilerSampleStream* CProfiler::GetSamplerStream() |
|
292 { |
|
293 return iUserStream; |
|
294 } |
|
295 |
|
296 void CProfiler::HandleSamplerControllerReadyL() |
|
297 { |
|
298 // load settings |
|
299 // check if settings file already loaded |
|
300 if(!iSettingsFileLoaded) |
|
301 { |
|
302 // load default settings file |
|
303 LoadSettingsL(); |
|
304 |
|
305 iSettingsFileLoaded = ETrue; |
|
306 } |
|
307 |
|
308 // notify engine's launcher(UI or PIProfilerLauncher) to continue launch |
|
309 RProcess::Rendezvous(KErrNone); |
|
310 } |
|
311 |
|
312 void CProfiler::NotifyRequesterForSettingsUpdate() |
|
313 { |
|
314 // set update status P&S property true => update needed on UI side |
|
315 iUpdateStatus.Set(ETrue); |
|
316 } |
|
317 |
|
318 void CProfiler::HandleProfilerErrorChangeL(TInt aError) |
|
319 { |
|
320 LOGSTRING2("CProfiler::HandleProfilerErrorChangeL() - error received, %d", aError); |
|
321 |
|
322 // check if profiler running |
|
323 if(iState == RProfiler::ERunning) |
|
324 { |
|
325 // stop profiler if error occurred during the trace |
|
326 iEngineStatus.Set(aError); |
|
327 |
|
328 // stop samplers, NOTE! Writer plugins not stopped since |
|
329 iSamplerHandler->StopSamplerPlugins(); |
|
330 |
|
331 // stop debug output plugin and write the rest of the trace data to output |
|
332 if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0) |
|
333 { |
|
334 // write the rest of trace data only if debug output selected |
|
335 iWriterHandler->StopSelectedPlugin(); |
|
336 } |
|
337 LOGSTRING2("CProfiler::HandleProfilerErrorChangeL - sampling stopped, going to state %d", RProfiler::EIdle); |
|
338 } |
|
339 } |
|
340 |
|
341 // ---------------------------------------------------------------------------- |
|
342 // Gets a value from settings file for certain attribute. |
|
343 // ---------------------------------------------------------------------------- |
|
344 void CProfiler::DoGetValueFromSettingsArray(CDesC8ArrayFlat* aLineArray, const TDesC8& aAttribute, TDes8& aValue) |
|
345 { |
|
346 LOGTEXT(_L("CProfiler::DoGetValueFromSettingsFile()")); |
|
347 _LIT8(KSettingItemSeparator, "="); |
|
348 |
|
349 // read a line of given array |
|
350 for (TInt i=0; i<aLineArray->MdcaCount(); i++) |
|
351 { |
|
352 // check if this line has a separator |
|
353 TInt sepPos = aLineArray->MdcaPoint(i).Find(KSettingItemSeparator); |
|
354 if (sepPos > 0) |
|
355 { |
|
356 // check that the element matches |
|
357 if (aLineArray->MdcaPoint(i).Left(sepPos).CompareF(aAttribute) == 0) |
|
358 { |
|
359 // get the value |
|
360 aValue.Copy(aLineArray->MdcaPoint(i).Right(aLineArray->MdcaPoint(i).Length()-sepPos-1)); |
|
361 break; |
|
362 } |
|
363 } |
|
364 } |
|
365 } |
|
366 |
|
367 // -------------------------------------------------------------------------------------------- |
|
368 TInt CProfiler::GetSamplerAttributesL(const RMessage2& aMessage) |
|
369 { |
|
370 TInt err(KErrNone); |
|
371 TInt pos(0); |
|
372 |
|
373 // get sampler count |
|
374 TInt count(iDefaultSamplerAttributesArray->Count()); |
|
375 |
|
376 // write each of the default sampler plugin setting attributes over client-server session |
|
377 for (TInt i(0); i<count; ++i) |
|
378 { |
|
379 TSamplerAttributes attr = iDefaultSamplerAttributesArray->At(i); |
|
380 TPckgC<TSamplerAttributes> attrPckg(attr); |
|
381 |
|
382 // write a TSamplerAttributes container at a time |
|
383 aMessage.WriteL(0, attrPckg, pos); |
|
384 pos += attrPckg.Length(); |
|
385 } |
|
386 |
|
387 aMessage.Complete(err); |
|
388 return err; |
|
389 } |
|
390 |
|
391 // -------------------------------------------------------------------------------------------- |
|
392 TInt CProfiler::SetSamplerAttributesL(const RMessage2& aMessage) |
|
393 { |
|
394 TSamplerAttributes attr; |
|
395 TPckg<TSamplerAttributes> inAttr(attr); |
|
396 |
|
397 TInt err = aMessage.Read(0, inAttr, 0); |
|
398 |
|
399 // apply the changes directly to a plugin |
|
400 iSamplerHandler->SetSamplerSettingsL(attr.iUid, attr); |
|
401 |
|
402 aMessage.Complete(err); |
|
403 return err; |
|
404 } |
|
405 |
|
406 // -------------------------------------------------------------------------------------------- |
|
407 TInt CProfiler::GetGeneralAttributesL(const RMessage2& aMessage) |
|
408 { |
|
409 TPckgBuf<TGeneralAttributes> generalSettings( iGeneralAttributes ); |
|
410 |
|
411 // write general attributes over client-server session |
|
412 TInt err = aMessage.Write(0, generalSettings); |
|
413 |
|
414 aMessage.Complete(err); |
|
415 return err; |
|
416 } |
|
417 |
|
418 // -------------------------------------------------------------------------------------------- |
|
419 TInt CProfiler::SetGeneralAttributesL(const RMessage2& aMessage) |
|
420 { |
|
421 // read the general settings from message |
|
422 TGeneralAttributes attr; |
|
423 TPckg<TGeneralAttributes> inPckg(attr); |
|
424 TInt err = aMessage.Read(0, inPckg, 0); |
|
425 |
|
426 // copy to the general attributes |
|
427 iGeneralAttributes.iSaveFileDrive.Copy(attr.iSaveFileDrive); |
|
428 iGeneralAttributes.iTraceFilePrefix.Copy(attr.iTraceFilePrefix); |
|
429 iGeneralAttributes.iTraceOutput.Copy(attr.iTraceOutput); |
|
430 |
|
431 aMessage.Complete(err); |
|
432 return err; |
|
433 } |
|
434 |
|
435 TInt CProfiler::GetSamplerAttributeCountL(const RMessage2& aMessage) |
|
436 { |
|
437 // get the plugin array count and wrap it to TPckgBuf<> |
|
438 TPckgBuf<TInt> attributeCount(iDefaultSamplerAttributesArray->Count()); |
|
439 |
|
440 // write general attributes over client-server session |
|
441 TInt err = aMessage.Write(0, attributeCount); |
|
442 |
|
443 aMessage.Complete(err); |
|
444 return err; |
|
445 } |
|
446 |
|
447 TInt CProfiler::RefreshStatus(const RMessage2& aMessage) |
|
448 { |
|
449 TInt err(KErrNone); |
|
450 |
|
451 // update profiler status for requester |
|
452 iEngineStatus.Set(iState); |
|
453 |
|
454 aMessage.Complete(err); |
|
455 return err; |
|
456 } |
|
457 |
|
458 // -------------------------------------------------------------------------------------------- |
|
459 TInt CProfiler::LoadSettingsL(/*const TDesC& configFile*/) |
|
460 { |
|
461 RFs fileServer; |
|
462 RFile file; |
|
463 TInt err(KErrNone); |
|
464 |
|
465 // connect to file server |
|
466 err = fileServer.Connect(); |
|
467 |
|
468 // check if file server can be connected |
|
469 if (err != KErrNone) |
|
470 { |
|
471 // file server couldn't be connected |
|
472 return KErrGeneral; |
|
473 } |
|
474 |
|
475 // check if settings file location length reasonable |
|
476 if ( iSettingsFileLocation.CompareF(KNullDesC) == 0 ) |
|
477 { |
|
478 // open the file with the default path and name |
|
479 TBuf<256> pathAndName; |
|
480 pathAndName.Append(PathInfo::PhoneMemoryRootPath()); |
|
481 pathAndName.Append(KProfilerSettingsFileName); |
|
482 iSettingsFileLocation.Copy(pathAndName); |
|
483 LOGTEXT(_L("CProfiler::LoadSettings - Opening settings file with name (with the default path)")); |
|
484 LOGTEXT(pathAndName); |
|
485 } |
|
486 |
|
487 // open the file with the given path and name |
|
488 err = file.Open(fileServer,iSettingsFileLocation,EFileRead); |
|
489 |
|
490 |
|
491 // check if RFile::Open() returned error |
|
492 if (err != KErrNone) |
|
493 { |
|
494 // file couldn't be opened |
|
495 LOGTEXT(_L("CProfiler::LoadSettings - Failed to open settings, using default")); |
|
496 |
|
497 // check if settings already loaded |
|
498 if(iDefaultSamplerAttributesArray->Count() > 0) |
|
499 { |
|
500 // reset default settings array |
|
501 iDefaultSamplerAttributesArray->Reset(); |
|
502 } |
|
503 |
|
504 // load default settings, instead of settings file ones |
|
505 iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray); |
|
506 |
|
507 fileServer.Close(); |
|
508 return KErrNone; |
|
509 } |
|
510 |
|
511 // initialize iSavedLineArray, initial settings file lines 64 |
|
512 if(iSavedLineArray) |
|
513 { |
|
514 iSavedLineArray->Reset(); |
|
515 } |
|
516 else |
|
517 { |
|
518 iSavedLineArray = new (ELeave) CDesC8ArrayFlat(KSavedLineCount); |
|
519 } |
|
520 |
|
521 iSavedLinesCount = KSavedLineCount; |
|
522 |
|
523 // get size of the file |
|
524 TInt fileSize(0); |
|
525 err = file.Size(fileSize); |
|
526 // check if an error occurred reading the file size |
|
527 if(err != KErrNone) |
|
528 { |
|
529 return KErrGeneral; // could not find the size |
|
530 } |
|
531 |
|
532 // sanity check for the file size |
|
533 if (fileSize < 3 || fileSize > 20000) |
|
534 { |
|
535 fileSize = KSettingsFileSize; |
|
536 return KErrNotSupported; |
|
537 } |
|
538 |
|
539 // read the contents of the file to buffer. |
|
540 iSettingsBuffer.Zero(); |
|
541 file.Read(iSettingsBuffer, fileSize); |
|
542 file.Close(); |
|
543 fileServer.Close(); |
|
544 LOGSTRING2("CProfiler::LoadSettings: read %d bytes",iSettingsBuffer.Length()); |
|
545 |
|
546 // append end mark "[end]" |
|
547 iSettingsBuffer.Append(KEndMark); |
|
548 // force an ending newline |
|
549 iSettingsBuffer.Append('\n'); |
|
550 |
|
551 // next fill the saved settings array (CDesC8ArrayFlat) for further comparison with changes and default values |
|
552 TBuf8<384> tmpBuf; |
|
553 TInt lineCount(0); |
|
554 TBool commentFound(EFalse); |
|
555 for (TInt i(0); i<iSettingsBuffer.Length(); i++) // loop all chars |
|
556 { |
|
557 // if new line char found, create a new text line |
|
558 if (iSettingsBuffer[i]=='\r' || iSettingsBuffer[i]=='\n') |
|
559 { |
|
560 // check if collected string has reasonable length |
|
561 if (tmpBuf.Length() > 0) |
|
562 { |
|
563 // remove extra spaces |
|
564 tmpBuf.TrimAll(); |
|
565 // check if the size of the array too small |
|
566 if(lineCount >= iSavedLinesCount) |
|
567 { |
|
568 iSavedLineArray->ExpandL(20); // expand by 20 lines |
|
569 iSavedLinesCount += 20; |
|
570 } |
|
571 iSavedLineArray->AppendL(tmpBuf); |
|
572 tmpBuf.Copy(KNullDesC8); |
|
573 lineCount++; |
|
574 } |
|
575 commentFound = EFalse; |
|
576 } |
|
577 // check if comment mark ';' is found on the line, skip the rest of the line |
|
578 else if(iSettingsBuffer[i]==';') |
|
579 { |
|
580 commentFound = ETrue; |
|
581 } |
|
582 // otherwise append a char to the temp line buffer if it is a wanted ASCII char |
|
583 else if (iSettingsBuffer[i]>=32 && iSettingsBuffer[i]<=127 && !commentFound) |
|
584 { |
|
585 tmpBuf.Append(iSettingsBuffer[i]); |
|
586 } |
|
587 } |
|
588 |
|
589 // empty tmpBuf |
|
590 tmpBuf.Copy(KNullDesC8); |
|
591 // check settings file version |
|
592 DoGetValueFromSettingsArray(iSavedLineArray, KProfilerVersionTag, tmpBuf); |
|
593 |
|
594 TBuf8<32> version; |
|
595 version.Copy(PROFILER_VERSION_SHORT); |
|
596 |
|
597 // check if settings file version is |
|
598 if(tmpBuf.CompareF(version) >= 0) |
|
599 { |
|
600 // update general attributes |
|
601 UpdateSavedGeneralAttributes(iSavedLineArray); |
|
602 |
|
603 // update settings to sampler plugins and save the attributes to default array |
|
604 iSamplerHandler->UpdateSavedSamplerAttributesL(iSavedLineArray, iDefaultSamplerAttributesArray); |
|
605 } |
|
606 else |
|
607 { |
|
608 // check if settings already loaded |
|
609 if(iDefaultSamplerAttributesArray) |
|
610 { |
|
611 // reset default settings array |
|
612 iDefaultSamplerAttributesArray->Reset(); |
|
613 } |
|
614 // get the default settings if settings file version too old |
|
615 iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray); |
|
616 } |
|
617 |
|
618 return err; |
|
619 } |
|
620 |
|
621 // -------------------------------------------------------------------------------------------- |
|
622 void CProfiler::UpdateSavedGeneralAttributes(CDesC8ArrayFlat* aSavedAttributes) |
|
623 { |
|
624 // get saved general settings |
|
625 DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceOutput, iGeneralAttributes.iTraceOutput); |
|
626 DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFilePrefix, iGeneralAttributes.iTraceFilePrefix); |
|
627 DoGetValueFromSettingsArray(aSavedAttributes, KGenericTraceFileSaveDrive, iGeneralAttributes.iSaveFileDrive); |
|
628 |
|
629 } |
|
630 |
|
631 TBool CProfiler::CheckLocationSanity(RFs& fs, const TDesC8& aLocation) |
|
632 { |
|
633 TBool ret(EFalse); |
|
634 |
|
635 TBuf<32> drive; |
|
636 |
|
637 CnvUtfConverter::ConvertToUnicodeFromUtf8(drive, aLocation); |
|
638 |
|
639 // check that aLocation contains some of reasonable drives |
|
640 if(aLocation.Find(_L8("C:\\")) != KErrNotFound) |
|
641 { |
|
642 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
643 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveC)) |
|
644 ret = ETrue; |
|
645 } |
|
646 else if(aLocation.Find(_L8("D:\\")) != KErrNotFound) |
|
647 { |
|
648 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
649 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveD)) |
|
650 ret = ETrue; |
|
651 } |
|
652 else if(aLocation.Find(_L8("E:\\")) != KErrNotFound) |
|
653 { |
|
654 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
655 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveE)) |
|
656 ret = ETrue; |
|
657 } |
|
658 else if(aLocation.Find(_L8("F:\\")) != KErrNotFound) |
|
659 { |
|
660 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
661 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveF)) |
|
662 ret = ETrue; |
|
663 } |
|
664 else if(aLocation.Find(_L8("G:\\")) != KErrNotFound) |
|
665 { |
|
666 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
667 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveG)) |
|
668 ret = ETrue; |
|
669 } |
|
670 else if(aLocation.Find(_L8("H:\\")) != KErrNotFound ) |
|
671 { |
|
672 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
673 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveH)) |
|
674 ret = ETrue; |
|
675 } |
|
676 else if(aLocation.Find(_L8("I:\\")) != KErrNotFound) |
|
677 { |
|
678 if(BaflUtils::CheckFolder(fs, drive) == KErrNone && |
|
679 !SysUtil::DiskSpaceBelowCriticalLevelL(&fs, 0, EDriveI)) |
|
680 ret = ETrue; |
|
681 } |
|
682 else |
|
683 { |
|
684 // otherwise return false |
|
685 ret = EFalse; |
|
686 } |
|
687 |
|
688 return ret; |
|
689 } |
|
690 |
|
691 TInt CProfiler::HandleGeneralSettingsChange() |
|
692 { |
|
693 // local literals |
|
694 _LIT8(KBackSlash, "\\"); |
|
695 _LIT8(KTraceFileExtension, ".dat"); |
|
696 |
|
697 TBuf8<KFileNameBufSize> fileNameBuf; |
|
698 TBuf8<10> number; |
|
699 TInt result(0); |
|
700 TInt index(1); |
|
701 TInt hashLocation(0); |
|
702 TParse parse; |
|
703 |
|
704 // check if plugin writer changed |
|
705 if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0) |
|
706 { |
|
707 iWriterHandler->SetPluginActive( KDebOutWriterPluginUid, EWriterPluginEnabled ); |
|
708 } |
|
709 else |
|
710 { |
|
711 RFs fileServer; |
|
712 RFile file; |
|
713 |
|
714 // connect to the file server |
|
715 result = fileServer.Connect(); |
|
716 if(result == KErrNone) |
|
717 { |
|
718 // disk writer plugin will be activated |
|
719 iWriterHandler->SetPluginActive( KDiskWriterPluginUid, EWriterPluginEnabled ); |
|
720 |
|
721 // fix the trace data file location as well |
|
722 iTotalPrefix.Zero(); |
|
723 iTotalPrefix.Append(iGeneralAttributes.iSaveFileDrive); |
|
724 |
|
725 // check that trace file location sane |
|
726 if(!CProfiler::CheckLocationSanity(fileServer, iTotalPrefix)) |
|
727 { |
|
728 // // empty location data |
|
729 // iTotalPrefix.Zero(); |
|
730 // // use default location instead |
|
731 // iTotalPrefix.Append(KProfilerDefaultDrive); |
|
732 fileServer.Close(); |
|
733 return KErrPathNotFound; |
|
734 } |
|
735 |
|
736 // remove extra spaces |
|
737 iTotalPrefix.TrimAll(); |
|
738 |
|
739 // check if trace data location directory => string ends with '\' |
|
740 if(iTotalPrefix.LocateReverse('\\') != iTotalPrefix.Length()-1 && |
|
741 iTotalPrefix.LocateReverse('/') != iTotalPrefix.Length()-1) |
|
742 { |
|
743 // append backslash to end |
|
744 iTotalPrefix.Append(KBackSlash); |
|
745 } |
|
746 |
|
747 // append trace file name prefix e.g. PIProfiler_# |
|
748 iTotalPrefix.Append(iGeneralAttributes.iTraceFilePrefix); |
|
749 |
|
750 // locate '#' mark for finding the next free trace file name, e.g. E:\data\PIProfiler_4.dat |
|
751 hashLocation = iTotalPrefix.Locate('#'); |
|
752 if( hashLocation == KErrNotFound ) |
|
753 { |
|
754 // append simply at the end of the trace file prefix, no need to inform user |
|
755 iTotalPrefix.Append('#'); |
|
756 // get new hash mark location |
|
757 hashLocation = iTotalPrefix.Locate('#'); |
|
758 } |
|
759 |
|
760 // add the file extension |
|
761 iTotalPrefix.Append(KTraceFileExtension); |
|
762 |
|
763 // search for files with different indices |
|
764 // until a free filename is found |
|
765 while(result != KErrNotFound) |
|
766 { |
|
767 fileNameBuf.Zero(); |
|
768 // start with the original prefix |
|
769 fileNameBuf.Append(iTotalPrefix); |
|
770 // convert the number to a descriptor |
|
771 number.Num(index); |
|
772 // replace the hashmark with the real number |
|
773 fileNameBuf.Replace(hashLocation,1,number); |
|
774 |
|
775 // make a copy to the iFileNameStream descriptor |
|
776 iFileNameStream.Zero(); |
|
777 CnvUtfConverter::ConvertToUnicodeFromUtf8(iFileNameStream, fileNameBuf); |
|
778 |
|
779 LOGSTRING2("CProfiler::HandleGeneralSettingsChange() - trying to open files %S ",&iFileNameStream); |
|
780 |
|
781 if((result = parse.Set(iFileNameStream, NULL, NULL)) != KErrNone) |
|
782 { |
|
783 // break loop if fails, problems in file name => change to log into debug output |
|
784 break; |
|
785 } |
|
786 |
|
787 // create directory for trace files if not exists |
|
788 result = fileServer.MkDirAll(parse.FullName()); |
|
789 |
|
790 // check that file server responded with KErrNone or KErrAlreadyExists |
|
791 if( result != KErrNone && result != KErrAlreadyExists) |
|
792 { |
|
793 // if some other result, e.g. memory full => break |
|
794 break; |
|
795 } |
|
796 |
|
797 // attempt opening the file |
|
798 result = file.Open(fileServer,parse.FullName(),EFileShareReadersOnly); |
|
799 if(result != KErrNotFound) |
|
800 { |
|
801 if( result != KErrNotReady && |
|
802 result != KErrServerBusy ) |
|
803 { |
|
804 // close the file if it could be opened |
|
805 LOGSTRING2("Found STREAM file with index %d",index); |
|
806 index++; |
|
807 } |
|
808 else |
|
809 { |
|
810 // in boot measurements the file system might not be ready yet. |
|
811 LOGSTRING2("Problem in opening STREAM file %d",index); |
|
812 } |
|
813 file.Close(); |
|
814 } |
|
815 } // while |
|
816 } |
|
817 else |
|
818 { |
|
819 // return error code |
|
820 return result; |
|
821 } |
|
822 |
|
823 TUint32 id(iWriterHandler->GetActiveWriter()->GetWriterType()); |
|
824 |
|
825 // check if a file name is one that does not exist and selected plugin is disk writer |
|
826 if(result == KErrNotFound && id == KDiskWriterPluginUid.iUid) |
|
827 { |
|
828 // write right trace data file name to disk writer plugin |
|
829 iWriterHandler->SetPluginSettings( KDiskWriterPluginUid, iFileNameStream ); |
|
830 } |
|
831 else |
|
832 { |
|
833 // return error if could not create trace log file |
|
834 return result; |
|
835 } |
|
836 // close file server |
|
837 fileServer.Close(); |
|
838 } // if output == KOutputToDebugOutput |
|
839 return KErrNone; |
|
840 } |
|
841 |
|
842 // -------------------------------------------------------------------------------------------- |
|
843 void CProfiler::SaveSettingsL() |
|
844 { |
|
845 LOGTEXT(_L("CProfiler::SaveSettings()")); |
|
846 |
|
847 // local literal |
|
848 _LIT(KGeneralHeader, "[general]"); |
|
849 _LIT(KVersionHeader, "version"); |
|
850 _LIT8(KPIProfilerSettingsHeader, "; PI Profiler Settings File"); |
|
851 _LIT8(KGeneralSettingsHeader, "; general settings"); |
|
852 _LIT8(KOutputFileDescription,"; \"output_type=file_system\" writes *.dat file to external memory"); |
|
853 _LIT8(KOutputDebugDescription,"; \"output_type=debug_output\" writes *.dat file to debug port"); |
|
854 _LIT8(KOutputFilePrefixDescription,"; if writing to file, prefix of the *.dat file\r\n; first '#' in the prefix is replaced with an integer"); |
|
855 _LIT8(KOutputSaveDriveDescription,"; if writing to file, the location to store the *.dat file"); |
|
856 |
|
857 RFs fs; |
|
858 RFile settingsFile; |
|
859 TInt err(KErrNone); |
|
860 TBuf8<384> line; |
|
861 |
|
862 // connect to file server |
|
863 err = fs.Connect(); |
|
864 if( err != KErrNone ) |
|
865 { |
|
866 // failed to write settings to settings file |
|
867 return; |
|
868 } |
|
869 |
|
870 // create and set the private path |
|
871 fs.CreatePrivatePath(EDriveC); |
|
872 fs.SetSessionToPrivate(EDriveC); |
|
873 |
|
874 // create the new settings file |
|
875 err = settingsFile.Replace(fs, iSettingsFileLocation, EFileWrite); |
|
876 if(err != KErrNone) |
|
877 return; |
|
878 |
|
879 CleanupClosePushL(settingsFile); |
|
880 |
|
881 // write the header |
|
882 line.Copy(KPIProfilerSettingsHeader); |
|
883 line.Append(KNewLineSeparator); |
|
884 line.Append(KNewLineSeparator); |
|
885 settingsFile.Write(line); |
|
886 |
|
887 // write the header |
|
888 line.Copy(KGeneralSettingsHeader); |
|
889 line.Append(KNewLineSeparator); |
|
890 settingsFile.Write(line); |
|
891 |
|
892 // write all generic settings |
|
893 line.Copy(KGeneralHeader); |
|
894 line.Append(KNewLineSeparator); |
|
895 settingsFile.Write(line); |
|
896 |
|
897 // write version info |
|
898 line.Copy(KVersionHeader); |
|
899 line.Append(KEquals); |
|
900 line.Append(PROFILER_VERSION_SHORT); |
|
901 line.Append(KNewLineSeparator); |
|
902 settingsFile.Write(line); |
|
903 |
|
904 // output explanation |
|
905 line.Copy(KOutputFileDescription); |
|
906 line.Append(KNewLineSeparator); |
|
907 line.Append(KOutputDebugDescription); |
|
908 line.Append(KNewLineSeparator); |
|
909 settingsFile.Write(line); |
|
910 |
|
911 // write trace output |
|
912 line.Copy(KGenericTraceOutput); |
|
913 line.Append(KEquals); |
|
914 line.Append(iGeneralAttributes.iTraceOutput); |
|
915 line.Append(KNewLineSeparator); |
|
916 settingsFile.Write(line); |
|
917 |
|
918 // file prefix explanation |
|
919 line.Copy(KOutputFilePrefixDescription); |
|
920 line.Append(KNewLineSeparator); |
|
921 settingsFile.Write(line); |
|
922 |
|
923 // write trace file prefix |
|
924 line.Copy(KGenericTraceFilePrefix); |
|
925 line.Append(KEquals); |
|
926 line.Append(iGeneralAttributes.iTraceFilePrefix); |
|
927 line.Append(KNewLineSeparator); |
|
928 settingsFile.Write(line); |
|
929 |
|
930 // file prefix explanation |
|
931 line.Copy(KOutputSaveDriveDescription); |
|
932 line.Append(KNewLineSeparator); |
|
933 settingsFile.Write(line); |
|
934 |
|
935 // write trace file location |
|
936 line.Copy(KGenericTraceFileSaveDrive); |
|
937 line.Append(KEquals); |
|
938 line.Append(iGeneralAttributes.iSaveFileDrive); |
|
939 line.Append(KNewLineSeparator); |
|
940 settingsFile.Write(line); |
|
941 |
|
942 // reset the default attributes array |
|
943 iDefaultSamplerAttributesArray->Reset(); |
|
944 |
|
945 // update the latest changes from plugins |
|
946 iSamplerHandler->GetSamplerAttributesL(iDefaultSamplerAttributesArray); |
|
947 |
|
948 // call CSamplerController to write all sampler settings |
|
949 iSamplerHandler->ComposeAttributesToSettingsFileFormat(settingsFile, iDefaultSamplerAttributesArray); |
|
950 |
|
951 CleanupStack::PopAndDestroy(); //settingsFile |
|
952 // close file |
|
953 fs.Close(); |
|
954 } |
|
955 |
|
956 TInt CProfiler::CheckOldProfilerRunning() |
|
957 { |
|
958 TFindProcess procName; |
|
959 procName.Find(_L("BappeaProf.exe*")); |
|
960 TFullName aResult; |
|
961 TInt err(KErrNone); |
|
962 RProcess proc; |
|
963 |
|
964 // now check if old Profiler is still running on |
|
965 err = procName.Next(aResult); |
|
966 // check if old profiler process found |
|
967 if(err == KErrNone) |
|
968 { |
|
969 // other process found, i.e. right process to communicate with, in case started from eshell |
|
970 err = proc.Open(procName); |
|
971 if(err == KErrNone) |
|
972 { |
|
973 if(proc.ExitCategory().Length() > 0) |
|
974 { |
|
975 proc.Close(); |
|
976 // process already exited => create a new one |
|
977 return KErrNotFound; |
|
978 } |
|
979 proc.Close(); |
|
980 } |
|
981 // return error for error handling |
|
982 return KErrAlreadyExists; |
|
983 } |
|
984 return err; |
|
985 } |
|
986 |
|
987 // -------------------------------------------------------------------------------------------- |
|
988 void CProfiler::HandleError(TInt aErr) |
|
989 { |
|
990 // write error to status property to inform requester |
|
991 TInt err(iEngineStatus.Set(KEngineStatusPropertyCat, EProfilerEngineStatus, aErr)); |
|
992 if(err != KErrNone) |
|
993 RDebug::Print(_L("CProfiler::HandleError() - error setting status: %d"), err); |
|
994 } |
|
995 |
|
996 // -------------------------------------------------------------------------------------------- |
|
997 TInt CProfiler::ControlDataL(TInt aCommand,TAny* value1,TAny* /*value2*/) |
|
998 { |
|
999 LOGSTRING3("CProfiler::ControlData %d, 0x%x",aCommand,value1); |
|
1000 |
|
1001 _LIT(KDebugOutput, "debug_output"); |
|
1002 _LIT(KFileOutput, "file_system"); |
|
1003 _LIT8(KOutputToDebugOutput, "debug_output"); |
|
1004 |
|
1005 TDes* desc; |
|
1006 TPtrC ptrDesc; |
|
1007 |
|
1008 switch(aCommand) |
|
1009 { |
|
1010 // new controls |
|
1011 case RProfiler::EGetFileName: |
|
1012 { |
|
1013 LOGTEXT(_L("Profiler::EGetFileName - start")); |
|
1014 LOGSTRING2(_L("Profiler::EGetFileName - total file name is: %S"),(TDes*)value1); |
|
1015 desc = (TDes*)value1; |
|
1016 desc->Zero(); |
|
1017 desc->Append(iFileNameStream); |
|
1018 LOGSTRING2(_L("Profiler::EGetFileName - now total file name is: %S"),(TDes*)value1); |
|
1019 return KErrNone; |
|
1020 } |
|
1021 case RProfiler::EGetActiveWriter: |
|
1022 { |
|
1023 LOGTEXT(_L("Profiler::EGetActiveWriter - start")); |
|
1024 desc = (TDes*)value1; |
|
1025 desc->Zero(); |
|
1026 if(iGeneralAttributes.iTraceOutput.CompareF(KOutputToDebugOutput) == 0) |
|
1027 { |
|
1028 desc->Append(KDebugOutput); |
|
1029 } |
|
1030 else |
|
1031 { |
|
1032 desc->Append(KFileOutput); |
|
1033 } |
|
1034 return KErrNone; |
|
1035 } |
|
1036 } |
|
1037 |
|
1038 return KErrNone; |
|
1039 } |
|
1040 |
|
1041 // -------------------------------------------------------------------------------------------- |
|
1042 TInt CProfiler::ControlL(TInt aCommand) |
|
1043 { |
|
1044 LOGSTRING2("CProfiler::Control - Controlling ProfilerEngine %d",aCommand); |
|
1045 TInt err(KErrNone); |
|
1046 |
|
1047 switch (aCommand) |
|
1048 { |
|
1049 case RProfiler::EStartSampling: |
|
1050 { |
|
1051 // check first if old Profiler already running |
|
1052 err = CheckOldProfilerRunning(); |
|
1053 if(err == KErrAlreadyExists) |
|
1054 { |
|
1055 // if exists do not start a profiling process since corrupts the collected trace data |
|
1056 HandleError(err); |
|
1057 err = KErrNone; |
|
1058 return err; |
|
1059 } |
|
1060 |
|
1061 // save settings before launching the profiler |
|
1062 // reason: the profiling may have set to the background => need for get right settings |
|
1063 SaveSettingsL(); |
|
1064 |
|
1065 // set the general settings to writer plugins to reflect the latest changes |
|
1066 err = HandleGeneralSettingsChange(); |
|
1067 if(err == KErrNone) |
|
1068 { |
|
1069 // reset the buffers before new profiling |
|
1070 iUserStream->ResetBuffers(); |
|
1071 |
|
1072 // give the CProfilerSampleStream a handle to current writer |
|
1073 iUserStream->SetWriter(*iWriterHandler->GetActiveWriter()); |
|
1074 |
|
1075 // set initially debug output writer active |
|
1076 err = iWriterHandler->StartSelectedPlugin(); |
|
1077 |
|
1078 // check that writer plugin started |
|
1079 if(err != KErrNone) |
|
1080 { |
|
1081 // if not started handle error |
|
1082 HandleError(err); |
|
1083 } |
|
1084 else |
|
1085 { |
|
1086 // start activated sampler plug-in, NOTE: plugins check if errors occur in startup for some reason |
|
1087 iSamplerHandler->StartSamplerPluginsL(); |
|
1088 |
|
1089 // set engine state P&S property to running, e.g. for PIProfiler UI to read |
|
1090 iState = RProfiler::ERunning; |
|
1091 |
|
1092 // set the engine into running mode |
|
1093 iEngineStatus.Set(iState); |
|
1094 } |
|
1095 } |
|
1096 else |
|
1097 { |
|
1098 // handle error and notify requester |
|
1099 HandleError(err); |
|
1100 } |
|
1101 |
|
1102 LOGTEXT(_L("CProfiler::Control - Finished processing EStartSampling!")); |
|
1103 |
|
1104 return err; |
|
1105 } |
|
1106 case RProfiler::EStopSampling: |
|
1107 LOGTEXT(_L("CProfiler::Control - Starting to stop sampling...")); |
|
1108 // stop sampler plugins |
|
1109 if(iState == RProfiler::ERunning) |
|
1110 { |
|
1111 iState = RProfiler::EStopping; |
|
1112 iEngineStatus.Set(RProfiler::EStopping); |
|
1113 |
|
1114 iSamplerHandler->StopSamplerPlugins(); |
|
1115 |
|
1116 // finalize the filled buffer writing |
|
1117 iUserStream->Finalise(); |
|
1118 |
|
1119 // stop output plugin and write the rest of the trace data to output |
|
1120 LOGTEXT(_L("CProfiler::Control - stopping writer")); |
|
1121 iWriterHandler->StopSelectedPlugin(); |
|
1122 |
|
1123 // set engine state P&S property idle |
|
1124 iState = RProfiler::EIdle; |
|
1125 iEngineStatus.Set(RProfiler::EIdle); |
|
1126 |
|
1127 LOGSTRING2("CProfiler::Control - sampling stopped, going to state %d", RProfiler::EIdle); |
|
1128 } |
|
1129 return KErrNone; |
|
1130 |
|
1131 case RProfiler::EExitProfiler: |
|
1132 { |
|
1133 // save settings into settings file when exiting |
|
1134 SaveSettingsL(); |
|
1135 |
|
1136 if(iUserStream) |
|
1137 { |
|
1138 delete iUserStream; |
|
1139 iUserStream = NULL; |
|
1140 } |
|
1141 |
|
1142 // set engine state P&S property idle |
|
1143 iState = RProfiler::EIdle; |
|
1144 iEngineStatus.Set(RProfiler::EIdle); |
|
1145 |
|
1146 LOGTEXT(_L("Stopping Activer Scheduler")); |
|
1147 CActiveScheduler::Stop(); |
|
1148 LOGTEXT(_L("Stopped Activer Scheduler")); |
|
1149 |
|
1150 return KErrNone; |
|
1151 } |
|
1152 } |
|
1153 |
|
1154 LOGTEXT(_L("CProfiler::Control - returning")); |
|
1155 |
|
1156 return err; |
|
1157 } |
|
1158 |
|
1159 // -------------------------------------------------------------------------------------------- |
|
1160 void CProfiler::Finalise() |
|
1161 { |
|
1162 LOGTEXT(_L("CProfiler::Finalise - Finished processing EStopSampling!")); |
|
1163 } |
|
1164 |
|
1165 // -------------------------------------------------------------------------------------------- |
|
1166 RProfiler::TSamplerState CProfiler::State() const |
|
1167 { |
|
1168 return iState; |
|
1169 } |
|
1170 |
|
1171 /* |
|
1172 * |
|
1173 * Class CPServer definition |
|
1174 * |
|
1175 */ |
|
1176 // -------------------------------------------------------------------------------------------- |
|
1177 inline const CPServer& CPSession::Server() const |
|
1178 { |
|
1179 return *static_cast<const CPServer*>(CSession2::Server()); |
|
1180 } |
|
1181 |
|
1182 // -------------------------------------------------------------------------------------------- |
|
1183 void CPSession::ServiceL(const RMessage2& aMessage) |
|
1184 { |
|
1185 LOGTEXT(_L("CPSession::ServiceL - Starting to process message")); |
|
1186 TInt err(KErrNone); |
|
1187 |
|
1188 if(aMessage.Function() == RProfiler::EGetGeneralAttributes) |
|
1189 { |
|
1190 Server().GetGeneralAttributesL(aMessage); |
|
1191 } |
|
1192 else if(aMessage.Function() == RProfiler::ESetGeneralAttributes) |
|
1193 { |
|
1194 Server().SetGeneralAttributesL(aMessage); |
|
1195 } |
|
1196 else if(aMessage.Function() == RProfiler::EGetSamplerAttributes) |
|
1197 { |
|
1198 Server().GetSamplerAttributesL(aMessage); |
|
1199 } |
|
1200 else if(aMessage.Function() == RProfiler::EGetSamplerAttributeCount) |
|
1201 { |
|
1202 Server().GetSamplerAttributeCountL(aMessage); |
|
1203 } |
|
1204 else if(aMessage.Function() == RProfiler::ESetSamplerAttributes) |
|
1205 { |
|
1206 Server().SetSamplerAttributesL(aMessage); |
|
1207 } |
|
1208 else if(aMessage.Function() == RProfiler::ERefreshProfilerStatus) |
|
1209 { |
|
1210 Server().RefreshStatus(aMessage); |
|
1211 } |
|
1212 else if(aMessage.Ptr0() == 0 && aMessage.Ptr1() == 0 && aMessage.Ptr2() == 0) |
|
1213 { |
|
1214 LOGTEXT(_L("Ptr0 && Ptr1 == 0 && Ptr2 == 0")); |
|
1215 aMessage.Complete(Server().ControlL(RProfiler::TCommand(aMessage.Function()))); |
|
1216 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1217 } |
|
1218 else if(aMessage.Ptr0() != 0 && aMessage.Ptr1() != 0 && aMessage.Ptr2() != 0) |
|
1219 { |
|
1220 LOGTEXT(_L("Error with message, all pointers contain data!")); |
|
1221 } |
|
1222 |
|
1223 else if (aMessage.Ptr0() != 0) |
|
1224 { |
|
1225 if(aMessage.Ptr1() == 0) |
|
1226 { |
|
1227 LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 == 0")); |
|
1228 // provided value is a descriptor |
|
1229 TBuf<64>* dst = new TBuf<64>; |
|
1230 aMessage.ReadL(0,*dst,0); |
|
1231 |
|
1232 err = Server().ControlDataL(aMessage.Function(),(TAny*)dst); |
|
1233 delete dst; |
|
1234 aMessage.Complete(err); |
|
1235 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1236 } |
|
1237 else |
|
1238 { |
|
1239 LOGTEXT(_L("ServiceL: Ptr0 != 0 && Ptr1 != 0")); |
|
1240 // provided value is a descriptor |
|
1241 TBuf<64>* dst = new TBuf<64>; |
|
1242 aMessage.ReadL(0,*dst,0); |
|
1243 |
|
1244 TUint32 num1 = (TUint32)aMessage.Ptr1(); |
|
1245 |
|
1246 err = Server().ControlDataL(aMessage.Function(),(TAny*)dst, (TAny*)num1); |
|
1247 delete dst; |
|
1248 aMessage.Complete(err); |
|
1249 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1250 } |
|
1251 } |
|
1252 else if (aMessage.Ptr1() != 0) |
|
1253 { |
|
1254 LOGTEXT(_L("ServiceL: Ptr1 != 0")); |
|
1255 // provided value is a TUint32 |
|
1256 if( ((TUint32)aMessage.Ptr3()) == 0xffffffff) |
|
1257 { |
|
1258 TUint32 num = (TUint32)aMessage.Ptr1(); |
|
1259 err = Server().ControlDataL(aMessage.Function(),(TAny*)num); |
|
1260 aMessage.Complete(err); |
|
1261 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1262 } |
|
1263 else |
|
1264 { |
|
1265 LOGTEXT(_L("ServiceL: Ptr3 != 0xffffffff")); |
|
1266 TUint32 num1 = (TUint32)aMessage.Ptr1(); |
|
1267 TUint32 num2 = (TUint32)aMessage.Ptr3(); |
|
1268 err = Server().ControlDataL(aMessage.Function(),(TAny*)num1,(TAny*)num2); |
|
1269 aMessage.Complete(err); |
|
1270 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1271 } |
|
1272 } |
|
1273 else if (aMessage.Ptr2() != 0) |
|
1274 { |
|
1275 // command requests for data, provided |
|
1276 // value should be a descriptor |
|
1277 if( ((TUint32)aMessage.Ptr3()) == 0xffffffff) |
|
1278 { |
|
1279 LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 == 0xffffffff")); |
|
1280 |
|
1281 TBuf<256>* src = new TBuf<256>; |
|
1282 src->Zero(); |
|
1283 err = Server().ControlDataL(aMessage.Function(),(TAny*)src); |
|
1284 |
|
1285 LOGSTRING2("Got sampler data %S",src); |
|
1286 |
|
1287 aMessage.WriteL(2, *src, 0); |
|
1288 |
|
1289 delete src; |
|
1290 aMessage.Complete(err); |
|
1291 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1292 } |
|
1293 else |
|
1294 { |
|
1295 LOGTEXT(_L("ServiceL: Ptr2 != 0 && Ptr3 != 0xffffffff")); |
|
1296 |
|
1297 TUint32 num1 = (TUint32)aMessage.Ptr2(); // containing id |
|
1298 TBuf<256>* buffer = new TBuf<256>; // Text data, e.g. plug-in name or description |
|
1299 |
|
1300 LOGSTRING3("Getting data for sampler: 0x%X, buffer max len %d",num1, aMessage.GetDesMaxLength(3)); |
|
1301 |
|
1302 err = Server().ControlDataL(aMessage.Function(), (TAny*)num1, (TAny*)buffer); |
|
1303 |
|
1304 LOGSTRING2("Got sampler data %S",&buffer); |
|
1305 |
|
1306 // write back to same parameter |
|
1307 aMessage.WriteL(3, *buffer, 0); |
|
1308 aMessage.Complete(err); |
|
1309 LOGTEXT(_L("CPSession::ServiceL - Message completed")); |
|
1310 } |
|
1311 } |
|
1312 LOGTEXT(_L("CPSession::ServiceL - Message processed")); |
|
1313 } |
|
1314 |
|
1315 // -------------------------------------------------------------------------------------------- |
|
1316 MProfilerController* CPServer::NewL(TInt aPriority, MProfilerEngine& aEngine) |
|
1317 { |
|
1318 LOGTEXT(_L("CPServer::NewL - Enter")); |
|
1319 CPServer* self = new(ELeave) CPServer(aPriority, aEngine); |
|
1320 CleanupStack::PushL(self); |
|
1321 self->StartL(KProfilerName); |
|
1322 CleanupStack::Pop(); |
|
1323 LOGTEXT(_L("CPSession::NewL - Exit")); |
|
1324 return self; |
|
1325 } |
|
1326 |
|
1327 // -------------------------------------------------------------------------------------------- |
|
1328 CPServer::CPServer(TInt aPriority, MProfilerEngine& aEngine) |
|
1329 : CServer2(aPriority), MProfilerController(aEngine) |
|
1330 { |
|
1331 |
|
1332 } |
|
1333 |
|
1334 // -------------------------------------------------------------------------------------------- |
|
1335 void CPServer::Release() |
|
1336 { |
|
1337 delete this; |
|
1338 } |
|
1339 |
|
1340 // -------------------------------------------------------------------------------------------- |
|
1341 CSession2* CPServer::NewSessionL(const TVersion&,const RMessage2&) const |
|
1342 { |
|
1343 return new(ELeave) CPSession(); |
|
1344 } |
|
1345 |
|
1346 /* |
|
1347 * |
|
1348 * Static methods for controlling the profiler |
|
1349 * through command line |
|
1350 * |
|
1351 */ |
|
1352 // -------------------------------------------------------------------------------------------- |
|
1353 static void RunEngineServerL(const TDesC& aSettingsFile) |
|
1354 { |
|
1355 RDebug::Print(_L("Profiler: RunEngineServerL() - Install active scheduler")); |
|
1356 CActiveScheduler* pS = new CActiveScheduler; |
|
1357 CActiveScheduler::Install(pS); |
|
1358 CProfiler* p = CProfiler::NewLC(aSettingsFile); |
|
1359 CActiveScheduler::Start(); |
|
1360 p->Finalise(); |
|
1361 CleanupStack::PopAndDestroy(p); |
|
1362 delete pS; |
|
1363 } |
|
1364 |
|
1365 // -------------------------------------------------------------------------------------------- |
|
1366 static TInt TestSettingsFile(const TDesC& configFile) |
|
1367 { |
|
1368 RFs fs; |
|
1369 TBuf8<256> configFile8; |
|
1370 |
|
1371 // check if file server can be connected |
|
1372 if (fs.Connect() != KErrNone) |
|
1373 { |
|
1374 // file server couldn't be connected, return false |
|
1375 return KErrNotFound; |
|
1376 } |
|
1377 |
|
1378 // check if config file name length is > 0 |
|
1379 if (configFile.Length() > 0) |
|
1380 { |
|
1381 // check sanity of settings file location |
|
1382 CnvUtfConverter::ConvertFromUnicodeToUtf8(configFile8, configFile); |
|
1383 if(!CProfiler::CheckLocationSanity(fs, configFile8)) |
|
1384 { |
|
1385 fs.Close(); |
|
1386 return KErrGeneral; |
|
1387 } |
|
1388 } |
|
1389 else |
|
1390 { |
|
1391 // configFile length 0, return false |
|
1392 fs.Close(); |
|
1393 return KErrNotFound; |
|
1394 } |
|
1395 // return true if tests passed |
|
1396 fs.Close(); |
|
1397 return KErrNone; |
|
1398 } |
|
1399 |
|
1400 // -------------------------------------------------------------------------------------------- |
|
1401 GLDEF_C TInt E32Main() |
|
1402 { |
|
1403 // parse command line arguments |
|
1404 TBuf<256> c; |
|
1405 |
|
1406 // copy the full command line with arguments into a buffer |
|
1407 User::CommandLine(c); |
|
1408 |
|
1409 TBuf<256> fileName; |
|
1410 fileName.Append(c); // only one settings param should be |
|
1411 LOGSTRING2("Filename is %S", &fileName); |
|
1412 if(TestSettingsFile(fileName) != KErrNone) |
|
1413 { |
|
1414 // settings file does not exist, copy null desc to file name |
|
1415 fileName.Copy(KNullDesC); |
|
1416 } |
|
1417 |
|
1418 // if no command line arguments found just start the profiler process |
|
1419 __UHEAP_MARK; |
|
1420 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
1421 TInt ret(KErrNoMemory); |
|
1422 if( cleanup ) |
|
1423 { |
|
1424 TRAPD( ret, RunEngineServerL(fileName) ); |
|
1425 RDebug::Print(_L("Profiler: E32Main() - ret %d"), ret); |
|
1426 delete cleanup; |
|
1427 } |
|
1428 __UHEAP_MARKEND; |
|
1429 |
|
1430 return ret; |
|
1431 } |
|
1432 |
|
1433 |
|