mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbcommon/src/mpxdbmanager.cpp
branchRCL_3
changeset 53 3de6c4cf6b67
child 56 2cbbefa9af78
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbcommon/src/mpxdbmanager.cpp	Wed Sep 01 12:32:02 2010 +0100
@@ -0,0 +1,3092 @@
+/*
+* Copyright (c) 2007 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:  This class is responsible for managing all database access
+*                databases.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include <sqldb.h>
+#include <badesca.h>
+#include <f32file.h>
+// PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed
+//#ifdef __WINSCW__    
+//#include <sqlrowsetutil.h>
+//#endif
+#include <sysutil.h>
+#ifdef __RAMDISK_PERF_ENABLE
+#include <centralrepository.h>
+#include <bautils.h>  
+#include <mpxinternalcrkeys.h>
+#endif //__RAMDISK_PERF_ENABLE
+
+#include <mpxlog.h>
+
+#include "mpxdbcommondef.h"
+#include "mpxtable.h"
+#include "mpxdbmanager.h"
+
+// CONSTANTS
+
+// Version of   Database
+const   TInt KMPXDbVersion[] = {6,0,0};
+
+_LIT8( KMCSqlConfig, "cache_size=1024; page_size=16384; " );
+
+_LIT(KSecureFilePath,   "%S[%x]%S");
+_LIT(KRootDrive, "C:");
+_LIT(KAliasName, "%1SDrive");
+_LIT(KBeginTransaction, "BEGIN TRANSACTION");
+_LIT(KCommitTransaction, "COMMIT TRANSACTION");
+_LIT(KRollbackTransaction, "ROLLBACK TRANSACTION");
+_LIT(KOrderByToken, "ORDER BY");
+_LIT(KDBNameToken, ":dbname");
+_LIT(KPlDBNameToken, ":pldbname");
+_LIT(KUnionAllToken, " UNION ALL ");
+_LIT(KSelectToken, "SELECT");
+
+//for database deletion
+_LIT( KDBFilePath, "\\private\\10281e17\\" );
+_LIT( KDBFilePattern, "*.db*" );    
+
+#ifdef _DEBUG
+_LIT(KTableQuery, "SELECT * FROM %S");
+_LIT(KAttachedTableQuery, "SELECT * FROM :dbname.%S");
+_LIT(KFindAllCDriveTablesQuery, "SELECT name FROM   sqlite_master WHERE type = 'table' ORDER BY name");
+_LIT(KFindAllAttachedTablesQuery, "SELECT name FROM :dbname.sqlite_master WHERE type = 'table' ORDER BY name");
+_LIT(KNameColumn, "name");
+#endif
+
+const TInt KMaxLogQuery = 248;
+const TInt KBufIncrement = 10;
+
+#ifdef __RAMDISK_PERF_ENABLE
+_LIT(KSecurePath,   "[%x]%S");
+_LIT(KRAMAliasName, "%S");
+_LIT( KDummyDbFile, "%c:\\private\\10281e17\\dummydb.dat" );
+const TInt64 KMPMegaByte = 1048576;
+const TInt64 KMPEstimatedSongInBytes = KMPMegaByte * 2; 
+const TInt KMPEstimatedSizePerDBEntry = 3000; // worst scenario, can be lower if needed
+const TInt KMPMinimumRAMSizeToRun = 6 * KMPMegaByte; 
+// if RAM is lower than 5MB, doesn't seem enough for SQL as well.
+// so we set this number to move back DBs before being kicked out
+
+#endif //__RAMDISK_PERF_ENABLE
+
+// Used to suppress overflow when appending formatted text to a buffer.
+class TOverflowHandle :
+    public TDesOverflow
+    {
+    public:
+        TOverflowHandle() :
+            iFlag(EFalse)
+            {
+            }
+
+        virtual void Overflow(TDes& /* aDes */)
+            {
+            iFlag = ETrue;
+            return;
+            }
+
+        TBool GetOverflowFlag()
+            {
+            TBool flag(iFlag);
+            iFlag = EFalse;
+            return flag;
+            }
+    protected:
+        TBool iFlag;
+    };
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Constructor
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXDbManager::CMPXDbManager(
+    RFs& aFs) :
+    iFs(aFs), 
+    iRAMDiskPerfEnabled(EFalse),
+    iMaximumAllowedRAMDiskSpaceToCopy(0),
+    iRAMInUse(EFalse)
+    {
+    MPX_FUNC("CMPXDbManager::CMPXDbManager");
+    }
+
+// ----------------------------------------------------------------------------
+// Second phase constructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::ConstructL(
+    const TFileName& aDatabaseFile)
+    {
+    MPX_FUNC("CMPXDbManager::ConstructL");
+    iDbFile = aDatabaseFile.AllocL();
+    
+#ifdef __RAMDISK_PERF_ENABLE
+    TInt flags( 0 );
+    CRepository* repository = CRepository::NewLC( KCRUidMPXMPFeatures );
+    User::LeaveIfError( repository->Get( KMPXMPLocalVariation, flags ));
+    MPX_DEBUG2("CMPXDbManager::ConstructL KMPXMPLocalVariation %d", flags);        
+    iRAMDiskPerfEnabled = static_cast<TBool>( flags & KMPXEnableRAMDisk );
+    
+    TInt temp;
+    User::LeaveIfError( repository->Get( KMAXAllowedDiskSpaceToCopy, temp) );
+    iMaximumAllowedRAMDiskSpaceToCopy = temp * KMPMegaByte;
+    CleanupStack::PopAndDestroy(repository);
+            
+    if ( iRAMDiskPerfEnabled )
+        {
+        MPX_DEBUG1("CMPXDbManager::ConstructL RAMDisk performance is enabled.");
+        MPX_DEBUG2("CMPXDbManager::ConstructL RAMDisk iMaximumAllowedRAMDiskSpaceToCopy=%Lu", iMaximumAllowedRAMDiskSpaceToCopy);
+        if ( GetRAMDiskPath() != KErrNone )
+            {
+            // Error finding ram drive, disable ram disk
+            iRAMDiskPerfEnabled = EFalse;
+            }
+        }
+    else
+        {
+        MPX_DEBUG2("CMPXDbManager::ConstructL RAMDisk performance is NOT enabled flag=%d", flags);
+        MPX_DEBUG2("CMPXDbManager::ConstructL RAMDisk iMaximumAllowedRAMDiskSpaceToCopy=%Lu", iMaximumAllowedRAMDiskSpaceToCopy);
+        }
+#endif //__RAMDISK_PERF_ENABLE
+    }
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXDbManager::~CMPXDbManager()
+    {
+    MPX_FUNC("CMPXDbManager::~CMPXDbManager");
+
+    // Close the state array
+    iPreparedStatements.Close();
+
+    // Close and destroy all RSQLStatements
+    TInt c( iStatements.Count() );
+    for( TInt i=0; i<c; ++i )
+        {
+        iStatements[i]->Close();
+        }
+    iStatements.ResetAndDestroy();
+
+    iTables.Close();
+    CloseAllDatabases();
+
+    delete iDbFile;
+    iDatabaseHandles.Close();
+    }
+
+// ----------------------------------------------------------------------------
+// Checks if all databases have been initialized.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXDbManager::IsInitialized()
+    {
+    MPX_FUNC("CMPXDbManager::IsInitialized");
+    return iInitialized;
+    }
+
+// ----------------------------------------------------------------------------
+// Begins a transaction on all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::BeginL()
+    {
+    MPX_FUNC("CMPXDbManager::BeginL");
+
+    ASSERT(iTransactionCount >= 0);
+
+    if (++iTransactionCount == 1)
+        {
+        DoBeginL();
+        }
+    }
+
+void CMPXDbManager::DoBeginL()
+    {
+    MPX_FUNC("CMPXDbManager::DoBeginL");
+
+    TInt err = iDatabase.Exec(KBeginTransaction);
+        
+    // transforms SQL error to KErrNotReady
+    if( (err <= KSqlErrGeneral && err >= KSqlErrNotDb) || err == KSqlErrStmtExpired )
+        {
+        User::Leave(KErrNotReady);
+        }
+    else
+        {
+        User::LeaveIfError(err);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Copy all DBs to RAM disk
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CopyDBsToRamL( TBool aIsMTPInUse )
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::CopyDBsToRamL");
+    if( iRAMDiskPerfEnabled )
+        {
+        if ( !IsRamDiskSpaceAvailable() )
+            {
+            return;
+            }
+        
+        // Check if we are over the allowed ram space.
+        TInt dbSize=0;
+        TInt err = GetTotalDatabasesSize(dbSize);
+        if ( err || (dbSize > iMaximumAllowedRAMDiskSpaceToCopy) )
+            {
+            MPX_DEBUG2("<--CMPXDbManager::CopyDBsToRamL Over the allowed Ram disk limit %Lu", iMaximumAllowedRAMDiskSpaceToCopy );
+            return;
+            }
+        
+        TInt transactionCount = iTransactionCount;
+        if (iTransactionCount > 0) 
+            {
+            iTransactionCount = 0;
+            DoCommitL();
+            }
+
+        TInt count(iDatabaseHandles.Count());
+        for ( TInt i = 0; i < count ; ++i )
+            {
+            if ( ! iDatabaseHandles[i].iOpen )
+                {
+                MPX_DEBUG1("CMPXDbManager::CopyDBsToRamL DB not open (assuming drive is not present)");
+                continue;
+                }
+            if ( iDatabaseHandles[i].iUseRAMdb )
+                {
+                // already used
+                MPX_DEBUG1("CMPXDbManager::CopyDBsToRamL iUseRAMdb already ETrue");
+                continue;
+                }
+            CloseDatabaseAtIndexL( i ); // let leave: not much we can do if we can't close the original DB
+            DoCopyDBToRam( i, aIsMTPInUse ); // copies if it can
+            TRAPD( err, OpenDatabaseAtIndexL( i ) );
+            if ( err != KErrNone )
+                {
+                MPX_DEBUG2("CMPXDbManager::CopyDBsToRamL OpenDatabaseAtIndexL leave=%d", err);
+                RemoveDummyFile(i);
+                if ( iDatabaseHandles[i].iUseRAMdb ) 
+                    {
+                    // go back to disk DB
+                    TRAP_IGNORE(CloseDatabaseAtIndexL( i ));
+                    iDatabaseHandles[i].iUseRAMdb = EFalse;
+                    OpenDatabaseAtIndexL( i );
+                    continue;
+                    }
+                else
+                    {
+                    User::Leave( err );
+                    }
+                }
+            }
+            
+        if (transactionCount > 0) 
+            {
+            DoBeginL();
+            iTransactionCount = transactionCount;
+            }
+        }
+    iRAMInUse = ETrue;
+	
+    MPX_DEBUG1("<--CMPXDbManager::CopyDBsToRamL");
+#endif //__RAMDISK_PERF_ENABLE
+
+    }
+
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::DoCopyDBToRam
+// ----------------------------------------------------------------------------
+//
+TBool CMPXDbManager::DoCopyDBToRam( TInt aIndex, TBool aIsMTPInUse )
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG2("-->CMPXDbManager::DoCopyDBsToRam drive=%d", (TInt)iDatabaseHandles[aIndex].iDrive);
+    DatabaseHandle& database = iDatabaseHandles[aIndex];
+    TInt err = KErrNone;
+
+    delete database.iOrigFullFilePath;
+    database.iOrigFullFilePath = 0;
+    delete database.iTargetFullFilePath;
+    database.iTargetFullFilePath = 0;
+    TRAP (err, 
+	      database.iOrigFullFilePath = CreateFullFilenameL( database.iDrive );
+          database.iUseRAMdb = ETrue; // must turn this on to create RAM filename
+          database.iTargetFullFilePath = CreateFullFilenameL( database.iDrive );
+          BaflUtils::EnsurePathExistsL( iFs, *database.iTargetFullFilePath ));
+    database.iUseRAMdb = EFalse;
+    if (err != KErrNone)
+        {
+        MPX_DEBUG1("CMPXDbManager::DoCopyDBsToRamL() CreateFilenameL or EnsurePathExistsL failed");
+        return EFalse;
+        }
+    MPX_DEBUG2("RAMDisk src path=%S", database.iOrigFullFilePath);
+    MPX_DEBUG2("RAMDisk dst path=%S", database.iTargetFullFilePath);
+
+    if (!BlockDiskSpace( aIndex, aIsMTPInUse ) )
+        {
+        MPX_DEBUG1("CMPXDbManager::DoCopyDBsToRamL() BlockDiskSpace failed");
+        return EFalse; // continue for next drive
+        }
+
+    if ( BaflUtils::CopyFile(iFs, *database.iOrigFullFilePath, *database.iTargetFullFilePath ) != KErrNone )
+        {
+        RemoveDummyFile( aIndex );
+        return EFalse;
+        }
+    MPX_DEBUG2("RAMDisk Database copied=%d", (TInt)database.iDrive);
+    database.iUseRAMdb = ETrue; // succeeded moving DB to RAM
+    MPX_DEBUG1("<--CMPXDbManager::DoCopyDBsToRamL");
+    return ETrue;
+#else
+    return EFalse;
+#endif //__RAMDISK_PERF_ENABLE
+    }
+
+// ----------------------------------------------------------------------------
+// Copy all DBs from RAM disk back to normal drives
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CopyDBsFromRamL()
+    {
+    MPX_FUNC("CMPXDbManager::CopyDBsFromRamL");
+#ifdef __RAMDISK_PERF_ENABLE
+    if( iRAMDiskPerfEnabled )
+       {
+        TInt transactionCount = iTransactionCount;
+        if (iTransactionCount > 0) 
+            {
+            iTransactionCount = 0;
+            TRAP_IGNORE( DoCommitL() );
+            }
+
+        TInt count(iDatabaseHandles.Count());
+        TInt leaveError = KErrNone;
+        iRAMInUse = EFalse;
+        // Should not leave until all the databases have been copied from RAM drive. 
+        for (TInt i = 0; i < count; ++i)
+            {
+            if ( !iDatabaseHandles[i].iUseRAMdb )
+                {
+                continue;
+                }
+            TRAPD( error, CloseDatabaseAtIndexL( i ) );
+            if ( error )
+                {
+                // Can't close db on RAM drive, so cleanup.
+                MPX_DEBUG2("CMPXDbManager::CopyDBsFromRamL CloseDatabaseAtIndexL fail: error = %d", error);
+                // Delete database on RAM drive.
+                BaflUtils::DeleteFile(iFs, *iDatabaseHandles[i].iTargetFullFilePath);
+                // Delete dummy file
+                RemoveDummyFile(i);
+                }
+            else
+                {
+                DoCopyDBFromRam(i);
+                }
+            iDatabaseHandles[i].iUseRAMdb = EFalse;
+            // open db from drive
+            TRAP( error, OpenDatabaseAtIndexL( i ) );      
+            if ( error && !leaveError )
+                {
+                leaveError = error;
+                }
+            }
+        
+        // leave if error
+        User::LeaveIfError(leaveError);
+
+        if (transactionCount > 0) 
+            {
+            DoBeginL();
+            iTransactionCount = transactionCount;
+            }
+        }
+#endif //__RAMDISK_PERF_ENABLE
+    }
+
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::DoCopyDBsToRam
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::DoCopyDBFromRam( TInt aIndex )
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::DoCopyDBsFromRam");    
+    DatabaseHandle& database = iDatabaseHandles[aIndex];
+
+    //Copy Db from RAM to replace dummy file
+    TRAPD(error, ReplaceFileL( *database.iTargetFullFilePath, database.iDummyFilePath));
+    MPX_DEBUG2("CMPXDbManager::CopyDBsFromRam RAMDisk copied over dummy, error=%d", error);
+
+    // done with RAM DB (whether copying succeeded or not) so can delete it
+    // can ignore errors since we cannot do anything if this fails
+    BaflUtils::DeleteFile(iFs, *database.iTargetFullFilePath);
+    MPX_DEBUG1("CMPXDbManager::DoCopyDBsFromRam RAM DB deleted");
+        
+    if ( error == KErrNone )
+        {
+        // Delete old DB on drive
+        // Can ignore error: either original does not exist or something is wrong and can't help it
+        BaflUtils::DeleteFile(iFs, *database.iOrigFullFilePath);
+        MPX_DEBUG1("CMPXDbManager::DoCopyDBsFromRam old DB on drive deleted");
+
+        // Rename dummy file to be original file name
+        error = BaflUtils::RenameFile(iFs, database.iDummyFilePath, *database.iOrigFullFilePath);
+        MPX_DEBUG2("CMPXDbManager::CopyDBsFromRam dummy file renamed, error=%d", error);
+        if ( error )
+            {
+            // Error renaming dummy file, delete dummy file.
+            RemoveDummyFile(aIndex);
+            }
+        }
+    else
+        {
+        RemoveDummyFile(aIndex);
+        MPX_DEBUG1("CMPXDbManager::DoCopyDBsFromRam dummy file deleted");
+        }
+
+    MPX_DEBUG1("<--CMPXDbManager::DoCopyDBsFromRam");
+#endif //__RAMDISK_PERF_ENABLE
+    } 
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ReplaceFileL
+//
+// Replaces a file with another writing over the destination file.
+// Leaves on error.
+// Implementation follows CFileMan::Copy except that 
+//  - we don't resize target file to zero
+//  - we can assume that source file already exists
+//  - we don't copy file attributes & timestamp
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::ReplaceFileL( const TDesC& aSrcName, const TDesC& aDstName )
+    {
+    // open files
+    RFile srcFile;
+    User::LeaveIfError( srcFile.Open(iFs, aSrcName, EFileRead|EFileShareReadersOnly) );
+    CleanupClosePushL( srcFile );
+    
+    RFile dstFile;
+	TInt error = dstFile.Open(iFs, aDstName, EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
+	if (error == KErrNotFound)
+	   {
+	   error = dstFile.Create(iFs, aDstName, EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
+	   }
+	User::LeaveIfError ( error );
+    CleanupClosePushL( dstFile );
+    
+    // resize destination file
+    TInt remainingBytes;
+    User::LeaveIfError( srcFile.Size(remainingBytes) );
+    User::LeaveIfError( dstFile.SetSize(remainingBytes) );
+
+    // allocate buffer
+   	const TInt KBigBufSize = 512 * 1024;
+    const TInt KMediumBufSize = 32 * 1024;
+    const TInt KSmallBufSize = 4 * 1024;
+    HBufC8* bufPtr=HBufC8::New( Min(KBigBufSize, remainingBytes) );
+    if (bufPtr==NULL)
+        bufPtr=HBufC8::New(KMediumBufSize);
+    if (bufPtr==NULL)
+        bufPtr=HBufC8::New(KSmallBufSize);
+    if (bufPtr == NULL)
+        User::Leave(KErrNoMemory);
+    CleanupStack::PushL(bufPtr);
+
+    // copy
+    TPtr8 copyBuf=bufPtr->Des();
+    TInt pos=0;
+    while( remainingBytes > 0 )
+        {
+        TInt s = Min( remainingBytes, copyBuf.MaxSize() );
+        TInt ret = srcFile.Read(pos, copyBuf, s);
+        if (ret == KErrNone && copyBuf.Length()!= s )
+            {
+            ret = KErrCorrupt;
+            }
+        if (ret == KErrNone)
+            {
+            ret = dstFile.Write(pos, copyBuf, s);
+            }
+        User::LeaveIfError (ret);
+        pos += s;
+        remainingBytes -= s;
+        }
+    User::LeaveIfError( dstFile.Flush() );
+    CleanupStack::PopAndDestroy(3); // bufPtr, dstFile, srcFile
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::RemoveDummyFile
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::RemoveDummyFile( TInt index )
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::RemoveDummyFile");
+       
+    if ( iDatabaseHandles[index].iDummyFilePath.Length() )
+        {
+        BaflUtils::DeleteFile(iFs, iDatabaseHandles[index].iDummyFilePath);
+        iDatabaseHandles[index].iDummyFilePath.Zero();
+        }
+    MPX_DEBUG1("<--CMPXDbManager::RemoveDummyFile");
+#endif //__RAMDISK_PERF_ENABLE
+
+    }
+
+
+// ----------------------------------------------------------------------------
+// Commits a transaction on all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CommitL()
+    {
+    MPX_FUNC("CMPXDbManager::CommitL");
+
+    if(iTransactionCount > 0)
+        {
+        if (--iTransactionCount == 0)
+            {
+            DoCommitL();
+            }
+        }
+    }
+    
+// ----------------------------------------------------------------------------
+// Commits a transaction on all databases.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::DoCommitL()
+    {
+    MPX_FUNC("CMPXDbManager::DoCommitL");
+    TInt err = iDatabase.Exec(KCommitTransaction);
+    
+    // transforms SQL error to KErrNotReady
+    if( (err <= KSqlErrGeneral && err >= KSqlErrNotDb) || err == KSqlErrStmtExpired )
+        {
+        MPX_DEBUG2("CMPXDbManager::CommitL failed err=%d", err);
+        User::Leave(KErrNotReady);
+        }
+    else
+        {
+        User::LeaveIfError(err);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Rolls back a transaction on all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::RollbackL()
+    {
+    MPX_FUNC("CMPXDbManager::RollbackL");
+
+    if(iTransactionCount > 0)
+        {
+        if (--iTransactionCount == 0)
+            {
+            TInt err = iDatabase.Exec(KRollbackTransaction);
+            
+            // transforms SQL error to KErrNotReady
+            if( (err <= KSqlErrGeneral && err >= KSqlErrNotDb) || err == KSqlErrStmtExpired )
+                {
+                User::Leave(KErrNotReady);  
+                }
+            else
+                {
+                User::LeaveIfError(err);
+                }
+            }
+    	}
+    }
+
+// ----------------------------------------------------------------------------
+// Rolls back a transaction on all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXDbManager::InTransaction()
+    {
+    MPX_FUNC("CMPXDbManager::InTransaction");
+    return iDatabase.InTransaction();
+    }
+
+// ----------------------------------------------------------------------------
+// Tries to create and open the databases on all specified drives.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::InitDatabasesL(
+    RArray<TInt> aDrives)
+    {
+    MPX_FUNC("CMPXDbManager::InitDatabasesL");
+
+    CloseAllDatabases();
+
+    TDriveUnit cdrive(KRootDrive());
+
+    CreateDatabaseL(cdrive);
+    OpenRootDatabaseL();
+
+    TInt count(aDrives.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        TDriveUnit drive(aDrives[i]);
+        if ((drive != cdrive) && !IsRemoteDrive(static_cast<TDriveNumber>(aDrives[i])))
+            {
+            const TDesC& driveName = drive.Name();
+
+            DatabaseHandle handle;
+
+            handle.iDrive = aDrives[i];
+            handle.iAliasname = HBufC::NewL(KAliasName().Length());
+            handle.iAliasname->Des().Format(KAliasName, &driveName);
+            handle.iOpen = EFalse;
+#ifdef __RAMDISK_PERF_ENABLE
+            handle.iOrigFullFilePath = HBufC::NewL(0);
+            handle.iTargetFullFilePath = HBufC::NewL(0);
+            handle.iDummyFilePath.Zero();
+            handle.iUseRAMdb = EFalse;
+#endif //__RAMDISK_PERF_ENABLE
+
+            TInt index = iDatabaseHandles.Count();
+            iDatabaseHandles.AppendL(handle);
+
+            TVolumeInfo vol;
+            if (iFs.Volume(vol, drive) == KErrNone)
+                {
+                CreateDatabaseL(drive);
+                AttachDatabaseL( index );
+                }
+            }
+        }
+
+    iInitialized = ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// Opens a specified database.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::OpenDatabaseL(
+    TInt aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::OpenDatabaseL");
+
+    if (iInitialized == EFalse)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    TDriveUnit drive(aDrive);
+    TDriveUnit cdrive(KRootDrive());
+    TBool found(EFalse);
+
+    if ((drive != cdrive) && !IsRemoteDrive(static_cast<TDriveNumber>(aDrive)))
+        {
+        TInt count(iDatabaseHandles.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            if (iDatabaseHandles[i].iDrive == aDrive)
+                {
+                MPX_DEBUG2("CMPXDbManager::OpenDatabaseL found %d", aDrive);
+                TInt transactionCount = iTransactionCount;
+                if (iTransactionCount > 0) 
+                    {
+                    iTransactionCount = 0;
+                    DoCommitL();
+                    }
+                OpenDatabaseAtIndexL( i );
+                if (transactionCount > 0) 
+                    {
+                    DoBeginL();
+                    iTransactionCount = transactionCount;
+                    }
+                found = ETrue;
+                break;
+                }
+            }
+        }
+    if (!found)
+        {
+        MPX_DEBUG1("CMPXDbManager::OpenDatabaseL not found");
+        User::Leave(KErrArgument);
+        }
+
+    // Close all prepared statements if a db is opened
+    //
+    ResetPreparedQueries();
+    }
+    
+void CMPXDbManager::OpenDatabaseAtIndexL( TInt aIndex )
+    {
+    	  DatabaseHandle & database = iDatabaseHandles[aIndex];
+        if (!database.iOpen)
+            {
+            MPX_DEBUG1("CMPXDbManager::OpenDatabaseAtIndexL not open");
+            // make sure the database is created
+            CreateDatabaseL( TDriveUnit(database.iDrive) );
+            AttachDatabaseL( aIndex );
+            }
+    }
+
+// ----------------------------------------------------------------------------
+// Closes a specified database.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CloseDatabaseL(
+    TInt aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::CloseDatabaseL");
+
+    if (iInitialized == EFalse)
+        {
+        User::Leave(KErrNotReady);
+        }
+    
+    TDriveUnit drive(aDrive);
+    TDriveUnit cdrive(KRootDrive());
+    TBool found(EFalse);
+
+    if ((drive != cdrive) && !IsRemoteDrive(static_cast<TDriveNumber>(aDrive)))
+        {
+        TInt count(iDatabaseHandles.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            if (iDatabaseHandles[i].iDrive == aDrive)
+                {
+                TBool inTransaction = InTransaction();
+                TInt transactionCount = iTransactionCount;
+                iTransactionCount = 0;								
+								
+                if (inTransaction) //if the transaction is ongoing, try committing
+                    {
+                    //if transaction committing fails, try roll-back	
+                    TInt error = iDatabase.Exec( KCommitTransaction );
+                    if ( error != KErrNone )
+                        {
+                        //The error is ignored since we can't do nothing about it
+                        iDatabase.Exec( KRollbackTransaction ); 
+                        }
+                    }
+                	
+#ifdef __RAMDISK_PERF_ENABLE                	
+                if ( iRAMDiskPerfEnabled && iDatabaseHandles[i].iUseRAMdb )
+            	      {
+                    MPX_DEBUG2("CMPXDbManager::CloseDatabaseL found %d at RAM", aDrive);
+                    TRAPD( err, CloseDatabaseAtIndexL( i ) );
+                    if ( err != KErrNone )
+                        {
+                        // Can't close db on RAM drive, so cleanup.
+                        MPX_DEBUG2("CMPXDbManager::CloseDatabaseL CloseDatabaseAtIndexL fail: error = %d", err);
+                        // Delete dummy file
+                        RemoveDummyFile(i);
+                        iDatabaseHandles[i].iUseRAMdb = EFalse;
+                        // Delete database on RAM drive.
+                        User::LeaveIfError( BaflUtils::DeleteFile(iFs, *iDatabaseHandles[i].iTargetFullFilePath) );
+                        }
+                    else
+                        {
+                        DoCopyDBFromRam(i);
+                        }
+                    iDatabaseHandles[i].iUseRAMdb = EFalse;
+                    }
+                else
+#endif
+                    {
+                    MPX_DEBUG2("CMPXDbManager::CloseDatabaseL found %d", aDrive);
+                    CloseDatabaseAtIndexL( i );
+                    }
+                
+                //Let MTP handle the transcation if there is any 
+                if ( inTransaction ) 
+                    {
+                    DoBeginL();
+                    iTransactionCount = transactionCount;
+                    }
+
+                found = ETrue;
+                break;
+                }
+            }
+        }
+    if (!found)
+        {
+        MPX_DEBUG1("CMPXDbManager::CloseDatabaseL not found");
+        User::Leave(KErrArgument);
+        }
+
+    }
+
+void CMPXDbManager::CloseDatabaseAtIndexL( TInt aIndex )
+    {
+    // Close all prepared statements if a db is closed
+    //
+    ResetPreparedQueries();
+
+    if (iDatabaseHandles[aIndex].iOpen)
+        {
+        MPX_DEBUG1("CMPXDbManager::CloseDatabaseAtIndexL found open");
+        DetachDatabaseL( aIndex );
+        }
+}
+
+// ----------------------------------------------------------------------------
+// Closes all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CloseAllDatabases()
+    {
+    MPX_FUNC("CMPXDbManager::CloseAllDatabases");
+
+    // Close all prepared statements if a db is closed
+    //
+    ResetPreparedQueries();
+
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        delete iDatabaseHandles[i].iAliasname;
+        iDatabaseHandles[i].iAliasname = 0;
+#ifdef __RAMDISK_PERF_ENABLE 
+        RemoveDummyFile(i);            	
+        delete iDatabaseHandles[i].iOrigFullFilePath;
+        iDatabaseHandles[i].iOrigFullFilePath = 0;
+        delete iDatabaseHandles[i].iTargetFullFilePath;
+        iDatabaseHandles[i].iTargetFullFilePath = 0;
+#endif //__RAMDISK_PERF_ENABLE 
+        }
+
+    iDatabaseHandles.Reset();
+    iDatabase.Close();
+    iInitialized = EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// Open all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::OpenAllDatabasesL()
+    {
+    MPX_FUNC("CMPXDbManager::OpenAllDatabasesL");
+
+    if (!iInitialized)
+        {
+        OpenRootDatabaseL();
+        }
+
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        TVolumeInfo vol;
+        if (iFs.Volume(vol, iDatabaseHandles[i].iDrive) == KErrNone)
+            {
+            AttachDatabaseL( i );
+            }
+        }
+    iInitialized = ETrue;
+
+    // Close all prepared statements if a db is closed
+    //
+    ResetPreparedQueries();
+    }
+
+// ----------------------------------------------------------------------------
+// Checks if the database on a specified drive is open.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXDbManager::IsOpen(
+    TInt aDrive) const
+    {
+    MPX_FUNC("CMPXDbManager::IsOpen");
+
+    TDriveUnit drive(aDrive);
+    TDriveUnit cdrive(KRootDrive());
+
+    if (!iInitialized)
+        {
+        return EFalse;
+        }
+    else if (drive == cdrive)
+        {
+        return ETrue;
+        }
+    else
+        {
+        TInt count(iDatabaseHandles.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            if (iDatabaseHandles[i].iDrive == aDrive)
+                {
+                return iDatabaseHandles[i].iOpen;
+                }
+            }
+        }
+
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// Returns the number of currently open databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXDbManager::DatabaseCount() const
+    {
+    MPX_FUNC("CMPXDbManager::DatabaseCount");
+
+    TInt openCount(0);
+    if (iInitialized)
+        {
+        ++openCount;
+
+        TInt count(iDatabaseHandles.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            if (iDatabaseHandles[i].iOpen)
+                {
+                ++openCount;
+                }
+            }
+        }
+
+    return openCount;
+    }
+
+// ----------------------------------------------------------------------------
+// Returns the drive corresponding to a given index.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXDbManager::DbDrive(
+    TInt aIndex) const
+    {
+    MPX_FUNC("CMPXDbManager::DbDrive");
+
+    ASSERT((aIndex >= 0) || (aIndex < iDatabaseHandles.Count()));
+    return iDatabaseHandles[aIndex].iDrive;
+    }
+
+// ----------------------------------------------------------------------------
+// Recreate a specified database.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::RecreateDatabaseL(
+    TInt aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::RecreateDatabaseL");
+
+    if (iInitialized == EFalse)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    TInt index = KErrNotFound;
+
+    if (aDrive == EDriveC)
+        {
+        index = iDatabaseHandles.Count();
+        }
+    else
+        {
+        TInt count(iDatabaseHandles.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            if ((iDatabaseHandles[i].iDrive == aDrive) && (iDatabaseHandles[i].iOpen))
+                {
+                index = i;
+                break;
+                }
+            }
+        }
+    if ( index >= 0 )
+        {
+        HBufC * filename = CreateFilenameL(aDrive);
+        CleanupStack::PushL(filename);
+
+        TRAPD(err, DoRecreateDatabaseL(filename));
+        if(err < 0)
+            {
+            TDriveUnit drive_unit(aDrive);
+
+            if(aDrive == EDriveC)
+                {
+                iDatabase.Close();
+                iInitialized = EFalse;
+
+                RSqlDatabase::Delete(*filename);
+                CreateDatabaseL(drive_unit);
+
+                User::LeaveIfError(iDatabase.Open(*filename));
+                iInitialized = ETrue;
+                }
+            else
+                {
+                DetachDatabaseL( index );
+
+                RSqlDatabase::Delete(*filename);
+                CreateDatabaseL(drive_unit);
+
+                AttachDatabaseL( index );
+                }
+            }
+
+        CleanupStack::PopAndDestroy(filename);
+        }
+    else
+        {
+        User::Leave(KErrNotFound);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Recreate all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::RecreateAllDatabasesL()
+    {
+    MPX_FUNC("CMPXDbManager::RecreateAllDatabasesL");
+
+    if (iInitialized == EFalse)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    // Recreate on drive C
+    RecreateDatabaseL(EDriveC);
+
+    // Recreate all attached drives
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        if (iDatabaseHandles[i].iOpen)
+            {
+            RecreateDatabaseL(iDatabaseHandles[i].iDrive);
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Returns current DB version
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TVersion CMPXDbManager::Version() const
+    {
+    MPX_FUNC("CMPXDbManager::Version");
+    return TVersion(KMPXDbVersion[0], KMPXDbVersion[1], KMPXDbVersion[2]);
+    }
+
+// ----------------------------------------------------------------------------
+// Registes a table with the database
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::RegisterTableL(
+    MMPXTable& aTable)
+    {
+    MPX_FUNC("CMPXDbManager::RegisterTableL");
+    iTables.AppendL(&aTable);
+    }
+
+// ----------------------------------------------------------------------------
+// Executes a select query with variable number of parameters
+// The query is executed on all available databases with a format like:
+//
+//      <query on database1> UNION ALL <query on database2> ...
+//
+// The query string passed in by the caller must have the ":dbname" prefix for all
+// the tables in the FROM clause. This will be replaced with the right alias for
+// attached databases or with no alias for the C database.
+//
+// In case the original query contains an ORDER BY clause, this will be extracted
+// and added at the end of the union query.
+//
+// Note: Running the union query seems to be similar in speed even if one of the
+// databases is empty and therefore no optimization was done for this case.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C RSqlStatement CMPXDbManager::ExecuteSelectQueryL(
+    TRefByValue<const TDesC> aFmt,
+    ...)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteSelectQueryL");
+
+    VA_LIST list;
+    VA_START(list, aFmt);
+
+    // Will reallocate
+    HBufC* selectBuf = FormatQueryLC(aFmt, list);
+    RSqlStatement statement = ExecuteSelectQueryOnAllDrivesL(selectBuf->Des());
+    CleanupStack::PopAndDestroy(selectBuf);
+
+    VA_END(list);
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// Executes a select query against a specified drive
+// ----------------------------------------------------------------------------
+//
+EXPORT_C RSqlStatement CMPXDbManager::ExecuteSelectQueryL(
+    TInt aDrive,
+    TRefByValue<const TDesC> aFmt,
+    ...)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteSelectQueryL");
+
+    VA_LIST list;
+    VA_START(list, aFmt);
+
+    // Will reallocate
+    HBufC* selectBuf = FormatQueryLC(aFmt, list);
+    RSqlStatement statement = ExecuteSelectQueryOnDriveL(aDrive, selectBuf->Des());
+    CleanupStack::PopAndDestroy(selectBuf);
+
+    VA_END(list);
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ExecuteSelectQueryL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C RSqlStatement& CMPXDbManager::ExecuteSelectQueryL(
+    TUint aStatementId,
+    TInt aFirstValue,
+    TInt aSecondValue,
+    TRefByValue<const TDesC> aFmt,
+    ...)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteOffsetSelectQueryL");
+
+    // Prepare the Query first
+    VA_LIST list;
+    VA_START(list, aFmt);
+    RSqlStatement& statement = PrepareQueryL( aStatementId, aFmt, list );
+    VA_END(list);
+
+    // Bind the Limit and Offset variables
+    User::LeaveIfError(statement.BindInt(0, aFirstValue));
+    User::LeaveIfError(statement.BindInt(1, aSecondValue));
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ExecuteSelectQueryL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C RSqlStatement& CMPXDbManager::ExecuteSelectQueryL( TUint aStatementId,
+                                                            const TDesC& aFirstValue,
+                                                            TInt aSecondValue,
+                                                            TRefByValue<const TDesC> aFmt, ...)
+    {
+    MPX_FUNC("CMPXDbManager::ExecuteMediaAscQueryL");
+
+    // Prepare the Query first
+    VA_LIST list;
+    VA_START(list, aFmt);
+    RSqlStatement& statement = PrepareQueryL( aStatementId, aFmt, list );
+    VA_END(list);
+
+    // bind the title and limit values
+    User::LeaveIfError(statement.BindText(0, aFirstValue));
+    User::LeaveIfError(statement.BindInt(1, aSecondValue));
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// Executes a query that does not return a record set (INSERT, UPDATE, DELETE,
+// CREATE, DROP, etc).
+//
+// If a valid drive is specified then the query is only executed only on
+// that drive. If KDbManagerAllDrives is specified then the query is executed
+// separately on each available drive.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::ExecuteQueryL(
+    TInt aDrive,
+    TRefByValue<const TDesC> aFmt,
+    ...)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteQueryL");
+
+    // make sure there is enough space on all drives affected
+    CheckDiskSpaceL(aDrive);
+
+    VA_LIST list;
+    VA_START(list, aFmt);
+
+    HBufC* selectBuf = FormatQueryLC(aFmt, list);
+    TPtr selectBufPtr = selectBuf->Des();
+    TInt dbCount(iDatabaseHandles.Count());
+
+    // a specified drive or all drives
+    TInt loopCount = (aDrive == KDbManagerAllDrives) ? (dbCount + 1) : 1;
+    TBool queryExecuted(EFalse); // flag to check if the query was executed at least once
+    for (TInt j = 0; j < loopCount; ++j)
+        {
+        HBufC* query = HBufC::NewLC(selectBufPtr.Length() + KBufIncrement);
+        TPtr queryPtr = query->Des();
+        queryPtr.Copy(selectBufPtr);
+        if (aDrive == EDriveC) // if C drive only
+            {
+            RemoveDriveAlias(queryPtr);
+            }
+        else // all drives or a particular drive other than C drive
+            {
+            if (aDrive == 0) // all drives
+                {
+                if (j == dbCount) // C drive
+                    {
+                    RemoveDriveAlias(queryPtr);
+                    }
+                else //all other drives, except C drive
+                    {
+                    if (iDatabaseHandles[j].iOpen)
+                        {
+                        ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[j].iAliasname));
+                        }
+                    }
+                }
+            else //a particular drive, other than C drive
+                {
+                for (TInt i = 0; i < dbCount; ++i)
+                    {
+                    if (iDatabaseHandles[i].iOpen && iDatabaseHandles[i].iDrive == aDrive)
+                        {
+                        ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
+                        break;
+                        }
+                    }
+                }
+            }
+        TInt dbnamePos = queryPtr.Find(KDBNameToken);// check if the query was created correctly
+        if (dbnamePos == KErrNotFound)
+            {
+            // log the query
+            TPtrC ptr(query->Left(KMaxLogQuery));
+            MPX_DEBUG2("Query: %S", &ptr);
+
+            User::LeaveIfError(ExecuteSqlStatement(iDatabase, queryPtr));
+            queryExecuted = ETrue;
+            }
+        CleanupStack::PopAndDestroy(query);
+        }   //for (TInt j = 0; j < loopCount; ++j)
+    CleanupStack::PopAndDestroy(selectBuf);
+    VA_END(list);
+    if (!queryExecuted && aDrive !=   0)
+        {
+        // the requested drive(s) is not open
+        User::Leave(KErrNotFound);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::FormatQueryLC
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXDbManager::FormatQueryLC(
+    TRefByValue<const TDesC> aFmt,
+    VA_LIST aList)
+    {
+    MPX_FUNC("CMPXDatabase::FormatQueryLC");
+
+    TOverflowHandle overflow;
+
+    HBufC* selectBuf = HBufC::NewLC(TDesC(aFmt).Length());//will reallocate
+    selectBuf->Des().AppendFormatList(aFmt, aList, &overflow);
+    while (overflow.GetOverflowFlag())
+        {
+        TInt len = selectBuf->Des().MaxLength() + KBufIncrement;
+        CleanupStack::PopAndDestroy(selectBuf);
+        selectBuf = HBufC::NewLC(len);
+        selectBuf->Des().AppendFormatList(aFmt, aList, &overflow);
+        }
+
+    return selectBuf;
+    }
+
+// ----------------------------------------------------------------------------
+// Executes a select query against a specified drive
+// ----------------------------------------------------------------------------
+//
+EXPORT_C RSqlStatement CMPXDbManager::ExecuteSelectQueryOnAllDrivesL(
+    TInt aDrive,
+    TRefByValue<const TDesC> aFmt,
+    ...)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteSelectQueryL");
+
+    VA_LIST list;
+    VA_START(list, aFmt);
+
+    // Will reallocate
+    HBufC* selectBuf = FormatQueryLC(aFmt, list);
+    RSqlStatement statement = ExecuteSelectQueryOnAllDrivesL(aDrive, selectBuf->Des());
+    CleanupStack::PopAndDestroy(selectBuf);
+
+    VA_END(list);
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ExecuteSelectQueryOnAllDrivesL
+// ----------------------------------------------------------------------------
+//
+RSqlStatement CMPXDbManager::ExecuteSelectQueryOnAllDrivesL(
+    TPtr aQuery)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteSelectQueryOnAllDrivesL");
+
+    TInt dbCount = iDatabaseHandles.Count();
+    HBufC* query = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
+        KUnionAllToken().Length() * dbCount);
+    TPtr queryPtr = query->Des();
+    HBufC* selectOutBuf = NULL;
+    TInt enclosed = aQuery.Mid(1, aQuery.Length() - 1).Find(KSelectToken);
+    if (enclosed != KErrNotFound)
+        {
+        enclosed++;//to compensate the indent
+        selectOutBuf = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
+            KUnionAllToken().Length() * dbCount);
+        selectOutBuf->Des().Copy(aQuery.Left(enclosed));
+        selectOutBuf->Des().Append(aQuery.Right(1));//the closing bracket
+        aQuery.Delete(0, enclosed);
+        aQuery.Delete(aQuery.Length() - 1, 1);
+        }
+
+    HBufC* orderBuf = NULL;
+    TInt orderPos = aQuery.Find(KOrderByToken);
+    if (orderPos != KErrNotFound)
+        {
+        orderBuf = aQuery.Right(aQuery.Length() - orderPos).AllocL();
+        aQuery.Delete(orderPos, aQuery.Length() - orderPos);
+        }
+    queryPtr.Append(aQuery);// for cdrive
+    RemoveDriveAlias(queryPtr);
+    for (TInt i = 0; i < dbCount; ++i)//for other drives
+        {
+        if (iDatabaseHandles[i].iOpen)
+            {
+            queryPtr.Append(KUnionAllToken);
+            queryPtr.Append(aQuery);
+            ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
+            }
+        }
+    if (orderBuf)
+        {
+        queryPtr.Append(orderBuf->Des());
+        }
+    delete orderBuf;
+    if (enclosed != KErrNotFound)
+        {
+        selectOutBuf->Des().Insert(enclosed, query->Des());
+        queryPtr.Copy(selectOutBuf->Des());
+        CleanupStack::PopAndDestroy(selectOutBuf);
+        }
+
+    // Log the query string before execution
+    TPtrC ptr(query->Left(KMaxLogQuery));
+    MPX_DEBUG2("Query: %S", &ptr);
+
+    // Return a temporary statement and not a member variable.
+    // This ensures that a copy is done and a second embedded query can be
+    // executed while the first result set is processed.
+    RSqlStatement statement;
+    User::LeaveIfError(statement.Prepare(iDatabase, queryPtr));
+    CleanupStack::PopAndDestroy(query);
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ExecuteSelectQueryOnAllDrivesL
+// ----------------------------------------------------------------------------
+//
+RSqlStatement CMPXDbManager::ExecuteSelectQueryOnAllDrivesL( TInt aDrive,
+    TPtr aQuery)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteSelectQueryOnAllDrivesL");
+
+    TInt dbCount = iDatabaseHandles.Count();
+    HBufC* query = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
+        KUnionAllToken().Length() * dbCount);
+    TPtr queryPtr = query->Des();
+    HBufC* selectOutBuf = NULL;
+    TInt enclosed = aQuery.Mid(1, aQuery.Length() - 1).Find(KSelectToken);
+    if (enclosed != KErrNotFound)
+        {
+        enclosed++;//to compensate the indent
+        selectOutBuf = HBufC::NewLC(aQuery.Length() * (dbCount + 1) +
+            KUnionAllToken().Length() * dbCount);
+        selectOutBuf->Des().Copy(aQuery.Left(enclosed));
+        selectOutBuf->Des().Append(aQuery.Right(1));//the closing bracket
+        aQuery.Delete(0, enclosed);
+        aQuery.Delete(aQuery.Length() - 1, 1);
+        }
+
+    HBufC* orderBuf = NULL;
+    TInt orderPos = aQuery.Find(KOrderByToken);
+    if (orderPos != KErrNotFound)
+        {
+        orderBuf = aQuery.Right(aQuery.Length() - orderPos).AllocL();
+        aQuery.Delete(orderPos, aQuery.Length() - orderPos);
+        }
+    
+    //remove KPlDBNameToken
+    if ( aDrive == EDriveC )//if playlist on c drive
+    	{
+    	RemoveDriveAlias(aQuery,KPlDBNameToken);
+    	}
+    else
+    	{//for other drives
+	    for (TInt i = 0; i < dbCount; ++i)
+	        {
+	        if (iDatabaseHandles[i].iOpen && (iDatabaseHandles[i].iDrive == aDrive))
+	            {
+	            ReplaceDriveAlias(aQuery, *(iDatabaseHandles[i].iAliasname),
+	            		KPlDBNameToken);
+	            break;
+	            }
+	        }
+    	}
+    
+    queryPtr.Append(aQuery);// for cdrive
+    RemoveDriveAlias(queryPtr);
+    for (TInt i = 0; i < dbCount; ++i)//for other drives
+        {
+        if (iDatabaseHandles[i].iOpen)
+            {
+            queryPtr.Append(KUnionAllToken);
+            queryPtr.Append(aQuery);
+            ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
+            }
+        }
+   
+    if (orderBuf)
+        {
+        queryPtr.Append(orderBuf->Des());
+        }
+    delete orderBuf;
+    if (enclosed != KErrNotFound)
+        {
+        selectOutBuf->Des().Insert(enclosed, query->Des());
+        queryPtr.Copy(selectOutBuf->Des());
+        CleanupStack::PopAndDestroy(selectOutBuf);
+        }
+
+    // Log the query string before execution
+    TPtrC ptr(query->Left(KMaxLogQuery));
+    MPX_DEBUG2("Query: %S", &ptr);
+
+    // Return a temporary statement and not a member variable.
+    // This ensures that a copy is done and a second embedded query can be
+    // executed while the first result set is processed.
+    RSqlStatement statement;
+    TInt err(statement.Prepare(iDatabase, queryPtr));
+    User::LeaveIfError(err);
+    CleanupStack::PopAndDestroy(query);
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ExecuteSelectQueryOnDriveLryLC
+// ----------------------------------------------------------------------------
+//
+RSqlStatement CMPXDbManager::ExecuteSelectQueryOnDriveL(
+    TInt aDrive,
+    TPtr aQuery)
+    {
+    MPX_FUNC("CMPXDatabase::ExecuteSelectQueryOnDriveL");
+
+    RSqlStatement statement;
+    if (KDbManagerAllDrives == aDrive)
+        {
+        statement = ExecuteSelectQueryOnAllDrivesL(aQuery);
+        }
+    else
+        {
+        TInt dbCount(iDatabaseHandles.Count());
+
+        // flag to check if the query was executed at least once
+        TBool queryExecuted = EFalse;
+
+        HBufC* query = HBufC::NewLC(aQuery.Length() + KBufIncrement);
+        TPtr queryPtr = query->Des();
+        queryPtr.Copy(aQuery);
+        if (aDrive == EDriveC) //if C drive
+            {
+            RemoveDriveAlias(queryPtr);
+            }
+        else // drive other than C drive
+            {
+            for (TInt i = 0; i < dbCount; ++i)
+                {
+                if (iDatabaseHandles[i].iOpen && (iDatabaseHandles[i].iDrive == aDrive))
+                    {
+                    ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
+                    break;
+                    }
+                }
+            }
+
+        TInt dbnamePos = queryPtr.Find(KDBNameToken);// check if the query was created correctly
+        if (dbnamePos == KErrNotFound)
+            {
+            // Log the query string before execution
+            TPtrC ptr(query->Left(KMaxLogQuery));
+            MPX_DEBUG2("Query: %S", &ptr);
+
+            User::LeaveIfError(statement.Prepare(iDatabase, queryPtr));
+            queryExecuted = ETrue;
+            }
+        CleanupStack::PopAndDestroy(query);
+
+        if (!queryExecuted)
+            {
+            // the requested drive(s) is not open
+            User::Leave(KErrNotFound);
+            }
+        }
+
+    return statement;
+    }
+
+// ----------------------------------------------------------------------------
+// Prepare a query for execution on all open database. This query's lifetime
+// is owned by the dbmanager
+// ----------------------------------------------------------------------------
+//
+RSqlStatement& CMPXDbManager::PrepareQueryL( TUint aStatementId,
+                                             TRefByValue<const TDesC> aFmt,
+                                             VA_LIST aList )
+    {
+    // Try to find the query first if it has been created
+    TInt index(KErrNotFound);
+    TInt c(iPreparedStatements.Count());
+
+    for( TInt i=0; i<c; ++i )
+        {
+        if( iPreparedStatements[i].iId == aStatementId )
+            {
+            index = i;
+            break;
+            }
+        }
+
+    // If the index isn't found we create a new query statement
+    //
+    if( index == KErrNotFound )
+        {
+        RSqlStatement* newStatement = new(ELeave) RSqlStatement();
+        CleanupStack::PushL(newStatement);
+
+        TSqlStatementState newState;
+        newState.iId = aStatementId;
+        newState.iPrepared = EFalse;
+        iPreparedStatements.AppendL( newState );
+
+        TInt err = iStatements.Append( newStatement ); // ownership x-fer
+        if (err != KErrNone)
+            {
+            iPreparedStatements.Remove(c);
+            User::Leave(err);
+            }
+        CleanupStack::Pop(newStatement);
+        index = c;
+        }
+
+    // Finally create the statement
+    if ( !iPreparedStatements[index].iPrepared )
+        {
+
+        // Will reallocate
+        HBufC* selectBuf = FormatQueryLC(aFmt, aList);
+        TPtr selectBufPtr = selectBuf->Des();
+        TInt dbCount = iDatabaseHandles.Count();
+        HBufC* query = HBufC::NewLC(selectBufPtr.Length() * (dbCount + 1) +
+            KUnionAllToken().Length() * dbCount);
+        TPtr queryPtr = query->Des();
+        HBufC* selectOutBuf = NULL;
+        TInt enclosed = selectBufPtr.Mid(1,selectBufPtr.Length() - 1).Find(KSelectToken);
+        if (enclosed != KErrNotFound)
+            {
+            enclosed++;//to compensate the indent
+            selectOutBuf = HBufC::NewLC(selectBufPtr.Length() * (dbCount + 1) +
+                KUnionAllToken().Length() * dbCount);
+            selectOutBuf->Des().Copy(selectBufPtr.Left(enclosed));
+            selectOutBuf->Des().Append(selectBufPtr.Right(1));//the closing bracket
+            selectBufPtr.Delete(0, enclosed);
+            selectBufPtr.Delete(selectBufPtr.Length()   -   1, 1);
+            }
+
+        HBufC* orderBuf = NULL;
+        TInt orderPos = selectBufPtr.Find(KOrderByToken);
+        if (orderPos != KErrNotFound)
+            {
+            orderBuf = selectBufPtr.Right(selectBufPtr.Length() - orderPos).AllocL();
+            selectBufPtr.Delete(orderPos,   selectBufPtr.Length() - orderPos);
+            }
+        queryPtr.Append(selectBufPtr);// for cdrive
+        RemoveDriveAlias(queryPtr);
+        for (TInt i = 0; i < dbCount; ++i)//for other drives
+            {
+            if (iDatabaseHandles[i].iOpen)
+                {
+                queryPtr.Append(KUnionAllToken);
+                queryPtr.Append(selectBufPtr);
+                ReplaceDriveAlias(queryPtr, *(iDatabaseHandles[i].iAliasname));
+                }
+            }
+        if (orderBuf)
+            {
+            queryPtr.Append(orderBuf->Des());
+            }
+        delete orderBuf;
+        if (enclosed != KErrNotFound)
+            {
+            selectOutBuf->Des().Insert(enclosed, query->Des());
+            queryPtr.Copy(selectOutBuf->Des());
+            CleanupStack::PopAndDestroy(selectOutBuf);
+            }
+
+        // Log the query string before execution
+        TPtrC ptr(query->Left(KMaxLogQuery));
+        MPX_DEBUG2("Query: %S", &ptr);
+
+        // use the member variable statement
+        User::LeaveIfError(iStatements[index]->Prepare(iDatabase, queryPtr));
+        CleanupStack::PopAndDestroy(2, selectBuf); //query
+
+        iPreparedStatements[index].iPrepared = ETrue;
+        }
+    else
+        {
+        iStatements[index]->Reset();
+        }
+
+    return *iStatements[index];
+    }
+
+// ----------------------------------------------------------------------------
+// Resets all prepared queries
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::ResetPreparedQueries()
+    {
+    MPX_FUNC("CMPXDbManager::ResetPreparedQueries");
+    iPreparedStatements.Reset();
+
+    TInt c( iStatements.Count() );
+    for( TInt i=0; i<c; ++i )
+        {
+        iStatements[i]->Close();
+        }
+    iStatements.ResetAndDestroy();
+    }
+
+// ----------------------------------------------------------------------------
+// Asks all registered tables to create themselves
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CreateTablesL(
+    RSqlDatabase& aDatabase)
+    {
+    MPX_FUNC("CMPXDbManager::CreateTablesL");
+
+	CreateTablesL(aDatabase, EFalse);
+    }
+
+// ----------------------------------------------------------------------------
+// CleanupTransaction: close transaction when creating DB
+// ----------------------------------------------------------------------------
+//
+static void CleanupTransaction(TAny * aDatabase)
+    {
+    TInt err = ((RSqlDatabase*)aDatabase)->Exec(KRollbackTransaction);
+    MPX_DEBUG2("CMPXDbManager CleanupTransaction rollback, error %d", err);
+    }
+    
+// ----------------------------------------------------------------------------
+// CMPXDbManager::CreateTablesL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::CreateTablesL(
+	RSqlDatabase& aDatabase,
+	TBool aCorrupt)
+	{
+	MPX_FUNC("CMPXDbManager::CreateTablesL");
+    TInt err = aDatabase.Exec(KBeginTransaction);
+    if (err < 0)
+       {
+       MPX_DEBUG2("SQL BEGIN TRANSACTION error %d", err);
+       User::Leave (err);
+       }
+    CleanupStack::PushL(TCleanupItem(&CleanupTransaction, &aDatabase));
+    TInt count(iTables.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        iTables[i]->CreateTableL(aDatabase, aCorrupt);
+        }
+    err = aDatabase.Exec(KCommitTransaction);
+    if (err < 0)
+        {
+        MPX_DEBUG2("SQL COMMIT TRANSACTION error %d", err);
+        User::Leave (err);
+        }
+    CleanupStack::Pop();
+	}
+
+// ----------------------------------------------------------------------------
+// Opens root database on C-drive
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::OpenRootDatabaseL()
+    {
+    MPX_FUNC("CMPXDbManager::OpenRootDatabaseL");
+        TDriveUnit cdrive(KRootDrive());
+    HBufC * filename = CreateFilenameL(cdrive);
+    CleanupStack::PushL(filename);
+    User::LeaveIfError(iDatabase.Open(*filename));
+
+    CleanupStack::PopAndDestroy(filename);
+    }
+
+// ----------------------------------------------------------------------------
+// Creates a specified database.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::CreateDatabaseL(
+    TDriveUnit aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::CreateDatabaseL");
+
+    RSqlDatabase database;
+    CleanupClosePushL(database);
+
+    HBufC* filename = CreateFilenameL(aDrive);
+    CleanupStack::PushL(filename);
+
+    if (database.Open(filename->Des()) != KErrNone)
+        {
+        MPX_DEBUG3("CMPXDbManager::CreateDatabaseL - cannot open db on drive %d %S", TInt(aDrive), filename);
+
+        // close the database first
+        database.Close();
+        DoCreateDatabaseL( aDrive );
+        }
+    else
+        {
+        TBool tableOK(ETrue);
+
+        // try to detect any corrupt tables
+        TInt count(iTables.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            // ask the table to check its structure
+            if (!iTables[i]->CheckTableL(database))
+                {
+                tableOK = EFalse;
+                break;
+                }
+            }
+
+        if (!tableOK)
+            {
+            // close the database first
+            database.Close();
+			
+			// delete database and create database
+            DoCreateDatabaseL( aDrive );
+            }
+        }
+    CleanupStack::PopAndDestroy(filename);
+    CleanupStack::PopAndDestroy(&database);
+    }
+
+// ----------------------------------------------------------------------------
+// Attaches a specified database.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::AttachDatabaseL( TInt aIndex )
+    {
+    MPX_FUNC("CMPXDbManager::AttachDatabaseL");
+    ASSERT( aIndex < iDatabaseHandles.Count() );
+    DatabaseHandle & database = iDatabaseHandles[ aIndex ];
+    if (!database.iOpen)
+        {
+        HBufC* filename = CreateFilenameL( database.iDrive );
+        CleanupStack::PushL(filename);
+                
+#ifdef __RAMDISK_PERF_ENABLE
+        if( database.iUseRAMdb )
+            {
+            delete database.iAliasname;
+            database.iAliasname = HBufC::NewL(KAliasName().Length());
+            HBufC* temp = HBufC::NewLC(2); // form of DE, DF, DX,...
+            temp->Des().Append(iRAMDrive); // length == 2
+            TDriveUnit pdrive( database.iDrive );
+            temp->Des().Append(pdrive.Name().Left(1)); //length == 2+ 1
+            database.iAliasname->Des().Format(KRAMAliasName, temp);
+            MPX_DEBUG2("CMPXDbManager::AttachDatabaseL - RAM change aliasname of %S", database.iAliasname );
+            CleanupStack::PopAndDestroy(temp);
+            }
+        else
+#endif //__RAMDISK_PERF_ENABLE
+            {
+            delete database.iAliasname;
+            TDriveUnit drive( database.iDrive );
+            const TDesC& driveName = drive.Name();
+            database.iAliasname = HBufC::NewL(KAliasName().Length());
+            database.iAliasname->Des().Format(KAliasName, &driveName);
+            MPX_DEBUG2("CMPXDbManager::AttachDatabaseL - normal change aliasname of %S", database.iAliasname);
+            }
+
+        TInt err = iDatabase.Attach( *filename, *database.iAliasname );
+        MPX_DEBUG2("CMPXDbManager::AttachDatabaseL - Attach Error =%d", err);
+        User::LeaveIfError(err);
+        database.iOpen = ETrue;
+
+        CleanupStack::PopAndDestroy(filename);
+        }
+    else
+        {
+        MPX_DEBUG1("CMPXDbManager::AttachDatabaseL - found already open");    
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Detaches a specified database.
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::DetachDatabaseL( TInt aIndex )
+    {
+    MPX_FUNC("CMPXDbManager::DetachDatabaseL");
+
+    ASSERT( iInitialized && aIndex < iDatabaseHandles.Count() );
+    DatabaseHandle & database = iDatabaseHandles[ aIndex ];
+    if ( database.iOpen )
+        {
+        MPX_DEBUG2("CMPXDbManager::DetachDatabaseL iAliasname=%S is open",database.iAliasname );
+        TInt err = iDatabase.Detach(*(database.iAliasname));
+        if ( err )
+            {
+            MPX_DEBUG2("CMPXDbManager::DetachDatabaseL detach failed Error=%d", err);
+            }
+        User::LeaveIfError(err);
+        database.iOpen = EFalse;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Creates the absolute database filename on a specified drive.
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXDbManager::CreateFilenameL(
+    TDriveUnit aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::CreateFilenameL");
+
+    HBufC* filename = HBufC::NewL(KMaxFileName);
+
+    const TDesC& securefilePath = KSecureFilePath;
+    TDriveUnit cdrive(KRootDrive());
+
+#ifdef __RAMDISK_PERF_ENABLE
+    TInt index(GetDatabaseIndex((TInt)aDrive));    
+    if ( index >=0 && iDatabaseHandles[index].iUseRAMdb && aDrive != cdrive )
+        {
+        MPX_DEBUG1("CMPXDbManager::CreateFilenameL - use RAMDisk");
+        TFileName path;
+        path.Append(iRAMDrive);
+        path.Append(_L(":"));
+        TBuf<2> d;
+        d.Append(aDrive.Name());
+        TFileName temp;
+        temp.Append(d.Left(1)); // attach original drive name
+        temp.Append(iDbFile->Des()); 
+        filename->Des().Format(securefilePath, &path, User::Identity().iUid, &temp);
+        MPX_DEBUG3("CMPXDbManager::CreateFilenameL - path=%S filename=%S", &path, filename);
+        }
+    else
+#endif //__RAMDISK_PERF_ENABLE
+        {
+        MPX_DEBUG1("CMPXDbManager::CreateFilenameL - use normal drive");
+        const TDesC& driveName = aDrive.Name();
+        filename->Des().Format(securefilePath, &driveName, User::Identity().iUid, iDbFile);
+        }
+    
+    MPX_DEBUG2("CMPXDbManager::CreateFilenameL filename = %S", filename); 
+    return filename;
+    }
+
+// ----------------------------------------------------------------------------
+// Replaces :dbname with a drive alias
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::ReplaceDriveAlias(
+    TDes& aQuery,
+    const TDesC& aAlias)
+    {
+//  MPX_FUNC("CMPXDbManager::ReplaceDriveAlias");
+
+    TInt dbnamePos(aQuery.Find(KDBNameToken));
+    while (dbnamePos != KErrNotFound)
+        {
+        aQuery.Delete(dbnamePos, KDBNameToken().Length());
+        aQuery.Insert(dbnamePos, aAlias);
+        dbnamePos = aQuery.Find(KDBNameToken);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Replaces :dbname with a drive alias
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::ReplaceDriveAlias(
+    TDes& aQuery,
+    const TDesC& aAlias,
+    const TDesC& aToKen)
+    {
+    
+    TInt dbnamePos(aQuery.Find(aToKen));
+    while (dbnamePos != KErrNotFound)
+        {
+        aQuery.Delete(dbnamePos, aToKen.Length());
+        aQuery.Insert(dbnamePos, aAlias);
+        dbnamePos = aQuery.Find(aToKen);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Removes :dbname
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::RemoveDriveAlias(
+    TDes& aQuery)
+    {
+    MPX_FUNC("CMPXDbManager::RemoveDriveAlias");
+
+    TInt dbnamePos(aQuery.Find(KDBNameToken));
+    while (dbnamePos != KErrNotFound)
+        {
+        aQuery.Delete(dbnamePos, KDBNameToken().Length() + 1);
+        dbnamePos = aQuery.Find(KDBNameToken);
+        }
+    }
+
+
+// ----------------------------------------------------------------------------
+// Removes :dbname
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::RemoveDriveAlias(
+    TDes& aQuery,const TDesC& aToKen)
+    {
+    MPX_FUNC("CMPXDbManager::RemoveDriveAlias");
+
+    TInt dbnamePos(aQuery.Find(aToKen));
+    while (dbnamePos != KErrNotFound)
+        {
+        aQuery.Delete(dbnamePos, aToKen.Length() + 1);
+        dbnamePos = aQuery.Find(aToKen);
+        }
+    }
+
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::CheckDiskSpaceL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::CheckDiskSpaceL(
+    TInt aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::CheckDiskSpaceL");
+    
+    // LTAN-7GH6BZ, crash if eject memory card when adding song to existing playlist
+    // due to special timing issue, it is possible drive number is -1 and create a
+    // panic when use for TDriveUnit
+    MPX_DEBUG2("aDrive = %d", aDrive);
+    
+    if (aDrive < 0)
+        {
+        MPX_DEBUG1("invalid driveId, leave with KErrNotReady");
+        User::Leave(KErrNotReady);
+        }
+    
+    EnsureDiskSpaceL(aDrive);
+    }
+    
+// ----------------------------------------------------------------------------
+// Regenerate all databases.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::RegenerateAllDatabasesL()
+    {
+    MPX_DEBUG1("CMPXDbManager::RegenerateAllDatabasesL Enter");
+    ResetPreparedQueries(); //just in case ...
+    TInt handles(iDatabaseHandles.Count());
+    for (TInt i = 0; i < handles; ++i)
+        {
+        iDatabaseHandles[i].iOpen = EFalse; //attach will open them again
+        }    
+    iDatabase.Close(); //close the database before deleting the file
+    iInitialized = EFalse;
+
+    MPX_DEBUG1("RegenerateAllDatabasesL: Regenerating main DB on C:");
+    HBufC * filename = CreateFilenameL(EDriveC);
+    CleanupStack::PushL(filename);
+    RSqlDatabase::Delete(*filename);
+    TDriveUnit cdrive(KRootDrive());
+    CreateDatabaseL(cdrive);
+    User::LeaveIfError(iDatabase.Open(*filename)); // will set handle status later
+    CleanupStack::PopAndDestroy(filename);
+    MPX_DEBUG1("RegenerateAllDatabasesL: DB regeneration complete");
+    
+    // Recreate all attached drives
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        if (iDatabaseHandles[i].iDrive != EDriveC)
+            {
+            MPX_DEBUG2("RegenerateAllDatabasesL: Regenerating DB on %d",iDatabaseHandles[i].iDrive);
+            TVolumeInfo volumeInfo; 
+            TInt err = iFs.Volume(volumeInfo,iDatabaseHandles[i].iDrive);
+            if(err != KErrNone)
+                {
+                continue; //if drive is not currently accessible, skip
+                }
+            filename = CreateFilenameL(iDatabaseHandles[i].iDrive);
+            CleanupStack::PushL(filename);
+            MPX_DEBUG1("RegenerateAllDatabasesL: Detaching DB");
+            err = iDatabase.Detach(*(iDatabaseHandles[i].iAliasname)); //ignore the error if any
+            MPX_DEBUG2("RegenerateAllDatabasesL: Detached[err=%d]; Deleting DB",err);
+            err = RSqlDatabase::Delete(*filename);
+            MPX_DEBUG2("RegenerateAllDatabasesL: Deleted[err=%d]; Creating new DB",err);
+            TDriveUnit drive(iDatabaseHandles[i].iDrive);
+            CreateDatabaseL(drive);
+            MPX_DEBUG1("RegenerateAllDatabasesL: Attaching new DB");
+            AttachDatabaseL( i );    
+            MPX_DEBUG1("RegenerateAllDatabasesL: DB regeneration complete");
+            CleanupStack::PopAndDestroy(filename);
+            }
+        else
+            {
+            iDatabaseHandles[i].iOpen = ETrue; //if we got here it is opened
+            }
+        }
+    iInitialized = ETrue;
+    MPX_DEBUG1("CMPXDbManager::RegenerateAllDatabasesL Exit");
+    }    
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::DoRecreateDatabaseL
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::DoRecreateDatabaseL(HBufC * aFilename)
+    {
+    RSqlDatabase database;
+    CleanupClosePushL(database);
+
+    User::LeaveIfError(database.Open(aFilename->Des()));
+
+    TInt count(iTables.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        iTables[i]->DropTableL(database);
+        iTables[i]->CreateTableL(database, EFalse);
+        }
+    CleanupStack::PopAndDestroy(&database);
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXDbManager::ExecuteSqlStatement
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbManager::ExecuteSqlStatement(RSqlDatabase& aDatabase,const TDesC& aStatement)
+    {
+    MPX_FUNC("CMPXDbManager::ExecuteSqlStatement");
+    TInt result( KErrNone );
+    RSqlStatement sqlStatement;
+    //Prepare and execute SQL statement
+    result = sqlStatement.Prepare(aDatabase, aStatement);
+    if (result == KErrNone)
+        {
+        result = sqlStatement.Exec();
+        //If the database schema was changed or the session expired repeat all the steps
+        if((result == KSqlErrStmtExpired) || (result == KSqlErrSchema))
+            {
+            sqlStatement.Close();
+            result = sqlStatement.Prepare(aDatabase, aStatement);
+            if (result == KErrNone)
+                {
+                result = sqlStatement.Exec();
+                }
+            }
+        sqlStatement.Close();
+        }
+    return result;
+    }
+
+#ifdef _DEBUG
+
+// ----------------------------------------------------------------------------
+// Returns the number of columns from a specified SQL statement
+// ----------------------------------------------------------------------------
+//
+TInt CMPXDbManager::GetColumnCountL(
+    RSqlStatement& aStatement)
+    {
+    TInt columnCount(0);
+
+// Using TSqlRowSetUtil causes linker errors on ARMv5 UDEB
+// Enabling this functionality for WINSCW UDEB only
+// PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed
+//#ifdef __WINSCW__
+//
+//    HBufC* headers = TSqlRowSetUtil::GetDeclColumnTypesL(aStatement);
+//    CleanupStack::PushL(headers);
+//
+//    // Count the number of semicolons to get the number of columns
+//    TPtr headerPtr = headers->Des();
+//    TInt location(headerPtr.Locate(';'));
+//    while ((location != KErrNotFound) && (location < headers->Length()))
+//        {
+//        ++columnCount;
+//        if (++location < headers->Length())
+//            {
+//            headerPtr = headers->Des().Mid(location);
+//            location = headerPtr.Locate(';');
+//            }
+//        }
+//    CleanupStack::PopAndDestroy(headers);
+//
+//#else
+	(void)aStatement;
+//#endif
+
+    return columnCount;
+    }
+
+// ----------------------------------------------------------------------------
+// Prints the table values from a specified SQL query
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::PrintTableValuesL(
+    RSqlStatement& aStatement)
+    {
+    TInt columnCount(GetColumnCountL(aStatement));
+    TInt err(KErrNone);
+    HBufC* tableRow = HBufC::NewLC(255 * columnCount);
+    TPtr tableRowPtr = tableRow->Des();
+
+    while ((err = aStatement.Next()) == KSqlAtRow)
+        {
+        tableRowPtr.Zero();
+        TInt error(KErrNone);
+        for (TInt index = 0; (error == KErrNone) && (index < columnCount); ++index)
+            {
+            if (index !=0)
+                {
+                tableRowPtr.Append(',');
+                }
+            switch (aStatement.ColumnType(index))
+                {
+                case ESqlNull:
+                    tableRowPtr.Append(_L("<NULL>"));
+                    break;
+
+                case ESqlInt:
+                    {
+                    tableRowPtr.AppendFormat(_L("%u"), aStatement.ColumnInt(index));
+                    }
+                    break;
+
+                case ESqlInt64:
+                    {
+                    tableRowPtr.AppendFormat(_L("%lu"), aStatement.ColumnInt64(index));
+                    }
+                    break;
+
+                case ESqlReal:
+                    {
+                    tableRowPtr.AppendFormat(_L("%f"), aStatement.ColumnReal(index));
+                    }
+                    break;
+
+                case ESqlText:
+                    {
+                    TPtrC columnValue;
+                    error = aStatement.ColumnText(index, columnValue);
+                    if (error == KErrNone)
+                        {
+                        tableRowPtr.AppendFormat(_L("%S"), &columnValue);
+                        }
+                    }
+                    break;
+
+                case ESqlBinary:
+                    {
+                    TPtrC8 columnValue;
+                    error = aStatement.ColumnBinary(index, columnValue);
+                    if (error == KErrNone)
+                        {
+                        tableRowPtr.AppendFormat(_L("%S"), &columnValue);
+                        }
+                    }
+                    break;
+
+                default :
+                    ASSERT(EFalse);
+                }
+
+            if (tableRowPtr.Length() > 255)
+                {
+                tableRowPtr.SetLength(255);
+                MPX_DEBUG2("%S", tableRow);
+                tableRowPtr.Zero();
+                }
+            }
+        if (tableRowPtr.Length() > 0)
+            {
+            tableRowPtr.SetLength(Min(tableRowPtr.Length(), 255));
+            MPX_DEBUG2("%S", tableRow);
+            }
+        }
+    CleanupStack::PopAndDestroy(tableRow);
+    if (err != KSqlAtEnd)
+        {
+        User::Leave(err);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Finds all the tables on the main or attached drives
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::FindAllTablesL(
+    const TDesC& aAlias,
+    RArray<HBufC*>& aTableName)
+    {
+    RSqlStatement statement;
+    CleanupClosePushL(statement);
+
+    if (aAlias == KNullDesC)
+        {
+        statement.Prepare(iDatabase, KFindAllCDriveTablesQuery);
+        }
+    else
+        {
+        HBufC* query = KFindAllAttachedTablesQuery().AllocL();
+        CleanupStack::PushL(query);
+        TPtr queryPtr = query->Des();
+        ReplaceDriveAlias(queryPtr, aAlias);
+        statement.Prepare(iDatabase, queryPtr);
+        CleanupStack::PopAndDestroy(query);
+        }
+
+    TInt err(KErrNone);
+
+    while ((err = statement.Next()) == KSqlAtRow)
+        {
+        TPtrC val = statement.ColumnTextL(statement.ColumnIndex(KNameColumn));
+        aTableName.AppendL(val.AllocL());
+        }
+    if (err != KSqlAtEnd)
+        {
+        User::Leave(err);
+        }
+
+    CleanupStack::PopAndDestroy(&statement);
+    }
+
+// ----------------------------------------------------------------------------
+// Prints the tables on the main or attached drives
+// ----------------------------------------------------------------------------
+//
+void CMPXDbManager::PrintTableL(
+    const TDesC& aAlias,
+    const TDesC& aTableName)
+    {
+    RSqlStatement statement;
+    CleanupClosePushL(statement);
+
+    if (aAlias == KNullDesC)
+        {
+        HBufC* selectQuery = HBufC::NewLC(KTableQuery().Length() + aTableName.Length());
+        selectQuery->Des().Format(KTableQuery, &aTableName);
+        User::LeaveIfError(statement.Prepare(iDatabase, *selectQuery));
+        CleanupStack::PopAndDestroy(selectQuery);
+        }
+    else
+        {
+        HBufC* selectQuery = HBufC::NewLC(KAttachedTableQuery().Length() + aTableName.Length());
+        selectQuery->Des().Format(KAttachedTableQuery, &aTableName);
+
+        TPtr selectQueryPtr(selectQuery->Des());
+        ReplaceDriveAlias(selectQueryPtr, aAlias);
+        User::LeaveIfError(statement.Prepare(iDatabase, *selectQuery));
+
+        CleanupStack::PopAndDestroy(selectQuery);
+        }
+
+    PrintTableValuesL(statement);
+    CleanupStack::PopAndDestroy(&statement);
+    }
+
+#endif
+
+// ----------------------------------------------------------------------------
+// Prints all the tables on the main and attached drives
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::PrintDatabaseL()
+    {
+#ifdef _DEBUG
+    if (iInitialized)
+        {
+        // C-Drive
+        RArray<HBufC*> tableNames;
+        FindAllTablesL(KNullDesC(), tableNames);
+
+        MPX_DEBUG1("### Drive C ###");
+
+        TInt tableCount(tableNames.Count());
+        for (TInt i = 0; i < tableCount; ++i)
+            {
+            MPX_DEBUG2("# %S #", tableNames[i]);
+            MPX_TRAPD(error, PrintTableL(KNullDesC, *tableNames[i]));
+            delete tableNames[i];
+            if (error != KErrNone)
+                {
+                if (error != KErrPermissionDenied)
+                    {
+                    User::Leave(error);
+                    }
+                else
+                    {
+                    MPX_DEBUG1("Unable to print table");
+                    }
+                }
+            }
+        tableNames.Close();
+
+        // Each attached drive
+        TInt count(iDatabaseHandles.Count());
+        for (TInt i = 0; i < count; ++i)
+            {
+            if (iDatabaseHandles[i].iOpen)
+                {
+                FindAllTablesL(iDatabaseHandles[i].iAliasname->Des(), tableNames);
+
+                TDriveUnit driveUnit(iDatabaseHandles[i].iDrive);
+                const   TDesC& name = driveUnit.Name();
+                MPX_DEBUG2("### Drive %S ###", &name);
+
+                for (TInt j = 0; j < tableCount; ++j)
+                    {
+                    MPX_DEBUG2("# %S #", tableNames[j]);
+                    MPX_TRAPD(error, PrintTableL(iDatabaseHandles[i].iAliasname->Des(), *tableNames[j]));
+                    delete tableNames[j];
+                    if (error != KErrNone)
+                        {
+                        if (error != KErrPermissionDenied)
+                            {
+                            User::Leave(error);
+                            }
+                        else
+                            {
+                            MPX_DEBUG1("Unable to print table");
+                            }
+                        }
+                    }
+                tableNames.Close();
+                }
+            }
+        }
+#endif
+    }
+
+// ----------------------------------------------------------------------------
+// Prints all the tables on the main and attached drives
+// ----------------------------------------------------------------------------
+//
+EXPORT_C RFs& CMPXDbManager::Fs()
+    {
+    return iFs;
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::IsRemoteDrive
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXDbManager::IsRemoteDrive(TDriveNumber aDrive)
+    {
+    TDriveInfo driveInfo;
+    TBool isRemoteDrive(EFalse);
+    if (iFs.Drive(driveInfo, aDrive) == KErrNone)
+        {
+        isRemoteDrive = driveInfo.iDriveAtt & KDriveAttRemote;
+        }
+    return isRemoteDrive;
+    }
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::DoCreateDatabaseL
+// ---------------------------------------------------------------------------
+//
+void CMPXDbManager::DoCreateDatabaseL( TDriveUnit aDrive )
+    {
+	MPX_FUNC( "CMPXDbManager::DoCreateDatabaseL" );
+	
+    RSqlDatabase database;
+    CleanupClosePushL(database);
+
+    HBufC* filename = CreateFilenameL(aDrive);
+    CleanupStack::PushL(filename);
+    
+    // remove old databases before creating/replacing new database
+    TInt driveNameLen = aDrive.Name().Length();
+    
+    TFileName dbFileName;
+
+#ifdef __RAMDISK_PERF_ENABLE
+    TInt index(GetDatabaseIndex((TInt)aDrive));
+    if( index >= 0 && iDatabaseHandles[index].iUseRAMdb )
+        {
+        dbFileName.Append(iRAMDrive); // RAM
+        dbFileName.Append(_L(":")); // RAM
+        }
+    else 
+#endif //__RAMDISK_PERF_ENABLE
+        {
+        MPX_DEBUG1("CMPXDbManager::CreateDatabaseL - E:");
+        dbFileName.Append(aDrive.Name()); //initialise with drive name
+        }
+        
+
+    MPX_DEBUG2("CMPXDbManager::CreateDatabaseL - dbFileName=%S", &dbFileName);
+    dbFileName.Append(KDBFilePath);  // append private path
+    
+    //append file name
+    dbFileName.Append(filename->Right((filename->Length())- driveNameLen));     
+    
+    // locate the offset position where version info starts in file name
+    TInt pos = dbFileName.LocateReverse('v');
+
+    //replace version info with wildcards 
+    dbFileName.Replace(pos, (dbFileName.Length()- pos), KDBFilePattern);
+
+    CFileMan* fileManager = CFileMan::NewL(iFs);
+    TInt ret = fileManager->Delete(dbFileName);
+    delete fileManager;
+    fileManager = NULL;
+    
+    // create the database now
+    RSqlSecurityPolicy securityPolicy;
+    CleanupClosePushL(securityPolicy);
+
+    TSecurityPolicy policy(TSecurityPolicy::EAlwaysPass);
+    securityPolicy.Create(policy);
+
+    TSecurityPolicy schemaPolicy(TSecurityPolicy::EAlwaysPass);
+    TSecurityPolicy readPolicy(TSecurityPolicy::EAlwaysPass);
+    TSecurityPolicy writePolicy(TSecurityPolicy::EAlwaysPass);
+
+    User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy, schemaPolicy));
+    User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, readPolicy));
+    User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy, writePolicy));
+
+    
+    const TDesC8& config = KMCSqlConfig;
+    
+    TBool corrupt(EFalse);
+    TInt err = database.Create(filename->Des(), securityPolicy, &config);
+    if (KErrAlreadyExists == err)
+        {
+        MPX_DEBUG1("CMPXDbManager::DoCreateDatabaseL - could not create the database");
+
+        // the file already exists and it is corrupted
+        // make sure we delete the file
+        User::LeaveIfError(database.Delete(*filename));
+
+        MPX_DEBUG1("CMPXDbManager::DoCreateDatabaseL - deleted the database");
+
+        // try again
+        err = database.Create(filename->Des(), securityPolicy, &config);
+
+        // the database could not be opened but the file exists
+        corrupt = ETrue;
+        }
+    User::LeaveIfError(err);
+
+    MPX_DEBUG1("CMPXDbManager::DoCreateDatabaseL - created the database");
+
+    CleanupStack::PopAndDestroy(&securityPolicy);
+
+    CreateTablesL(database, corrupt);
+
+    CleanupStack::PopAndDestroy(filename);
+    CleanupStack::PopAndDestroy(&database);
+    }
+	
+// ---------------------------------------------------------------------------
+// CMPXDbManager::GetRAMDiskPath
+// ---------------------------------------------------------------------------
+//
+TInt CMPXDbManager::GetRAMDiskPath()
+    {
+    TInt error = KErrNotSupported;
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::GetRAMDiskPath");
+    TDriveList driveList;
+    TBool ramDriveFound = EFalse;
+    TInt driveOffset = 'A';
+    iRAMFolder.Zero();
+    
+    error = iFs.DriveList( driveList );
+    if ( error == KErrNone )
+        {
+        for ( TInt i = 0; i < driveList.Length(); i++ )
+            {
+            if ( driveList[i] != 0 )
+                {
+                TDriveInfo info;
+                TInt err = iFs.Drive( info, i );
+                if ( !err && info.iType == EMediaRam )
+                    {
+                    iRAMDrive = driveOffset + i;
+                    iRAMFolder.Append(iRAMDrive);
+                    iRAMFolder.Append(_L(":"));
+                    iRAMFolder.Append(KDBFilePath);
+                    ramDriveFound = ETrue;
+                    MPX_DEBUG2("RAMDisk path=%S", &iRAMFolder);
+                    break;
+                    }
+                }
+            }
+        
+        // Check if ram drive is found.
+        if ( !ramDriveFound )
+            {
+            error = KErrNotFound;
+            }
+        }
+    MPX_DEBUG2("CMPXDbManager::GetRAMDiskPath Get DriveList error=%d", error);
+    MPX_DEBUG1("<--CMPXDbManager::GetRAMDiskPath");
+#endif //__RAMDISK_PERF_ENABLE
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::IsRamDiskSpaceAvailable
+// ---------------------------------------------------------------------------
+//
+TBool CMPXDbManager::IsRamDiskSpaceAvailable()
+    {
+
+#ifdef __RAMDISK_PERF_ENABLE
+
+    MPX_DEBUG1("-->CMPXDbManager::IsDiskSpaceAvailable" );
+    TInt driveIndex;
+    RFs::CharToDrive(iRAMDrive, driveIndex);
+    TVolumeInfo vol;
+    TInt err = iFs.Volume( vol, driveIndex );
+    if ( err == KErrNone )
+        {
+        MPX_DEBUG2("CMPXDbManager::IsRamDiskSpaceAvailable Free in bytes =%Lu", vol.iFree);
+        if ( vol.iFree > KMPMinimumRAMSizeToRun )
+            {
+            MPX_DEBUG1("CMPXDbManager::IsRamDiskSpaceAvailable Ok to copy");
+            return ETrue;
+            }
+        MPX_DEBUG1("CMPXDbManager::IsRamDiskSpaceAvailable NOT Ok to copy");
+        return EFalse;
+        }
+    
+    MPX_DEBUG2("CMPXDbManager::IsRamDiskSpaceAvailable Disk Not available to use. %d", err);
+    MPX_DEBUG1("<--CMPXDbManager::IsDiskSpaceAvailable");
+
+#endif //__RAMDISK_PERF_ENABLE
+
+    return EFalse;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::BlockDiskSpaceL
+// ---------------------------------------------------------------------------
+//
+TBool CMPXDbManager::BlockDiskSpace( TInt aIndex, TBool aIsMTPInUse )
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+
+    MPX_DEBUG2("-->CMPXDbManager::BlockDiskSpaceL %d", aIndex );
+    DatabaseHandle & database = iDatabaseHandles[aIndex];    
+    // if current DB size can not fit in RAM, abort now
+    TInt ramDrive;
+    RFs::CharToDrive(iRAMDrive, ramDrive);
+    TVolumeInfo vol;
+    TInt err = iFs.Volume( vol, ramDrive );
+    TEntry origDb;
+    iFs.Entry( *database.iOrigFullFilePath, origDb );
+    if ( vol.iFree <= origDb.iSize + KMPMinimumRAMSizeToRun )
+        {
+        MPX_DEBUG1("-->CMPXDbManager::BlockDiskSpaceL Not enough even for copy original DB file, leave" );
+        return EFalse;
+        }
+
+    // ensure you have the disk volume and database
+    err = iFs.Volume( vol, database.iDrive );
+    if (err != KErrNone) 
+        {
+        MPX_DEBUG2("CMPXDbManager::BlockDiskSpaceL Volume not available on drive %d", database.iDrive);
+        return EFalse;
+        }
+
+    // Check if the drive has enough space to block
+    MPX_DEBUG2("CMPXDbManager::BlockDiskSpaceL Disk total free space in bytes =%Lu", vol.iFree);
+    TInt64 blockingSize( CalculateInitalDummyDBSize( vol, origDb.iSize, aIsMTPInUse ));
+    MPX_DEBUG2("CMPXDbManager::BlockDiskSpaceL Disk blocking size =%Lu", blockingSize);
+    if ( vol.iFree <= blockingSize + 1*KMPMegaByte )
+        {
+        MPX_DEBUG1("CMPXDbManager::BlockDiskSpaceL NOk to block");
+        return EFalse;
+        }
+
+    // Create and resize the dummy file
+    TChar ch;
+    RFs::DriveToChar(database.iDrive, ch );
+    database.iDummyFilePath.Format( KDummyDbFile, (TUint)ch);
+    RFile dummyDb;
+    err = dummyDb.Replace( iFs, database.iDummyFilePath, EFileWrite );
+    if (err != KErrNone) 
+        {
+        MPX_DEBUG2("CMPXDbManager::BlockDiskSpaceL Can't open dummy file %d", err);
+        database.iDummyFilePath.Zero();
+        return EFalse;
+        }
+    err = dummyDb.SetSize( blockingSize );
+    if ( err )
+        {
+        MPX_DEBUG2("CMPXDbManager::BlockDiskSpaceL Can't resize dummy file %d", err);
+        dummyDb.Close();
+        RemoveDummyFile(aIndex);
+        return EFalse;
+        }
+
+    dummyDb.Close();
+    MPX_DEBUG1("CMPXDbManager::BlockDiskSpaceL Ok to block");
+    MPX_DEBUG1("<--CMPXDbManager::BlockDiskSpace");
+
+    return ETrue;
+#else
+    return EFalse;
+#endif //__RAMDISK_PERF_ENABLE
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::CalculateInitalDummyDBSizeL
+//
+//a) MTP case
+//-------------
+//        totalNumOfSongsCanFit = <disk free space> / 2 MB;
+//        metadataSize = totalNumOfSongsCanFit * 3000B 
+//        estimatedDBSize = metadataSize + <orig DB size>;
+//        dummyDBSize = MIN (iMaximumAllowedRAMDiskSpaceToCopy , estimatedDBSize )
+
+//b) Harvesting case
+//-------------------
+//        totalNumOfSongsCanFit = <disk total size>/ 2 MB
+//        metadataSize = totalNumOfSongsCanFit * 3000B 
+//        estimatedSize = metadataSize+ <orig DB size>
+//        freeDiskSpace = <disk free space> - 1 MB
+//        dummyDBSize = MIN (freeDiskSpace, iMaximumAllowedRAMDiskSpaceToCopy , estimatedSize);
+//
+// ---------------------------------------------------------------------------
+//
+TInt64 CMPXDbManager::CalculateInitalDummyDBSize( const TVolumeInfo& aVol, TInt aOrigDbSize, TBool aIsMTPInUse )
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::CalculateInitalDummyDBSize");
+
+    if ( aIsMTPInUse )
+        {
+        TInt64 totalNumOfSongsCanFit = aVol.iFree / KMPEstimatedSongInBytes;
+        MPX_DEBUG2("-->CMPXDbManager::CalculateInitalDummyDBSize aVol.iFree=%Lu", aVol.iFree );
+        MPX_DEBUG2("-->CMPXDbManager::CalculateInitalDummyDBSize totalNumOfSongsCanFit=%Lu", totalNumOfSongsCanFit );
+        TInt64 estimatedSize = totalNumOfSongsCanFit * (TInt64) KMPEstimatedSizePerDBEntry + aOrigDbSize;
+        MPX_DEBUG2("-->CMPXDbManager::CalculateInitalDummyDBSize (MTP case) estimated DB size from calculation=%Lu", estimatedSize );
+        if ( estimatedSize > iMaximumAllowedRAMDiskSpaceToCopy )
+            {
+            MPX_DEBUG2("<--CMPXDbManager::CalculateInitalDummyDBSize returned iMaximumAllowedRAMDiskSpaceToCopy %d", iMaximumAllowedRAMDiskSpaceToCopy);
+            return iMaximumAllowedRAMDiskSpaceToCopy;
+            }
+        else
+            {
+            MPX_DEBUG2("<--CMPXDbManager::CalculateInitalDummyDBSize returned %Lu", estimatedSize );
+            return estimatedSize;
+            }
+        }
+    else
+        {
+        TInt64 totalNumOfSongsCanFit = aVol.iSize / KMPEstimatedSongInBytes;
+        TInt64 estimatedSize = totalNumOfSongsCanFit * (TInt64) KMPEstimatedSizePerDBEntry + aOrigDbSize;
+        MPX_DEBUG2("-->CMPXDbManager::CalculateInitalDummyDBSize estimated DB size from calculation=%Lu", estimatedSize );
+        if ( estimatedSize > iMaximumAllowedRAMDiskSpaceToCopy )
+            {
+            MPX_DEBUG1("<--CMPXDbManager::CalculateInitalDummyDBSize");
+            // If estimated size is larger than expected free RAM size, 
+            // and if the RAM size is larger than free disk space,
+            // then use free disk space. 1*KMPMegaByte prevent MP to use up all diskspace
+            //return iMaximumAllowedRAMDiskSpaceToCopy > aVol.iFree - 1*KMPMegaByte  
+            //    ? aVol.iFree - 1*KMPMegaByte : iMaximumAllowedRAMDiskSpaceToCopy;
+            return iMaximumAllowedRAMDiskSpaceToCopy;
+            }
+        else
+            {
+            MPX_DEBUG1("<--CMPXDbManager::CalculateInitalDummyDBSize");
+            // If estimated size is larger than disk free size, use free diskspace size,            
+            //return estimatedSize > aVol.iFree - 1*KMPMegaByte
+            //    ? aVol.iFree - 1*KMPMegaByte : estimatedSize;
+            return estimatedSize;
+            }
+        }
+    
+#endif //__RAMDISK_PERF_ENABLE    
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::GetDatabaseIndex
+// ---------------------------------------------------------------------------
+//
+TInt CMPXDbManager::GetDatabaseIndex(TInt aDrive) 
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG2("-->CMPXDbManager::GetDatabaseIndex %d", aDrive );
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        if ( iDatabaseHandles[i].iDrive == aDrive )
+            {
+            return i;
+            }
+        }    
+#endif //__RAMDISK_PERF_ENABLE    
+    MPX_DEBUG1("<--CMPXDbManager::GetDatabaseIndex returned -1");
+    return -1;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::EnsureRamSpaceL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXDbManager::EnsureRamSpaceL() 
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::EnsureRamSpaceL");
+
+    if ( iRAMInUse )
+        {
+        TVolumeInfo vol;
+        TInt driveIndex;
+        RFs::CharToDrive( iRAMDrive, driveIndex );
+
+        TInt errRAM = iFs.Volume( vol, driveIndex );
+        if ( errRAM == KErrNone && vol.iFree < KMPMinimumRAMSizeToRun )
+            {
+            // RAM not enough, copy back to normal drive and continue to harvest.
+            MPX_DEBUG1("CMPXDbManager::EnsureRamSpaceL RAM diskspace is full, copy dbs back");
+            CopyDBsFromRamL();
+            }
+        else
+            {
+            TInt size=0;
+            TInt err = GetTotalRamDatabasesSizeL(size);
+            if ( err || (size > iMaximumAllowedRAMDiskSpaceToCopy) )
+                {
+                // Databases using too much RAM space, copy back to normal drive and continue to harvest.
+                if ( err )
+                    {
+                    MPX_DEBUG2("CMPXDbManager::EnsureRamSpaceL Get DBs Size Err = %d, copy dbs back", err);
+                    }
+                else
+                    {
+                    MPX_DEBUG2("CMPXDbManager::EnsureRamSpaceL DBs using too much RAM space size = %d, copy dbs back", size);
+                    }
+                CopyDBsFromRamL();
+                }
+            }
+        }
+    MPX_DEBUG1("<--CMPXDbManager::EnsureRamSpaceL");
+#endif //__RAMDISK_PERF_ENABLE    
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::EnsureDiskSpaceL
+// ---------------------------------------------------------------------------
+//
+void CMPXDbManager::EnsureDiskSpaceL(TInt aDrive) 
+    {
+    MPX_DEBUG2("-->CMPXDbManager::EnsureDiskSpaceL for drive %d", aDrive);
+    // handle the case of C drive
+    TDriveUnit drive(aDrive);
+    TDriveUnit cdrive(KRootDrive());
+
+    if(drive == cdrive)
+        {
+        if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, 0, aDrive))
+            {
+            MPX_DEBUG1("CMPXDbManager::EnsureDiskSpaceL Error diskspace full");
+            User::Leave(KErrDiskFull);
+            }
+
+        return;
+        }
+
+    // handle other drives (eg. removable EDriveE)
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count; ++i)
+        {
+        DatabaseHandle& database = iDatabaseHandles[i];
+        if (((KDbManagerAllDrives == aDrive) ||
+            (aDrive == database.iDrive)) &&
+            database.iOpen
+#ifdef __RAMDISK_PERF_ENABLE
+            && !database.iUseRAMdb
+#endif
+            )
+            {
+            if (SysUtil::DiskSpaceBelowCriticalLevelL(&iFs, 0,
+                database.iDrive))
+                {
+                MPX_DEBUG1("CMPXDbManager::EnsureDiskSpaceL Error diskspace full");
+                User::Leave(KErrDiskFull);
+                }
+            }
+
+        if (aDrive == database.iDrive)
+            {
+            // exit if just one drive to check
+            break;
+            }
+        }
+    MPX_DEBUG1("<--CMPXDbManager::EnsureDiskSpaceL");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CMPXDbManager::DoBackupDBs
+// ---------------------------------------------------------------------------
+//
+/*EXPORT_C void CMPXDbManager::BackupDBsL()
+    {
+#ifdef __RAMDISK_PERF_ENABLE
+    MPX_DEBUG1("-->CMPXDbManager::BackupDBsL");
+
+    TInt transactionCount = iTransactionCount;
+    if (iTransactionCount > 0) 
+        {
+        iTransactionCount = 0;
+        DoCommitL();
+        }
+    
+    TInt count(iDatabaseHandles.Count());
+    for (TInt i = 0; i < count && iDatabaseHandles[i].iUseRAMdb ; ++i)
+        {
+        CloseDatabaseAtIndexL( i );            
+
+        TInt err= BaflUtils::CopyFile(iFs, 
+            iDatabaseHandles[i].iTargetFullFilePath->Des(), 
+            iDatabaseHandles[i].iOrigFullFilePath->Des());
+
+        MPX_DEBUG2("CMPXDbManager::BackupDBsL err = %d", err);     
+
+        OpenDatabaseAtIndexL( i );      
+        }
+        
+    if (transactionCount > 0) 
+        {
+        DoBeginL();
+        iTransactionCount = transactionCount;
+        }
+    MPX_DEBUG1("<--CMPXDbManager::BackupDBsL");
+#endif //__RAMDISK_PERF_ENABLE    
+    }*/
+    
+// ---------------------------------------------------------------------------
+// CMPXDbManager::GetTotalDatabasesSize
+// ---------------------------------------------------------------------------
+//
+TInt CMPXDbManager::GetTotalDatabasesSize(TInt& aSize)
+    {
+    MPX_FUNC("CMPXDbManager::GetTotalDatabasesSize");
+    TInt err = KErrNotSupported;
+#ifdef __RAMDISK_PERF_ENABLE
+    TInt size=0;
+    TInt count(iDatabaseHandles.Count());
+    err = KErrNone;
+    for ( TInt i = 0; i < count ; ++i )
+        {
+        // Generate database name.
+        TFileName dbFilename;
+        TDriveUnit drive(iDatabaseHandles[i].iDrive);
+        dbFilename.Append(drive.Name());
+        dbFilename.Append(KDBFilePath);
+        TFileName filename;            
+        filename.Format(KSecurePath, User::Identity().iUid, iDbFile); //x:\private\10281e17\[sldfdsf]mpxv2_5.db
+        dbFilename.Append(filename);
+        MPX_DEBUG2("CMPXDbManager::GetTotalDatabasesSize - Database name = %S", &dbFilename);
+        TEntry entry;
+        err = iFs.Entry( dbFilename, entry );
+        if (err == KErrNotFound || err == KErrNotReady )
+            {
+            MPX_DEBUG3("CMPXDbManager::GetTotalDatabasesSize - Ignored %S, error = %d", &dbFilename, err);
+            err = KErrNone;
+            continue;
+            }
+        if ( err != KErrNone )
+            {
+            break;
+            }
+        MPX_DEBUG3("CMPXDbManager::GetTotalDatabasesSize - Size of Db %S = %d", &dbFilename, entry.iSize);
+        // sum up size
+        size += entry.iSize;
+        }
+    aSize = size;
+    MPX_DEBUG2("CMPXDbManager::GetTotalDatabasesSize - Total Size of Dbs = %d", size);
+    
+#endif //__RAMDISK_PERF_ENABLE    
+    MPX_DEBUG2("CMPXDbManager::GetTotalDatabasesSize - Return err = %d", err);
+    return err;
+    }
+    
+// ---------------------------------------------------------------------------
+// CMPXDbManager::GetTotalRamDatabasesSize
+// ---------------------------------------------------------------------------
+//
+TInt CMPXDbManager::GetTotalRamDatabasesSizeL(TInt& aSize)
+    {
+    MPX_FUNC("CMPXDbManager::GetTotalRamDatabasesSize");
+    TInt err = KErrNotSupported;
+#ifdef __RAMDISK_PERF_ENABLE
+    TInt size=0;
+    TInt count(iDatabaseHandles.Count());
+    err = KErrNone;
+    for ( TInt i = 0; i < count ; ++i )
+        {
+        // make sure this db is in ram drive.
+        if ( !iDatabaseHandles[i].iUseRAMdb )
+            {
+            continue;
+            }
+        // Generate database name.
+        TFileName dbFilename;
+        dbFilename.Append(iRAMFolder);
+        TBuf<2> d;
+        TDriveUnit drive(iDatabaseHandles[i].iDrive);
+        d.Append(drive.Name());
+        HBufC* temp = HBufC::NewLC(KMaxFileName);
+        temp->Des().Append(d.Left(1));
+        temp->Des().Append(iDbFile->Des());
+        TFileName filename;            
+        filename.Format(KSecurePath, User::Identity().iUid, temp);
+        CleanupStack::PopAndDestroy(temp);
+        dbFilename.Append(filename);
+        MPX_DEBUG2("CMPXDbManager::GetTotalRamDatabasesSizeL - Database name = %S", &dbFilename);
+        TEntry entry;
+        err = iFs.Entry( dbFilename, entry );
+        if ( (err != KErrNone) && (err != KErrNotFound) )
+            {
+            break;
+            }
+        MPX_DEBUG3("CMPXDbManager::GetTotalRamDatabasesSizeL - Size of Db %S = %d", &dbFilename, entry.iSize);
+        // sum up size
+        size += entry.iSize;
+        }
+    aSize = size;
+    MPX_DEBUG2("CMPXDbManager::GetTotalRamDatabasesSizeL - Total Size of Dbs = %d", size);
+#endif //__RAMDISK_PERF_ENABLE    
+    MPX_DEBUG2("CMPXDbManager::GetTotalRamDatabasesSizeL - Return err = %d", err);
+    return err;
+    }
+
+// ----------------------------------------------------------------------------
+// Creates the absolute database filename on a specified drive.
+// ----------------------------------------------------------------------------
+//
+HBufC* CMPXDbManager::CreateFullFilenameL(TDriveUnit aDrive)
+    {
+    MPX_FUNC("CMPXDbManager::CreateFullFilenameL");
+
+    HBufC* filename = HBufC::NewL(KMaxFileName);
+    const TDesC& securefilePath = KSecureFilePath;
+    TDriveUnit cdrive(KRootDrive());
+
+#ifdef __RAMDISK_PERF_ENABLE
+    TInt index(GetDatabaseIndex((TInt)aDrive));    
+    if ( index >=0 && iDatabaseHandles[index].iUseRAMdb && aDrive != cdrive )
+        {
+        MPX_DEBUG1("CMPXDbManager::CreateFullFilenameL - use RAMDisk");
+        TFileName path;
+        path.Append(iRAMDrive);
+        path.Append(_L(":"));
+        path.Append(KDBFilePath);
+        TBuf<2> d;
+        d.Append(aDrive.Name());
+        TFileName temp;
+        temp.Append(d.Left(1)); // attach original drive name
+        temp.Append(iDbFile->Des()); 
+        filename->Des().Format(securefilePath, &path, User::Identity().iUid, &temp);
+        MPX_DEBUG3("CMPXDbManager::CreateFullFilenameL - path=%S filename=%S", &path, filename);
+        }
+    else
+#endif //__RAMDISK_PERF_ENABLE
+        {
+        MPX_DEBUG1("CMPXDbManager::CreateFullFilenameL - use normal drive");
+        TFileName dbPath;
+        dbPath.Append(aDrive.Name());
+        dbPath.Append(KDBFilePath);
+        filename->Des().Format(securefilePath, &dbPath, User::Identity().iUid, iDbFile);
+        }
+    
+    MPX_DEBUG2("CMPXDbManager::CreateFullFilenameL filename = %S", filename); 
+    return filename;
+    }
+
+// End of File