diff -r 14979e23cb5e -r 3de6c4cf6b67 mpxplugins/serviceplugins/collectionplugins/mpxsqlitedbcommon/src/mpxdbmanager.cpp --- /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 +#include +#include +// PREQ2536 the files sqlrowsetutil.h and sqlrowsetutil.cpp has been removed +//#ifdef __WINSCW__ +//#include +//#endif +#include +#ifdef __RAMDISK_PERF_ENABLE +#include +#include +#include +#endif //__RAMDISK_PERF_ENABLE + +#include + +#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( 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; iClose(); + } + 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 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(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(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(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: +// +// UNION ALL ... +// +// 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 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 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 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 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 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 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 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 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; iDes(); + 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; iClose(); + } + 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("")); + 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& 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 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 = / 2 MB; +// metadataSize = totalNumOfSongsCanFit * 3000B +// estimatedDBSize = metadataSize + ; +// dummyDBSize = MIN (iMaximumAllowedRAMDiskSpaceToCopy , estimatedDBSize ) + +//b) Harvesting case +//------------------- +// totalNumOfSongsCanFit = / 2 MB +// metadataSize = totalNumOfSongsCanFit * 3000B +// estimatedSize = metadataSize+ +// freeDiskSpace = - 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