dbgsrv/coredumpserver/plugins/formatters/utrace/src/utraceformatter.cpp
changeset 0 c6b0df440bee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgsrv/coredumpserver/plugins/formatters/utrace/src/utraceformatter.cpp	Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,383 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <d32btrace.h>
+
+#include "utraceformatter.h"
+
+
+/**
+1st stage construction
+@return pointer to the newly created object, caller takes ownership of the object.
+*/
+CUtraceFormatter* CUtraceFormatter::NewL()
+	{
+    LOG_MSG("->CUtraceFormatter::NewL()\n");
+    CUtraceFormatter* self = CUtraceFormatter::NewLC();
+	CleanupStack::Pop(self);
+    return self;
+	}
+
+/**
+1st stage construction
+@return pointer to the newly created object, caller takes ownership of the object.
+*/
+CUtraceFormatter* CUtraceFormatter::NewLC()
+	{
+    LOG_MSG("->CUtraceFormatter::NewLC()\n");
+    CUtraceFormatter* self = new(ELeave) CUtraceFormatter();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+/**
+dtor
+*/
+CUtraceFormatter::~CUtraceFormatter()
+	{
+    LOG_MSG("->~CDexcFormatter()\n");
+    iConfigList.ResetAndDestroy();
+	}
+
+/**
+2nd stage construction
+*/
+void CUtraceFormatter::ConstructL()
+	{
+	LOG_MSG("->CDexcFormatter::ConstructL()\n");
+	
+	//Configure the plugin
+	COptionConfig * config = NULL;
+	
+	iConfigList.ReserveL( (TInt) ETraceGuard );
+	
+	_LIT(KTraceSize, "How much trace data to dump? (Kb)");
+	
+	config = COptionConfig::NewL(   (TInt) ETraceSize,    
+									KUtraceFormatterUID,
+									COptionConfig::EFormatterPlugin,
+									COptionConfig::ETInt,
+									KTraceSize,
+									1,
+									KNullDesC,
+									100,
+									KNullDesC);
+	
+	TInt error = iConfigList.Append(config);
+	
+	if(error != KErrNone)
+		{
+		delete config;
+		LOG_MSG2("\tCDexcFormatter::ConstructL() - unable to store COptionConfig object in param list: %d", error);
+		}
+
+	}
+
+/**
+Called by CDS to ask for the configuration parameters that the writer needs (see Plugin Configuration) 
+@return actual number of implemented config parameters
+*/
+TInt CUtraceFormatter::GetNumberConfigParametersL()
+	{
+	TInt count = iConfigList.Count();
+	LOG_MSG2("->CUtraceFormatter::GetNumberConfigParametersL() : returns:%d\n", count );
+	return count;
+	}
+
+/**
+Called by CDS to ask for configuration parameter prompt (see Plugin Configuration) 
+
+@param aIndex indicates which parameter to return
+@return pointer to COptionConfig object representing the requested config parameter. Caller doesn't take ownership of the object!
+@leave KErrBadHandle if index is out of bounds
+@see COptionConfig
+*/
+COptionConfig* CUtraceFormatter::GetConfigParameterL(const TInt aIndex)
+	{
+	// return the config identified by aIndex
+	if( ( aIndex < 0 ) || ( aIndex >= iConfigList.Count() ) )
+		{
+		User::Leave( KErrBadHandle );
+		}
+	
+	return iConfigList[aIndex];
+	}
+
+/**
+Change a configuration parameter.
+@param aIndex Index of parameter to change
+@param aValue Unused 
+@param aDescValue Path and filename to use
+@leave KErrBadHandle if index is out of bounds or one of the other system wide error codes
+*/
+void CUtraceFormatter::SetConfigParameterL( const TInt aIndex, const TInt32 & aValue, const TDesC & aDescValue )
+	{
+	
+	if( ( aIndex < 0 ) || ( aIndex >= iConfigList.Count() ) )
+		{
+			User::Leave( KErrBadHandle );
+		}
+	
+	COptionConfig & config = *(iConfigList[aIndex]);
+
+	if( ( aIndex != (TInt)ETraceSize ) )
+		{
+			LOG_MSG( "\tLeaving : aIndex != ETraceSize " );
+			User::Leave( KErrArgument );
+		}
+	
+	//For the moment, we care not for the aDescValue
+	if(aValue > 0)
+		{
+		config.Value(aValue);
+		config.ValueL(KNullDesC);
+		}
+	
+	}
+
+/**
+Sets pointer to the writer plugin.
+Configures formatter's dump data save plugin.
+
+@param aDataSave pointer to writer plugin object.
+@leave KErrNoMemory if aDataSave is NULL 
+*/
+void CUtraceFormatter::ConfigureDataSaveL(CCrashDataSave* aDataSave)
+	{
+    LOG_MSG2("\tConfigureDataSaveL(%d)", aDataSave);
+    User::LeaveIfNull(aDataSave);
+    iDataSave = aDataSave;
+	}
+
+/**
+Sets pointer to the crash data server.
+Configures formatter's crash data source plugin.
+
+@param aDataSource pointer to core dump server object.
+@leave KErrNoMemory if aDataSource is NULL 
+*/
+void CUtraceFormatter::ConfigureDataSourceL(CCrashDataSource* aDataSource)
+	{
+    LOG_MSG2("\tConfigureDataSourceL(%d)", aDataSource);
+    User::LeaveIfNull(aDataSource);
+    iDataSource = aDataSource;
+	}
+
+void CUtraceFormatter::GetDescription(TDes& aPluginDescription)
+	{
+    LOG_MSG("\tCDexcFormatter::GetDescription()");
+	aPluginDescription.Copy(KPluginDescription());
+	}
+
+void CUtraceFormatter::CrashEventL(TCrashInfo* aCrashInfo)
+	{
+	LOG_MSG("->CUtraceFormatter::CrashEventL\n");
+	
+	User::LeaveIfNull(aCrashInfo);
+    User::LeaveIfNull(iDataSource);
+    User::LeaveIfNull(iDataSave);
+    
+    TInt traceDataToCapture = iConfigList[ (TInt)ETraceSize ]->Value();
+	if(traceDataToCapture == 0)
+		{
+		LOG_MSG("CUtraceFormatter::WriteTraceBufferL - not configured to dump trace data");
+		return;
+		}
+    
+    //update notifier
+    UpdateCrashProgressL( KUTraceCrashStart );
+    
+    iDataSave->OpenL( DumpFileNameLC(aCrashInfo->iTime ));
+    CleanupStack::PopAndDestroy(); //filename
+    
+	TUint traceAvailable = 0;	
+	TRAPD(err, traceAvailable = iDataSource->GetAvailableTraceSizeL());
+	if(err != KErrNone)
+		{
+		LOG_MSG2("Unable to get available trace size. Err = [%d] ", err);
+		User::Leave(err);
+		}
+	
+	//Write the data to the file
+	LOG_MSG2("\tWriting Trace data: iDataSave->WriteL() at Offset =0, size =%d bytes", traceAvailable);
+	TUint size = 0;
+	
+	TRAP(err, size = HelpWriteTraceBufferL(traceAvailable, traceDataToCapture * 1024, 0));
+	if(err == KErrNotSupported)
+		{
+		LOG_MSG("Unable to use data source to dump trace so reverting to the live trace framework");
+		TRAP(err, size = HelpWriteTraceBufferWithTraceFrameWorkL(traceDataToCapture * 1024, 0));
+		}
+	
+	if(err != KErrNone)
+		{
+		//This error is not fatal but worth logging
+		LOG_MSG2("Trace writing didnt succeed. Error = [%d]", err);
+		}	
+
+	LOG_MSG2("\tTrace data and info succesfully written - [%d] bytes", size);
+	
+	iDataSave->CloseL();
+	}
+
+/**
+ * This gets trace from the data source. This is for use when you dont want trace from the live system and want 
+ * the data source to decide how we obtain the trace. The data source may not support this, and leaving with
+ * KErrNotSupported will mean that you should be using the live trace system to get the data
+ * @param aTraceAvailable The amount of availbale trace data
+ * @param aTraceWanted The amount of trace data we wish to dump
+ * @param aOffset The position in the file to write the trace
+ * @see HelpWriteTraceBufferWithTraceFrameWorkL
+ */
+TUint CUtraceFormatter::HelpWriteTraceBufferL(TUint aTraceAvailable, TUint aTraceWanted, TUint aOffset)
+	{
+	LOG_MSG4("CUtraceFormatter::HelpWriteTraceBufferL aTraceAvailable = [%d] aTraceWanted = [%d] aOffset = [%d]", aTraceAvailable, aTraceWanted, aOffset);
+	
+	TUint dataReq = (aTraceAvailable >= aTraceWanted) ? aTraceWanted : aTraceAvailable;
+	TUint bufferSize = dataReq;
+	RBuf8 theTraceData;	
+	TBool bufferCreated = EFalse;
+	
+	//Try and allocate the buffer
+	while(!bufferCreated)
+		{
+		LOG_MSG2("Trying to create a buffer of size [%d] bytes", bufferSize);
+		
+		if(bufferSize == 0)
+			{
+			User::LeaveNoMemory();
+			}
+		
+		TInt err = theTraceData.Create(bufferSize);
+		if(KErrNone == err)
+			{
+			bufferCreated = ETrue;
+			theTraceData.CleanupClosePushL();
+			}
+		else
+			{
+			bufferSize = bufferSize/4;
+			}
+		}
+	
+	//Now we read the trace data bit by bit
+	TUint sizeWritten = 0;
+	while(sizeWritten < dataReq)
+		{		
+		iDataSource->ReadTraceBufferL(theTraceData, sizeWritten);
+		
+		LOG_MSG3("Writing [%d] bytes of raw trace data at [%d]", theTraceData.Size(), aOffset);
+		iDataSave->WriteL( aOffset, const_cast<TUint8*>(theTraceData.Ptr()), theTraceData.Size());
+		
+		sizeWritten += theTraceData.Length();
+		aOffset += theTraceData.Length();
+		}
+	
+	CleanupStack::PopAndDestroy(&theTraceData);
+	
+	return sizeWritten;
+	}
+
+/**
+ * Writes trace to the file using the trace framework. This is to use when you want trace from the live system.
+ * @param aTraceWanted The amount of trace data we wish to dump
+ * @param aOffset The position in the file to write the trace
+ * @see HelpWriteTraceBufferL
+ */
+TUint CUtraceFormatter::HelpWriteTraceBufferWithTraceFrameWorkL(TUint aTraceWanted, TUint aOffset)
+	{
+	LOG_MSG3("CUtraceFormatter::HelpWriteTraceBufferWithTraceFrameWorkL aTraceWanted = [%d] aOffset = [%d]", aTraceWanted, aOffset);
+    
+    RBTrace trace;
+    User::LeaveIfError(trace.Open());
+    CleanupClosePushL(trace);
+    
+    TUint8 *data = NULL;
+    TInt size = trace.GetData(data);
+    
+    if(!data)
+    	{
+    	User::Leave(KErrNotFound);
+    	}
+    
+    TUint sizeToDump = (aTraceWanted >= size) ? size : aTraceWanted;
+    
+    LOG_MSG2("Adding [%d] bytes to the file", sizeToDump);
+    iDataSave->WriteL( aOffset, data, sizeToDump);
+    
+    CleanupStack::PopAndDestroy(&trace);	
+	
+	return size;
+	}
+
+/**
+Prepares the name of the dump file. Checks DataSave filename option, if it is provided by the user
+it appends the time stamp, if not it uses default name appended with the time stamp. 
+@param aStamp lower 32 bits of the time stamp
+@return descriptor holding the final dump file name, caller is responsible to pop it from the cleanup stack
+@leave err one of system wide error codes
+ */
+const TDesC& CUtraceFormatter::DumpFileNameLC(TUint64 aStamp)
+{
+    LOG_MSG("->CUtraceFormatter::DumpFileNameLC()\n");
+    COptionConfig *option = iDataSave->GetConfigParameterL(CCrashDataSave::ECoreFilePath);
+	const TDesC &userFileName = option->ValueAsDesc();
+	HBufC *filename = HBufC::NewLC(userFileName.Length() + KUTraceDumpFileLength);
+    if(userFileName.Length() > 0)
+        {
+	    *filename = userFileName;
+        _LIT(KStampFormat, "%u");
+        filename->Des().AppendFormat(KStampFormat, I64LOW(aStamp));
+        }
+    else
+        {
+        _LIT(KTxtFileFormat, "e:\\trace%u");
+        filename->Des().Format(KTxtFileFormat, aStamp);
+        }
+    return *filename;
+}
+
+/**
+Checks the value of the crash cancel property. If set to cancel, it closes the 
+data save and then leaves with KErrAbort.
+Otherwise it updates the crash progress with the argument value.
+
+@param aProgress Progress description.
+@leave KErrAbort if crash cancel property has been set
+*/
+void CUtraceFormatter::UpdateCrashProgressL( const TDesC &aProgress )
+    {
+    
+    LOG_MSG("->CUtraceFormatter::UpdateCrashProgress()\n");
+    TInt cancelCrash;
+    _LIT(KNoProgress, "");
+    RProperty::Get( KCoreDumpServUid, ECancelCrash, cancelCrash );
+
+    if( cancelCrash )
+        {
+        RProperty::Set( KCoreDumpServUid, ECrashProgress, KNoProgress );
+
+		
+		LOG_MSG("  iDataSave->CloseL();\n");
+		iDataSave->CloseL();
+
+		LOG_MSG("  UpdateCrashProgress() -> User::Leave( KErrAbort )\n");
+        User::Leave( KErrAbort );
+        }
+
+    RProperty::Set( KCoreDumpServUid, ECrashProgress, aProgress );
+
+    }