piprofiler/plugins/DiskWriterPlugin/src/DiskWriterPlugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 15 Sep 2010 13:53:27 +0300
branchRCL_3
changeset 49 7fdc9a71d314
parent 19 da2cedce4920
permissions -rw-r--r--
Revision: 201035 Kit: 201036

/*
* Copyright (c) 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 Files  

#include "DiskWriterPlugin.h"	// CDiskWriterPlugin
#include <e32base.h>
#include <sysutil.h>
//#include <piprofiler/EngineUIDs.h>

// constants
const TUid KDiskWriterPluginUid = { 0x2001E5BB };   // own UID

// engine properties
const TUid KEngineStatusPropertyCat={0x2001E5AD};
enum TEnginePropertyKeys
    {
    EProfilerEngineStatus = 8,
    EProfilerErrorStatus
    };

/*
 *
 *	Class CDiskWriterPlugin implementation
 *
 */

//  Member Functions
CDiskWriterPlugin* CDiskWriterPlugin::NewL(const TUid /*aImplementationUid*/, TAny* /*aInitParams*/)
    {
	LOGTEXT(_L("CDiskWriterPlugin::NewL() - entry"));
	CDiskWriterPlugin* self = new (ELeave) CDiskWriterPlugin(KDiskWriterPluginUid);
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
	LOGTEXT(_L("CDiskWriterPlugin::NewL() - exit"));
    return self;
    }

CDiskWriterPlugin::CDiskWriterPlugin(const TUid aImplementationUid) :
	iWriterType(aImplementationUid.iUid)
    {
    LOGTEXT(_L("CDiskWriterPlugin::CDiskWriterPlugin - entry"));
    isEnabled = EFalse;
    iWriterId = Id().iUid;
    LOGTEXT(_L("CDiskWriterPlugin::CDiskWriterPlugin - exit"));
    }

CDiskWriterPlugin::~CDiskWriterPlugin()
    {
    LOGTEXT(_L("CDiskWriterPlugin::~CDiskWriterPlugin - entry"));

    iErrorStatus.Close();
    
    if(iWriterHandler)
        {
        iWriterHandler->Cancel();
        delete iWriterHandler;
        }
    LOGTEXT(_L("CDiskWriterPlugin::~CDiskWriterPlugin - exit"));
    }

void CDiskWriterPlugin::ConstructL()
	{
	// second phase constructor, anything that may leave must be constructed here
	LOGTEXT(_L("CDiskWriterPlugin::ConstructL() - entry"));
	iWriterHandler = CDiskWriterHandler::NewL(this);
	User::LeaveIfError(iErrorStatus.Attach(KEngineStatusPropertyCat, EProfilerErrorStatus));
	LOGTEXT(_L("CDiskWriterPlugin::ConstructL() - exit"));
	}

TUid CDiskWriterPlugin::Id() const 
	{
    LOGSTRING2("CDiskWriterPlugin::Id():0x%X", KDiskWriterPluginUid.iUid );
    return KDiskWriterPluginUid;
	}
	 
void CDiskWriterPlugin::GetWriterVersion(TDes* aDes)
	{
	_LIT(KDiskWriterVersion, "1.0.0");
	aDes->Append(KDiskWriterVersion);
	}

TInt CDiskWriterPlugin::Start()
	{
//	if(isEnabled)
//		{
//		TRAPD(err, iWriterHandler->StartL());
//		if( err != KErrNone)
//		    {
//		    LOGTEXT(_L("Could not start writer plugin"));
//		    return err;
//		    }
//		}
	return KErrNone;
	}

void CDiskWriterPlugin::Stop()
	{
	// stop writer handler normally
	iWriterHandler->Stop();
	}

TBool CDiskWriterPlugin::GetEnabled()
	{
	return isEnabled;
	}

TUint32 CDiskWriterPlugin::GetWriterType()
	{
	return iWriterType;
	}


void CDiskWriterPlugin::SetValue( const TWriterPluginValueKeys aKey,
                                    TDes& aValue )
    {
    TRAP_IGNORE( SetValueL( aKey, aValue ) );
    }


void CDiskWriterPlugin::GetValue( const TWriterPluginValueKeys aKey,
                                    TDes& aValue )
    {
    TRAP_IGNORE( GetValueL( aKey, aValue ) );
    }

void CDiskWriterPlugin::SetValueL( const TWriterPluginValueKeys aKey, TDes& aValue )
    {
    TInt error(KErrNone);
    
    switch( aKey )
        {
        case EWriterPluginEnabled:
            isEnabled = ETrue;
        	LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - plugin enabled"));
        	break;
        case EWriterPluginDisabled:
            isEnabled = EFalse;
        	LOGTEXT(_L("CDebOutWriterPlugin::SetValueL - plugin disabled"));	
            break;
        case EWriterPluginSettings:	// file name in case of disk writer plugin
        	iFileName.Zero();
        	iFileName.Append(aValue);
        	error = iWriterHandler->TestFile(iFileName);
        		User::LeaveIfError(error);
        	break;
        default:
        	break;
        }
    }

void CDiskWriterPlugin::GetValueL( const TWriterPluginValueKeys aKey, TDes& aValue )
    {
    switch( aKey )
        {
        case EWriterPluginVersion:
        	GetWriterVersion(&aValue);
        	break;
        case EWriterPluginType:
        	break;
        case EWriterPluginSettings:	// file name in disk writer case
        	aValue.Copy(iFileName);
           default:
                break;
        }
    }

void CDiskWriterPlugin::DoCancel()
    {
	LOGTEXT(_L("CDebOutWriterPlugin::DoCancel - entry"));
    }

void CDiskWriterPlugin::WriteData()
    {
    // Activate handler to write data from buffer to output
    LOGTEXT(_L("CDiskWriterPlugin::WriteData() - entry"));
    TRAP_IGNORE(iWriterHandler->StartL());
    LOGTEXT(_L("CDiskWriterPlugin::WriteData() - exit"));
    }

void CDiskWriterPlugin::HandleError(TInt aError)
    {
    TInt err(KErrNone);
    RDebug::Print(_L("CDiskWriterPlugin::HandleError() - error received: %d"), aError);
    err = iErrorStatus.Set(aError);
    if(err != KErrNone)
        {
        RDebug::Print(_L("CDiskWriterPlugin::HandleError() - error in updating property: %d"), err);
        }
    }

/*
 * 
 * Implementation of class CDiskWriterHandler
 * 
 */

CDiskWriterHandler* CDiskWriterHandler::NewL(CDiskWriterPlugin* aWriter)
    {
	LOGTEXT(_L("CDiskWriterHandler::NewL() - entry"));
	CDiskWriterHandler* self = new (ELeave) CDiskWriterHandler(aWriter);
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
	LOGTEXT(_L("CDiskWriterHandler::NewL() - exit"));
    return self;
    }

CDiskWriterHandler::CDiskWriterHandler(CDiskWriterPlugin* aWriter)  :
    CActive(EPriorityStandard)
    {
    LOGTEXT(_L("CDiskWriterHandler::CDiskWriterHandler - entry"));

    iWriter = aWriter;
    
    // set initial mode to non-stopping
    iStopping = EFalse;
    
    // add the handler to the active scheduler
    CActiveScheduler::Add(this);
    
    LOGTEXT(_L("CDiskWriterHandler::CDiskWriterHandler - exit"));
    }


CDiskWriterHandler::~CDiskWriterHandler()
    {
	LOGTEXT(_L("CDiskWriterHandler::~CDiskWriterHandler - entry"));

	LOGTEXT(_L("CDiskWriterHandler::~CDiskWriterHandler - exit"));
    }    
    
void CDiskWriterHandler::ConstructL()
	{
	}

TInt CDiskWriterHandler::TestFile(const TDesC& totalPrefix) 
    {
    TParse parse;

    TInt err(KErrNone);
    if((err = parse.Set(totalPrefix, NULL, NULL)) != KErrNone)
        return err;

    err = iFs.Connect();
    if(err != KErrNone)
        {
        LOGTEXT(_L("CDiskWriterHandler::TestFile() - Failed to open a session to file server"));
        return KErrNotFound;
        }
    
    iFs.MkDirAll(parse.FullName());
    
    err = iFile.Replace(iFs,parse.FullName(),EFileWrite);
    if(err != KErrNone)
        {
        iFs.Close();
        return KErrNotFound;
        }
    
    iFileName.Copy(parse.FullName());

    return KErrNone;
    }

void CDiskWriterHandler::Reset()
    {
    // cancel active object
    Cancel();
    
    // start writing new buffer if there is one available
    TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer();
    
    // empty the rest of the buffers synchronously
    while(nextBuf != 0)
        {
        LOGTEXT(_L("CDiskWriterHandler::Reset - writing to file"));
        if(nextBuf->iDataSize != 0)
            {
            LOGTEXT(_L("CDiskWriterHandler::Reset - writing to file"));
            WriteMemBufferToFile(*(nextBuf->iBufDes),iStatus);
            }
        
        // empty buffers when profiling stopped
        iWriter->iStream->AddToFreeBuffers(nextBuf);

        LOGTEXT(_L("CDiskWriterHandler::Reset - get next full buffer"));
        // start writing new buffer if there is one available
        nextBuf = iWriter->iStream->GetNextFilledBuffer();
        LOGSTRING2("CDiskWriterHandler::Reset - got next filled 0x%x",nextBuf);
        }
    }

void CDiskWriterHandler::HandleFullBuffers()
    {
    LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - entry"));
    // previous write operation has finished
    // release the previous buffer 
    iWriter->iStream->AddToFreeBuffers(iBufferBeingWritten);

    LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - get next full buffer"));
    // start writing new buffer if there is one available
    TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer();

    if(nextBuf != 0)
        {
        LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - writing to file"));
        if(nextBuf->iDataSize != 0)
            {
            WriteBufferToOutput(nextBuf);
            }
        } 
    LOGTEXT(_L("CDiskWriterHandler::HandleFullBuffers - exit"));
    }

void CDiskWriterHandler::RunL()
    {
    LOGTEXT(_L("CDiskWriterHandler::RunL - entry"));
    // call function to complete full buffer handling
    HandleFullBuffers();
    LOGTEXT(_L("CDiskWriterHandler::RunL - exit"));
    }

void CDiskWriterHandler::DoCancel()
    {
    
    }

//-----------------------------------------------------------------------------
// CPIProfilerTraceCoreLauncher::RunError(TInt aError)
// Handle leaves from RunL().
//-----------------------------------------------------------------------------
TInt CDiskWriterHandler::RunError(TInt aError)
    {
    // no reason to continue if disk full or removed
    iFile.Close();
    // close handle to file server too
    iFs.Close();
    iFileName.Zero();
    
    iWriter->HandleError(KErrDiskFull);
    return aError;
    }

void CDiskWriterHandler::WriteMemBufferToFile(TDesC8& aDes, TRequestStatus& aStatus)
    {   
    LOGTEXT(_L("CDiskWriterPlugin::WriteMemBufferToFile - entry"));

    TUint sampleSize(aDes.Length());
    TInt err(KErrNone);
    TInt drive(0);
    TDriveInfo info;
    TBool noDiskSpace(EFalse);
    
    err = iFile.Drive(drive,info);

    // test available disk space 
    TRAP_IGNORE((noDiskSpace = SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, sampleSize, drive))); 
    // check first if still space on disk
    if(noDiskSpace)
        {
        // set error to disk full
        err = KErrDiskFull;
        LOGTEXT(_L("CDiskWriterPlugin::WriteMemBufferToFile - disk full, cannot write"));
        }
    else
        {
        // check if profiling in stopping mode
        if(iStopping)
            {
            // RDebug::Print(_L("CDiskWriterPlugin::WriteMemBufferToFile - data written, length %d, stopping"), aDes.Length());
            // write to file without status
            err = iFile.Write(aDes);
            }
        else
            {
            // RDebug::Print(_L("CDiskWriterPlugin::WriteMemBufferToFile - data written, length %d"), aDes.Length());
            // write to file with status
            iFile.Write(aDes,aStatus);
            }
        }
    
    // check if error in write
    if(err != KErrNone)
        {
        // stop writer handler (and its timer) immediately, DO NOT try write data!
        Cancel();
        
        // no reason to continue if disk full or removed
        // end of stream detected, file can be closed
        iFile.Close();
        // close handle to file server too
        iFs.Close();
        iFileName.Zero();
        
        // set error status for engine to read
        iWriter->HandleError(err);
        }
    LOGTEXT(_L("CDiskWriterPlugin::WriteMemBufferToFile - exit"));
    }

void CDiskWriterHandler::WriteBufferToOutput(TBapBuf* aBuf)
    {
    LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - entry"));
    iBufferBeingWritten = aBuf;

    // set the data length just to be sure
    iBufferBeingWritten->iBufDes->SetLength(aBuf->iDataSize);

    LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - writing to file"));
    WriteMemBufferToFile(*(iBufferBeingWritten->iBufDes), iStatus);

    // set AO back to active, until filled buffers are emptied 
    SetActive();
    
    LOGTEXT(_L("CDiskWriterPlugin::WriteBufferToOutput - exit"));
    }

void CDiskWriterHandler::StartL()
	{
	LOGTEXT(_L("CDiskWriterHandler::StartL - entry"));
    if(!IsActive())
        {
        LOGTEXT(_L("CDiskWriterHandler::StartL - is not active"));
    
        TBapBuf* nextBuf = iWriter->iStream->GetNextFilledBuffer();
        LOGSTRING2("CDiskWriterHandler::StartL - got next filled 0x%x",nextBuf);
    
        if(nextBuf != 0)
            {
            LOGTEXT(_L("CDiskWriterHandler::StartL - writing to file"));
            WriteBufferToOutput(nextBuf);
            }
        }
    LOGTEXT(_L("CDiskWriterHandler::StartL - exit"));
	}

void CDiskWriterHandler::Stop()
	{
	LOGTEXT(_L("CDiskWriterHandler::Stop - entry"));
	
	// set to stopping mode, needed for emptying the remaining full buffers
	iStopping = ETrue;
	
	// stop the timer
	Reset();

    // end of stream detected, file can be closed
    iFile.Close();
    // close handle to file server too
    iFs.Close();
    iFileName.Zero();
    
    // set mode back to non-stopping
    iStopping = EFalse;
    
    LOGTEXT(_L("CDiskWriterHandler::Stop - exit"));
	}

// end of file