harvester/monitorplugins/fileplugin/src/processoriginmapper.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 22:10:25 +0300
branchRCL_3
changeset 22 29d87345eaeb
parent 21 85f623e1ef41
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* 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:  Maintains a list of process ids and matching origin*
*/

#include <e32base.h>
#include <f32file.h>

#include "processoriginmapper.h"
#include "harvesterlog.h"

// File header of the location/origin -mapping file.
_LIT8( KFileHeader, "Process UID / Origin -mapping table\n"
                    "\n"
                    "UID         Origin\n" );

// Location of the process/origin -mapping file.
_LIT( KDefaultMappingFile, "C:\\private\\200009F5\\mappings.db" );
_LIT( KDefaultMappingRomFile, "Z:\\private\\200009F5\\mappings.db" );

// Maximum line length read from a file.
// Thus also size of the line buffer and length of first file header line,
// which should be file's longest line.
const TInt KMaxLineLength = 36;

// Length of all file header lines put together.
const TInt KHeaderLength = 57;


//-----------------------------------------------------------------------------
// CProcessOriginMapper::NewL()
//-----------------------------------------------------------------------------
//
CProcessOriginMapper* CProcessOriginMapper::NewL()
    {
    CProcessOriginMapper* self = new (ELeave) CProcessOriginMapper();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }
    
//-----------------------------------------------------------------------------
// CProcessOriginMapper::~CProcessOriginMapper()
// Destructor.
//-----------------------------------------------------------------------------
//
CProcessOriginMapper::~CProcessOriginMapper()
    {
    delete iLineBuffer;
    iLineBuffer = NULL;
    iProcessOriginMap.Close();
    iReadStream.Close();
    iWriteStream.Close();
    iFs.Close();
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::CProcessOriginMapper()
// Constructor.
//-----------------------------------------------------------------------------
//
CProcessOriginMapper::CProcessOriginMapper()
	: iLineBuffer( NULL ), iDefaultFileRead( EFalse )
    {
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::ConstructL()
// Second phase construction called by NewL().
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::ConstructL()
    {
    User::LeaveIfError( iFs.Connect() );
    iLineBuffer = HBufC8::NewL( KMaxLineLength + 4 );
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::RegisterProcessL()
// Add a process to the list.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::RegisterProcessL( const TUid& aProcessId,
    const TOrigin& aOrigin )
    {
    WRITELOG2( "CProcessOriginMapper::RegisterProcessL - processId: 0x%.8x, origin: %d", aProcessId.iUid, (TInt)aOrigin );
    const TInt index = FindProcess( aProcessId );
    if ( index < 0 ) // not found
        {
        TProcessOriginPair pair = { aProcessId, aOrigin };
        User::LeaveIfError( iProcessOriginMap.InsertInOrder(pair, TLinearOrder<TProcessOriginPair>(CProcessOriginMapper::Compare))); 
        }
    else if ( index < iProcessOriginMap.Count() )
        {
        iProcessOriginMap[index].iOrigin = aOrigin;
        }
    else
        {
        User::Leave( KErrUnknown );
        }
    
    if( !iDefaultFileRead )
    	{
    	WriteFileL();
    	}
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::UnregisterProcessL()
// Remove a process from the list.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::UnregisterProcessL( const TUid& aProcessId )
    {
    WRITELOG1( "CProcessOriginMapper::UnregisterProcessL - processId: 0x%.8x", aProcessId.iUid );
    const TInt index = FindProcess( aProcessId );
    if ( index >= 0 && index < iProcessOriginMap.Count() )
        {
        iProcessOriginMap.Remove( index );
        }
    else
        {
        User::Leave( KErrNotFound );
        }
    
    WriteFileL();
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::OriginL()
// Check a process from the list.
//-----------------------------------------------------------------------------
//
TOrigin CProcessOriginMapper::OriginL( const TUid& aProcessId )
    {
    WRITELOG1( "CProcessOriginMapper::OriginL - search for processId: 0x%.8x", aProcessId.iUid );
    TOrigin origin = MdeConstants::Object::EOther;
    const TInt index = FindProcess( aProcessId );
    if ( index >= 0 && index < iProcessOriginMap.Count() )
        {
        origin = iProcessOriginMap[index].iOrigin;
        }

    WRITELOG2( "CProcessOriginMapper::OriginL - processId: 0x%.8x, origin: %d", aProcessId.iUid, (TInt)origin );
    return origin;
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::ReadFileL()
// Read process id mappings from a file.
// This doesn't clear the list of currently registered mappings.
//-----------------------------------------------------------------------------
//
TInt CProcessOriginMapper::ReadFileL( const TDesC& aFile )
    {
    WRITELOG1( "CProcessOriginMapper::ReadFileL - START reading file %S", &aFile );
    if ( aFile.Length() <= 0 || aFile.Length() > KMaxFileName )
        {
        User::Leave( KErrBadName );
        }

    TInt err = iReadStream.Open( iFs, aFile, EFileRead | EFileStreamText );
    if ( err == KErrNotFound || err == KErrPathNotFound )
        {
        // if mappings file is not found, try to read from rom (Z) drive
        err = iReadStream.Open( iFs, KDefaultMappingRomFile, EFileRead | EFileStreamText );
        }
    User::LeaveIfError( err );

    // read / match file header

    const TChar KLineFeed = '\n';
    TPtr8 ptr( iLineBuffer->Des() );
    iReadStream.ReadL( ptr, KLineFeed );
    ptr.SetLength( KMaxLineLength-1 );
    TBufC8<KHeaderLength> headerBuf( KFileHeader );
    if ( headerBuf.Locate( KLineFeed ) != KMaxLineLength-1 ||
        iLineBuffer->Compare( headerBuf.Left(KMaxLineLength-1) ) != 0 )
        {
        User::Leave( KErrCorrupt );
        }
    iReadStream.ReadL( ptr, KLineFeed );  // skip the next two lines (header stuff)
    iReadStream.ReadL( ptr, KLineFeed );

    TUid processId = { 0 };
    TOrigin origin = MdeConstants::Object::EOther;

    // read and register pairs one by one
    // for-loop limits the maximum amount of loops
    TInt count = 0;
    for ( count = 0; count < KMaxMappingSize; count++ )  
        {
        TRAP( err, ReadProcessOriginPairL( processId, origin ) );
        if ( err == KErrEof )
            {
            // successful exit
            break;
            }
        else if ( err != KErrNone )
            {
            User::Leave( KErrCorrupt );
            }
        RegisterProcessL( processId, origin );
        }

    iReadStream.Release();
    WRITELOG2( "CProcessOriginMapper::ReadFileL - END reading file %S, count %d", &aFile, count );
    return count;
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::ReadFileL()
// Read process id mappings from the default file.
//-----------------------------------------------------------------------------
//
TInt CProcessOriginMapper::ReadFileL()
    {
    WRITELOG( "CProcessOriginMapper::ReadFileL - reading default file" );
    iDefaultFileRead = ETrue;
    const TInt count = ReadFileL( KDefaultMappingFile );
    iDefaultFileRead = EFalse;
    return count;
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::WriteFileL()
// Writes process id mappings to a file.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::WriteFileL( const TDesC& aFile )
    {
    WRITELOG1( "CProcessOriginMapper::WriteFileL - writing file %S", &aFile );
    if ( aFile.Length() <= 0 || aFile.Length() > KMaxFileName )
        {
        User::Leave( KErrBadName );
        }

    TInt err = iWriteStream.Replace( iFs, aFile,
            EFileWrite | EFileShareExclusive | EFileStreamText );
    User::LeaveIfError( err );
    CleanupClosePushL( iWriteStream );
    
    // write file header
    
    iWriteStream.WriteL( KFileHeader );
    
    TUid processId = { 0 };
    TOrigin origin = MdeConstants::Object::EOther;

    // write pairs one by one
    // for-loop limits the maximum amount of loops
    const TInt count = iProcessOriginMap.Count();
    for ( TInt i( 0 ); i < count; i++ )
        {
        processId = iProcessOriginMap[i].iProcessId;
        origin = iProcessOriginMap[i].iOrigin;
        TRAP( err, WriteProcessOriginPairL( processId, origin ) );
        if ( err != KErrNone )
            {
            User::Leave( KErrCorrupt );
            }
        }
    
    iWriteStream.CommitL();
    iWriteStream.Release();

    CleanupStack::PopAndDestroy( &iWriteStream );
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::WriteFileL()
// Write process id mappings to the default file.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::WriteFileL()
    {
    WRITELOG( "CProcessOriginMapper::WriteFileL - writing default file..." );
    WriteFileL( KDefaultMappingFile );
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::Clear()
// Clear mapping table in memory.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::Clear()
    {
    WRITELOG( "CProcessOriginMapper::Clear - clearing origin map db" );
    iProcessOriginMap.Reset();
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::Count()
// Return the count of currently registered mappings.
//-----------------------------------------------------------------------------
//
TInt CProcessOriginMapper::Count()
    {
    return iProcessOriginMap.Count();
    }


// PRIVATE METHODS

//-----------------------------------------------------------------------------
// CProcessOriginMapper::FindProcess()
// Find index by process id.
//-----------------------------------------------------------------------------
//
TInt CProcessOriginMapper::FindProcess( const TUid& aProcessId )
    {
    TInt low( 0 );
    TInt high( iProcessOriginMap.Count() );
    
    while( low < high )
        {
        TInt mid( (low+high)>>1 );
        
        const TInt compare( aProcessId.iUid - iProcessOriginMap[mid].iProcessId.iUid );
        if( compare == 0 )
            {
            return mid;
            }
        else if( compare > 0 )
            {
            low = mid + 1;
            }
        else
            {
            high = mid;
            }
        }

    return KErrNotFound;
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::ReadProcessOriginPairL()
// Read one related process/origin pair from a text file.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::ReadProcessOriginPairL( TUid& aProcessId,
    TOrigin& aOrigin )
    {    
    const TUint32 KMinTestRangeId = 0xE0000000;
    const TUint32 KMaxTestRangeId = 0xEFFFFFFF; 
    
    const TUint32 KMaxProcessId = 0xFFFFFFFF;
    const TChar KLineFeed = '\n';

    // read a line

    TPtr8 ptr( iLineBuffer->Des() );
    iReadStream.ReadL( ptr, KLineFeed );

    TUint32 tempId = 0;
    TInt16 tempOrigin = 0;
    
    // parse process id

    TLex8 parser( ptr );
    TInt err = parser.Val( tempId, EHex );
    if ( err == KErrGeneral )
        {
        User::Leave( KErrEof );
        }
    else if ( err != KErrNone ) 
        {
        User::Leave( err ); // might be KErrOverflow
        }

    // parse origin

    parser.SkipSpace();
    err = parser.Val( tempOrigin );
    if ( err == KErrGeneral )
        {
        User::Leave( KErrCorrupt );
        }
    else if ( err != KErrNone ) 
        {
        User::Leave( err ); // might be KErrOverflow
        }

    if ( tempOrigin < 0 )
        {
        User::Leave( KErrCorrupt );
        }
    if ( tempId >= KMinTestRangeId && 
         tempId <= KMaxTestRangeId )
        {
        User::Leave( KErrCorrupt );
        }
    else if( tempId > KMaxProcessId )
        {
        User::Leave( KErrCorrupt );
        }

    // set results
    
    aProcessId = TUid::Uid( tempId );
    aOrigin = TOrigin( tempOrigin );
    }

//-----------------------------------------------------------------------------
// CProcessOriginMapper::WriteProcessOriginPairL()
// Write one related process/origin pair to a file.
//-----------------------------------------------------------------------------
//
void CProcessOriginMapper::WriteProcessOriginPairL( TUid& aProcessId,
    TOrigin& aOrigin )
    {
    _LIT8( KDelimiter, "\t" );
    _LIT8( KLineFeed, "\n" );
    TPtr8 ptr( iLineBuffer->Des() );
    ptr.Num( aProcessId.iUid );
    iWriteStream.WriteL( ptr );
    iWriteStream.WriteL( KDelimiter );
    ptr.Num( aOrigin );
    iWriteStream.WriteL( ptr );
    iWriteStream.WriteL( KLineFeed );
    }

TInt CProcessOriginMapper::Compare(const TProcessOriginPair& aFirst, const TProcessOriginPair& aSecond)
    {
    return aFirst.iProcessId.iUid - aSecond.iProcessId.iUid;
    }