tracesrv/tracecore/btrace_handler/src/TraceCore.cpp
changeset 56 aa2539c91954
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecore/btrace_handler/src/TraceCore.cpp	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,589 @@
+// Copyright (c) 2007-2010 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:
+//  Trace Core main instance implementation
+//
+//
+
+#include <e32def.h>
+#include <e32btrace.h>
+#include <trace_certification.h>
+
+#include "TraceCore.h"
+#include "TraceCoreSendReceive.h"
+#include "TraceCoreRouter.h"
+#include "TraceCoreDebug.h"
+#include "TraceCoreBTraceHandler.h"
+#include "TraceCorePrintfTraceHandler.h"
+#include "TraceCoreNotifier.h"
+#include "TraceCoreConfiguration.h"
+#include "TraceCoreInternalMessageHandler.h"
+#include "TraceCoreActivation.h"
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "TraceCoreTraces.h"
+#endif
+
+/**
+ * TraceCore global instance
+ */
+DTraceCore* DTraceCore::iInstance = NULL;
+
+
+/**
+ * Gets the TraceCore instance,
+ * @return DTraceCore object or NULL if TraceCore is not created yet.
+ */
+EXPORT_C DTraceCore* DTraceCore::GetInstance()
+    {
+    return iInstance;
+    }
+
+/**
+ * Returns ETrue if tracecore is loaded already EFalse otherwies
+ */
+EXPORT_C TBool DTraceCore::IsLoaded()
+    {
+    return ( iInstance != NULL );
+    }
+
+/**
+ * Gets the BTrace handler
+ */
+DTraceCoreBTraceHandler* DTraceCore::GetBTraceHandler()
+    {
+    DTraceCoreBTraceHandler* retval = NULL;
+    DTraceCore* traceCore = DTraceCore::GetInstance();
+    // BTrace handler is the first one to be registered
+    if ( traceCore != NULL && traceCore->iHandlers.Count() > 0 )
+        {
+        retval = ( DTraceCoreBTraceHandler* )traceCore->iHandlers[ 0 ];
+        }
+    return retval;
+    }
+
+/**
+ * Constructor
+ */
+DTraceCore::DTraceCore()
+: iRouter( NULL )
+, iSendReceive( NULL )
+, iNotifier( NULL )
+, iConfiguration( NULL )
+, iInternalMessageHandler( NULL )
+, iBTrace( NULL )
+, iPrintf( NULL )
+, iTraceCoreSettings( NULL )
+, iActiveWriter( NULL )
+, iActivationQ(NULL)
+, iPreviousTraceDropped(EFalse)
+, iTraceCertified(EFalse)
+    {
+    }
+
+/**
+ * Destructor
+ */
+DTraceCore::~DTraceCore()
+    {
+    // Writers and handlers are deleted first
+    //  -> They call unregister functions
+    delete iBTrace;
+    delete iPrintf;
+
+    iHandlers.Reset();
+    iWriters.Reset();
+    iActivations.Reset();
+
+    delete iRouter;
+    delete iSendReceive;
+    delete iNotifier;
+    delete iConfiguration;
+	//destroy iActivationQue
+    if (iActivationQ)
+        iActivationQ->Destroy();
+    }
+
+
+/*
+ * Init TraceCore
+ */
+TInt DTraceCore::Init()
+    {
+    TC_TRACE( ETraceLevelFlow, Kern::Printf( ">DTraceCore::Init()" ) );
+    TInt ret;
+
+    //TODO: measure how much time it takes to boot up
+    //TODO: measure how much memory is consumed by TraceCore
+   //TODO: check granularity of internal RArrays - update this for most used use case
+
+    //TODO: check dfc que (if we have any) that deals with pulling trace data from buffer
+
+   // Store the trace certified flag, used to suppress tracing on production images.
+   // This stored value is used throughout the session, even if the status of the certificate changes.
+   // This is done to avoid performance issues when performing the check with every trace outputted.
+   iTraceCertified = TraceCertification::IsTraceCertified();
+
+    //create activation/deactivation queue
+   const TInt KTCDfcThreadPriority = 24; // Kern::DfcQ0 is 27
+   //TODO: put this const to a header
+   //TODO: check if I can use constants for this (DFCQ0-1) ?
+   _LIT(KTCDfcQueue, "TraceCoreActivationDfcQ");
+   Kern::Printf("Creating TC dfc - %S...", &KTCDfcQueue);
+   ret = Kern::DynamicDfcQCreate(iActivationQ, KTCDfcThreadPriority, KTCDfcQueue);
+   Kern::Printf("returned code: %d, ptr: 0x%x", ret, iActivationQ);
+   if (ret==KErrNone)
+       //disable real-time state of the dfcq
+       iActivationQ->SetRealtimeState(ERealtimeStateOff);
+
+    // Disable Component ID filtering in BTrace
+    BTrace::SetFilter2(1);
+
+    // Create needed components
+    iRouter = new DTraceCoreRouter();
+    iSendReceive = new DTraceCoreSendReceive();
+    iNotifier = new DTraceCoreNotifier();
+    iConfiguration = new DTraceCoreConfiguration();
+    iInternalMessageHandler = new DTraceCoreInternalMessageHandler();
+
+    // Check that creating of the components was succesfull
+    if ( iRouter != NULL && iSendReceive != NULL && iNotifier != NULL && iConfiguration != NULL )
+        {
+        ret = iSendReceive->Init( *iRouter );
+        if ( ret == KErrNone )
+            {
+            ret = iRouter->Init( *iSendReceive );
+            if ( ret == KErrNone )
+                {
+                ret = iConfiguration->Init();
+                if ( ret == KErrNone )
+                    {
+                    ret = iInternalMessageHandler->Init();
+                    }
+                }
+            }
+        }
+    else
+        {
+        ret = KErrNoMemory;
+        }
+
+    // BTrace handler is integrated to TraceCore
+    if ( ret == KErrNone )
+        {
+        ret = StartBTrace();
+        }
+
+    // Printf handler is integrated to TraceCore
+    if ( ret == KErrNone )
+        {
+        ret = StartPrintfTraceHandler();
+        }
+    TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::Init() - %d", ret ) );
+
+    return ret;
+    }
+
+/**
+ * Starts the BTrace handler
+ */
+TInt DTraceCore::StartBTrace()
+    {
+    TInt ret = KErrNone;
+
+    // Create BTrace handler
+    iBTrace = new DTraceCoreBTraceHandler();
+    if ( iBTrace != NULL )
+        {
+        // Init calls RegisterHandler
+        ret = iBTrace->Init();
+        }
+    else
+        {
+        ret = KErrNoMemory;
+        }
+    TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::StartBTrace() - %d", ret ) );
+    return ret;
+    }
+
+
+/**
+ * Starts the Printf trace handler
+ */
+TInt DTraceCore::StartPrintfTraceHandler()
+    {
+    TInt ret;
+
+    // Create PrintF handler
+    iPrintf = new DTraceCorePrintfTraceHandler();
+    if ( iPrintf != NULL )
+        {
+        // Init calls RegisterHandler
+        ret = iPrintf->Init();
+        }
+    else
+        {
+        ret = KErrNoMemory;
+        }
+    TC_TRACE( ETraceLevelFlow, Kern::Printf( "<DTraceCore::StartPrintfTraceHandler() - %d", ret ) );
+    return ret;
+    }
+
+
+/**
+ * Registers an activation interface
+ */
+TInt DTraceCore::RegisterActivation( MTraceCoreActivation& aActivation )
+    {
+    return iActivations.Append( &aActivation );
+    }
+
+
+/**
+ * Gets an activation interface.
+ * Tracing from this method is not allowed.
+ */
+MTraceCoreActivation* DTraceCore::GetActivation( TUint32 aComponentId )
+    {
+    MTraceCoreActivation* retval = NULL;
+
+    // Find the correct activation interface from the list
+    for ( int i = 0; i < iActivations.Count(); i++ )
+        {
+        if ( iActivations[ i ]->IsComponentSupported( aComponentId ) )
+            {
+            retval = iActivations[ i ];
+            }
+        }
+
+    return retval;
+    }
+
+
+/**
+ * Registers a handler
+ *
+ * @param aHandler The handler
+ */
+TInt DTraceCore::RegisterHandler( DTraceCoreHandler& aHandler )
+    {
+    OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERHANDLER_ENTRY, "> DTraceCore::RegisterHandler 0x%x", ( TUint )&( aHandler ) );
+    TInt ret = iHandlers.Append( &aHandler );
+
+    // If there is not yet active writer, set the new one
+    if ( ret == KErrNone && iActiveWriter != NULL )
+        {
+        aHandler.SetWriter( iActiveWriter );
+        }
+
+    // Set settings to the handler
+    if ( ret == KErrNone && iTraceCoreSettings != NULL )
+     	{
+     	aHandler.SetSettings( iTraceCoreSettings );
+    	}
+    OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERHANDLER_EXIT, "< DTraceCore::RegisterHandler. Ret:%d", ret );
+
+    return ret;
+    }
+
+
+/**
+ * Unregisters a handler
+ *
+ * @param aHandler The handler
+ */
+void DTraceCore::UnregisterHandler( DTraceCoreHandler& aHandler )
+    {
+    // Find thiss handler from the list of handlers
+    for ( TInt i = 0; i < iHandlers.Count(); i++ )
+        {
+        if ( iHandlers[ i ] == &aHandler )
+            {
+            OstTrace1( TRACE_NORMAL, DTRACECORE_UNREGISTERHANDLER_HANDLER_REMOVED, "DTraceCore::UnregisterHandler - Handler removed 0x%x", ( TUint )&aHandler );
+            iHandlers.Remove( i );
+            i = iHandlers.Count();
+            }
+        }
+    }
+
+/**
+ * Registers the settings
+ *
+ * @param aSettings The settings saver
+ * @return KErrNone if registration successful
+ */
+TInt DTraceCore::RegisterSettings( DTraceCoreSettings& aSettings )
+    {
+    iTraceCoreSettings = &aSettings;
+    for ( TInt i = 0; i < iHandlers.Count(); i++ )
+        {
+        iHandlers[ i ]->SetSettings( iTraceCoreSettings );
+        }
+    return KErrNone;
+    }
+
+
+/**
+ * Unregisters the settings
+ *
+ * @param aSettings The settings
+ */
+void DTraceCore::UnregisterSettings( DTraceCoreSettings& aSettings )
+    {
+    if ( &aSettings == iTraceCoreSettings )
+        {
+        iTraceCoreSettings = NULL;
+
+        // Remove settings from all the handlers
+        for ( TInt i = 0; i < iHandlers.Count(); i++ )
+            {
+            iHandlers[ i ]->SetSettings( NULL );
+            }
+        }
+    }
+
+
+/**
+ * Registers a writer
+ *
+ * @param aWriter The writer
+ */
+TInt DTraceCore::RegisterWriter( DTraceCoreWriter& aWriter )
+    {
+    OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERWRITER_ENTRY, "> DTraceCore::RegisterWriter 0x%x", ( TUint )&( aWriter ) );
+
+    TInt ret = iWriters.Append( &aWriter );
+    if ( ret == KErrNone )
+        {
+        // First writer that registers is selected as the active one
+        if ( iActiveWriter == NULL )
+            {
+            iActiveWriter = &aWriter;
+            SetWriterToHandlers();
+            }
+        }
+
+    OstTrace1( TRACE_FLOW, DTRACECORE_REGISTERWRITER_EXIT, "< DTraceCore::RegisterWriter %d", ret );
+    return ret;
+    }
+
+
+/**
+ * Unregisters a writer
+ *
+ * @param aWriter The writer
+ */
+void DTraceCore::UnregisterWriter( DTraceCoreWriter& aWriter )
+    {
+    for ( TInt i = 0; i < iWriters.Count(); i++ )
+        {
+        if ( iWriters[ i ] == &aWriter )
+            {
+            OstTraceExt2( TRACE_NORMAL, DTRACECORE_UNREGISTERHANDLER_WRITER_UNREGISTERED, "DTraceCore::UnregisterWriter - Writer unregistered WriterType:%d Addr:0x%x", ( TInt )aWriter.GetWriterType(), ( TUint )&aWriter );
+            iWriters.Remove( i );
+            i = iWriters.Count();
+            // If the active writer was removed, another writer needs to be activated
+            if ( &aWriter == iActiveWriter )
+                {
+                SwitchToFirstWriter();
+                }
+            }
+        }
+    }
+
+
+/**
+ * Starts to use the first writer from the writers list
+ */
+void DTraceCore::SwitchToFirstWriter()
+    {
+    if ( iWriters.Count() > 0 )
+        {
+        iActiveWriter = iWriters[ 0 ];
+        }
+    else
+        {
+        iActiveWriter = NULL;
+        }
+    SetWriterToHandlers();
+    }
+
+
+/**
+ * Starts to use a writer of the specific type. Does nothing if the writer is already active
+ */
+EXPORT_C TInt DTraceCore::SwitchToWriter( TWriterType aWriterType )
+    {
+    OstTrace1( TRACE_FLOW, DTRACECORE_SWITCHTOWRITER_ENTRY,"> DTraceCore::SwitchToWriter WriterType:%d", ( TUint )( aWriterType ) );
+    TInt retval( KErrNone );
+
+    // Remove writer
+    if ( aWriterType == EWriterTypeNone )
+        {
+        if ( iActiveWriter != NULL )
+            {
+            iActiveWriter = NULL;
+            SetWriterToHandlers();
+            }
+        }
+    else
+        {
+        if ( iActiveWriter == NULL || iActiveWriter->GetWriterType() != aWriterType )
+            {
+            retval = KErrNotSupported;
+
+            // Find the correct writer from the list
+            for ( int i = 0; i < iWriters.Count() && retval != KErrNone; i++ )
+                {
+                DTraceCoreWriter* writer = iWriters[ i ];
+
+                // revert this
+                TWriterType wt = writer->GetWriterType();
+
+                if ( wt == aWriterType )
+                    {
+                    iActiveWriter = writer;
+                    retval = KErrNone;
+                    }
+                }
+
+            // Set writer to all handlers
+            if ( retval == KErrNone )
+                {
+                SetWriterToHandlers();
+                }
+            }
+        }
+    OstTrace1( TRACE_FLOW, DTRACECORE_SWITCHTOWRITER_EXIT, "< DTraceCore::SwitchToWriter %d", retval );
+    return retval;
+    }
+
+/**
+ * Sets the active writer to all registered handlers
+ */
+void DTraceCore::SetWriterToHandlers()
+    {
+    if ( iActiveWriter != NULL )
+        {
+        OstTraceExt2( TRACE_NORMAL, DTRACECORE_SETWRITERTOHANDLERS_WRITER_SELECTED, "DTraceCore::SetWriterToHandlers - Writer selected 0x%x WriterType:%d", (TUint) iActiveWriter, (TInt) iActiveWriter->GetWriterType() );
+        }
+
+    // PrepareSetWriter method is called with interrupts enabled
+    // SetWriter is called with interrupts disabled to prevent tracing
+    // while switching the writer
+    for ( TInt i = 0; i < iHandlers.Count(); i++ )
+        {
+        iHandlers[ i ]->PrepareSetWriter( iActiveWriter );
+        }
+    //TODO: this is not SMP safe but it's rare case - update it later
+    TInt interrupts = NKern::DisableAllInterrupts();
+    for ( TInt j = 0; j < iHandlers.Count(); j++ )
+        {
+        iHandlers[ j ]->SetWriter( iActiveWriter );
+        }
+    NKern::RestoreInterrupts( interrupts );
+    }
+
+/**
+ * Get current writer type
+ *
+ * @return Current writer type
+ */
+EXPORT_C TInt DTraceCore::GetCurrentWriterType()
+    {
+    TInt ret(0);
+    ret = iActiveWriter->GetWriterType();
+    return ret;
+    }
+
+/*
+ * Destroy the static instance of tracecore
+ */
+EXPORT_C void DTraceCore::DestroyTraceCore()
+    {
+    TC_TRACE( ETraceLevelNormal, Kern::Printf( "StopTraceCore started" ) );
+    delete DTraceCore::GetInstance();
+    DTraceCore::iInstance = NULL;
+    TC_TRACE( ETraceLevelNormal, Kern::Printf( "StopTraceCore Finished" ) );
+    }
+
+
+/**
+ * Sets the "Trace Dropped" flag
+ *
+ * @param aTraceDropped ETrue if Trace Dropped, EFalse Otherwise
+ */
+EXPORT_C void DTraceCore::SetPreviousTraceDropped(TBool aTraceDropped)
+    {
+    iPreviousTraceDropped = aTraceDropped;
+    }
+
+/**
+ * returns the state of the  "Trace Dropped" flag
+ *
+ * @param none
+ */
+EXPORT_C TBool DTraceCore::PreviousTraceDropped() const
+    {
+    return iPreviousTraceDropped;
+    }
+
+
+EXPORT_C DTraceCore* DTraceCore::CreateInstance()
+    {
+    if(iInstance == NULL)
+      {
+        DTraceCore* instance = new DTraceCore();
+        if ( instance != NULL )
+            {
+            iInstance = instance;
+            TInt ret = iInstance->Init();
+            if(ret != KErrNone)
+                {
+                delete iInstance;
+                iInstance = NULL;
+                }
+            }
+        }
+
+    return iInstance;
+    }
+
+
+EXPORT_C DTraceCoreWriter* DTraceCore::GetActiveWriter()
+    {
+    return iActiveWriter;
+    }
+
+/**
+ * Reactivate all currently activated traces
+ *
+ * @param none
+ * @return KErrNone if refresh successful
+ */
+TInt DTraceCore::RefreshActivations()
+    {
+    TInt ret = KErrNone;
+    // Go through all activation interfaces from the list
+    TInt activationsCount = iActivations.Count();
+    for ( int i = 0; i < activationsCount; i++ )
+        {
+        TInt err = iActivations[ i ]->RefreshActivations();
+        if (err != KErrNone)
+            {
+            ret = err;
+            }
+        }
+    return ret;
+    }