diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/LogServ/src/LogServDatabaseMarshall.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loggingservices/eventlogger/LogServ/src/LogServDatabaseMarshall.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,622 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include "LogServDatabaseMarshall.h" +#include "logservpanic.h" +#include "LogServCacheConfig.h" +#include "LogServCacheStrings.h" +#include "LogServCacheTypes.h" +#include "LogServBackupInterface.h" +#include "LogServResourceInterpreter.h" +#include "LogServDatabaseChangeInterface.h" +#include +#include "LogServSqlStrings.h" +#include "LOGREPDEFS.H" + + +// Constants +const TInt KExpectedNumberOfTables = 4; // Should match the code in CreateTablesL + +// Literal constants +_LIT(KLogDatabaseName,"Logdbu.dat"); + + + +///////////////////////////////////////////////////////////////////////////////////////// +// -----> CLogServDatabaseMarshall (source) +///////////////////////////////////////////////////////////////////////////////////////// + +CLogServDatabaseMarshall::CLogServDatabaseMarshall(RFs& aFsSession, + CLogServResourceInterpreter& aResourceInterface, + MLogServBackupInterface& aBackupInterface) +: iFsSession(aFsSession), iResourceInterface(aResourceInterface), iBackupInterface(aBackupInterface) + { + } + +CLogServDatabaseMarshall::~CLogServDatabaseMarshall() + { + iBackupInterface.BIObserverRemove(*this); + // + delete iDatabaseName; + delete iCacheStrings; + delete iCacheTypes; + delete iCacheConfig; + delete iSecurity; + delete iEventType; + // + iDatabase.Close(); + iStandardTypeUids.Close(); + } + +void CLogServDatabaseMarshall::ConstructL() + { + iBackupInterface.BIObserverAddL(*this, MLogServBackupInterface::EObjectDatabaseMarshall); + // + iSecurity = CLogServSecurity::NewL(iResourceInterface); + // + iEventType = CLogEventType::NewL(); + + DatabaseLocateL(); + DatabaseOpenL(); + RestoreStandardTypesL(); + + iCacheTypes->CopyStandardTypeUidsL(iStandardTypeUids); + } + +CLogServDatabaseMarshall* CLogServDatabaseMarshall::NewL(RFs& aFsSession, + CLogServResourceInterpreter& aResourceInterface, + MLogServBackupInterface& aBackupInterface) + { + CLogServDatabaseMarshall* self = new(ELeave) CLogServDatabaseMarshall(aFsSession, aResourceInterface, aBackupInterface); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +TInt CLogServDatabaseMarshall::DTIBegin() + { + const TInt backupError = iBackupInterface.BIErrorValueForCurrentState(); + if (backupError != KErrNone) + return backupError; + + __ASSERT_DEBUG(!iDatabase.InTransaction(), Panic(ELogBeginInTransaction)); + return iDatabase.Begin(); + } + +TInt CLogServDatabaseMarshall::DTICommitAndEnd() + { + __ASSERT_DEBUG(iDatabase.InTransaction(), Panic(ELogCommitNotInTransaction)); + TInt err = iDatabase.Commit(); + if (err == KErrNone && iCacheStrings != NULL) + { + iCacheStrings->Commit(); + } + return err; + } + +void CLogServDatabaseMarshall::DTIRollBack() + { + __ASSERT_DEBUG(iDatabase.InTransaction(), Panic(ELogRollbackNotInTransaction)); + iDatabase.Rollback(); + if (iCacheStrings != NULL) + { + iCacheStrings->Rollback(); + } + } + +TInt CLogServDatabaseMarshall::DTIExecuteSql(const TDesC& aStatement, TDbTextComparison aComparison) + { + return iDatabase.Execute(aStatement, aComparison); + } + +TBool CLogServDatabaseMarshall::DTIInTransaction() const + { + return iDatabase.InTransaction(); + } + +TBool CLogServDatabaseMarshall::DTIDatabaseIsDamaged() const + { + return iDatabase.IsDamaged(); + } + +CLogServResourceInterpreter& CLogServDatabaseMarshall::DTIResourceInterface() const + { + return iResourceInterface; + } + +MLogServDatabaseChangeInterface& CLogServDatabaseMarshall::DTIChangeInterface() const + { + __ASSERT_ALWAYS(iChangeInterface, Panic(ELogNoChangeInterfacePointer)); + return *iChangeInterface; + } + +CLogServCacheStrings& CLogServDatabaseMarshall::DTICacheStrings() const + { + __ASSERT_ALWAYS(iCacheStrings, Panic(ELogCacheAccessDuringBackupStrings)); + return *iCacheStrings; + } + +CLogServCacheTypes& CLogServDatabaseMarshall::DTICacheTypes() const + { + __ASSERT_ALWAYS(iCacheTypes, Panic(ELogCacheAccessDuringBackupTypes)); + return *iCacheTypes; + } + +CLogServCacheConfig& CLogServDatabaseMarshall::DTICacheConfig() const + { + __ASSERT_ALWAYS(iCacheConfig, Panic(ELogCacheAccessDuringBackupConfig)); + return *iCacheConfig; + } + +RDbDatabase& CLogServDatabaseMarshall::DTIDatabase() + { + return iDatabase; + } + +TBool CLogServDatabaseMarshall::DTIIsAllowed(TEventOp aEventOp, const RMessage2& aMessage, TUid aEventType, const char* aDiagnostic) const + { + return iSecurity->IsAllowed(aMessage, aEventType, aEventOp, aDiagnostic); + } + +const RArray& CLogServDatabaseMarshall::DTIUidsOfStandardTypes() + { + return iStandardTypeUids; + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +void CLogServDatabaseMarshall::BOHandleEventL(TLogServBackupEvent aEvent) + { + switch(aEvent) + { + case EBackupStarting: + { + //Destroy config, types and strings caches + delete iCacheConfig; + iCacheConfig = NULL; + delete iCacheStrings; + iCacheStrings = NULL; + delete iCacheTypes; + iCacheTypes = NULL; + //Close the database + iDatabase.Close(); + } + break; + + case EBackupEnded: + { + // Re-open the database and create config, types and strings caches + DatabaseOpenL(); + // reset views as a different database is being restored + DTIChangeInterface().DCISubmitGlobalChangeContextL(KLogClientChangeEventRefreshView); + } + break; + default: + break; + } + } + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + +void CLogServDatabaseMarshall::DatabaseLocateL() + { + // Get drive for database + TDriveUnit driveUnit(static_cast(RFs::GetSystemDrive())); + TDriveName name(driveUnit.Name()); + + TFileName path; + iFsSession.PrivatePath(path); + + // Ensure database path exists + TParse parse; + User::LeaveIfError(parse.Set(path, &name, NULL)); + path = parse.FullName(); + + TInt error = iFsSession.MkDirAll(path); + if (error != KErrAlreadyExists) + User::LeaveIfError(error); + + path += KLogDatabaseName; + iDatabaseName = path.AllocL(); + } + +/** +Opens the LogEng database. +@return KErrNone, If the "database open" operation completes successfully. + If the "database open" operation fails the function returns the repported error code. + KErrCorrupt, If the database is opened successfully but is damaged, then the function returns KErrCorrupt. +*/ +TInt CLogServDatabaseMarshall::DoDbOpen() + { + LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - attempting to open db: %S", iDatabaseName); +#ifdef LOGGING_ENABLED + TEntry entry; + if (iFsSession.Entry(*iDatabaseName, entry) == KErrNone) + { + LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - Database file: %S DOES exist", iDatabaseName); + } + else + { + LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - Database file: %S NOT FOUND", iDatabaseName); + } +#endif + // Open database + TInt err = iDatabase.Open(iFsSession, DatabaseName()); + LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - attempting to open DMBS database resulted in error: %d", error); + // Check if the database is damaged. If it is set the error to KErrCorrupt so that it + // will be deleted. + if ((err == KErrNone) && iDatabase.IsDamaged()) + { + err = KErrCorrupt; + } + return err; + } + +/** +Check if the database table count is the expected one - KExpectedNumberOfTables. +@return True, The database tables count is KExpectedNumberOfTables, + False, The database tables count is not KExpectedNumberOfTables; +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors or + other system-wide error codes. +*/ +TBool CLogServDatabaseMarshall::DbTableCntCheckL() + { + CDbTableNames* tables = iDatabase.TableNamesL(); + TInt numberOfTables = tables->Count(); + delete tables; + LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - Number of tables: %d", numberOfTables); + return numberOfTables == KExpectedNumberOfTables; + } + +/** +Alters the "Event" table if the number column length is not KLogMaxNumberLength. +@return KErrNone, The "alter" operation has completed successfully, system wide or database specific error code otherwise. +*/ +TInt CLogServDatabaseMarshall::AlterEventTblIfOldFmt(CDbColSet& aEventTblColSet) + { + const TDbCol* numberCol = aEventTblColSet.Col(KLogFieldEventNumberString); + __ASSERT_DEBUG(numberCol != NULL, User::Invariant()); + TInt err = KErrNone; + // check the column width is correct + if(numberCol->iMaxLength != KLogMaxNumberLength) + { + //The column width is not correct, so this is an old format database. + //Modify the database so the number length is KLogMaxNumberLength. + (const_cast (numberCol))->iMaxLength = KLogMaxNumberLength; + err = iDatabase.AlterTable(KLogNameEventString, aEventTblColSet); + } + return err; + } + +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM + +/** +Alters the "Event" table if the the table does not have "SimId" column. +@return KErrNone, The "alter" operation has completed successfully, system wide or database specific error code otherwise. +@leave KErrNoMemory, an out of memory condition has occurred; + Some other failure codes, not related to the "alter" opertaion. +*/ +TInt CLogServDatabaseMarshall::AlterEventTblIfNoSimIdL(CDbColSet& aEventTblColSet) + {//Compiled only when SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM macro is defined + const TDbCol* simIdCol = aEventTblColSet.Col(KLogFieldEventSimId); + TInt err = KErrNone; + if(!simIdCol) + { + TDbCol col(KLogFieldEventSimId, EDbColUint32); + aEventTblColSet.AddL(col); + err = iDatabase.AlterTable(KLogNameEventString, aEventTblColSet); + } + return err; + } + +#endif + +/** +Checks the database structure and alters the tables if that's an old format database. +@return KErrNone, The "alter" operation has completed successfully, system wide or database specific error code otherwise. +@leave KErrNoMemory, an out of memory condition has occurred; + Some other failure codes, not related to the "alter" opertaion. +*/ +TInt CLogServDatabaseMarshall::AlterDbIfOldFmtL() + { + CDbColSet* tableEventCol = iDatabase.ColSetL(KLogNameEventString); + CleanupStack::PushL(tableEventCol); + //Check for old format database which had MaxNumberLength =32 + TInt err = AlterEventTblIfOldFmt(*tableEventCol); +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM + //Check if the "SimId" column is present + if(err == KErrNone) + { + err = AlterEventTblIfNoSimIdL(*tableEventCol); + } +#endif + CleanupStack::PopAndDestroy(tableEventCol); + return err; + } + +/** +Closes and deletes the LogEng database. In _DEBUG builds the "delete file" error will be printed out. +*/ +void CLogServDatabaseMarshall::DbDelete() + { + iDatabase.Close(); +#ifdef _DEBUG + //Do not remove the statement bellow. In _DEBUG builds it forms a single "TInt err2 = iFsSession.Delete(DatabaseName());" statement. + TInt err2 = +#endif + iFsSession.Delete(DatabaseName()); +#ifdef _DEBUG + if((err2 != KErrNone) && (err2 != KErrNotFound)) + { + RDebug::Print(_L("CLogServDatabaseMarshall::DatabaseOpenL() - Failed to delete file. Error = %d"), err2); + } +#endif + } + +/** +Attempts to create the LogEng database and tables. +@return KErrNoNone, The database was created successfully, system wide or database specific error otherwise. +*/ +TInt CLogServDatabaseMarshall::DbCreate() + { + // Try and create the database + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - trying to create database"); + TRAPD(err, DatabaseCreateL(DatabaseName())); + LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - creation error was: %d", error); + return err; + } + +/** +Creates config and string LogEng caches. Finishes the initialization of the event types cache. +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors or + other system-wide error codes. +*/ +void CLogServDatabaseMarshall::CreateCachesL() + { + // Create other cache objects (these require the database to be already opened) + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - creating config cache"); + iCacheConfig = CLogServCacheConfig::NewL(*this); + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - creating string cache"); + iCacheStrings = CLogServCacheStrings::NewL(*this); + // Finish the type cache initialization + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - initializing type cache"); + iCacheTypes->InitializeL(); + } + +void CLogServDatabaseMarshall::DatabaseOpenL() + { + // Create the cache objects - objects need to be put into the cache as + // soon as the database is open. + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - creating type cache"); + iCacheTypes = CLogServCacheTypes::NewL(*this); + TInt err = DoDbOpen(); + // Check we have the expected number of tables + if(err == KErrNone && !DbTableCntCheckL()) + { + err = KErrCorrupt; + } + // Check a compaction can be performed. If it can't it indicates a serious problem? + if(err == KErrNone && (err = iDatabase.Compact()) != KErrNone) + { + err = KErrCorrupt; + } + if(err == KErrNone) + { + err = CLogServDatabaseMarshall::AlterDbIfOldFmtL(); + } + // If the database failed to open, delete and recreate. + if(err == KErrNotFound || err == KErrCorrupt || err == KErrArgument || err == KErrEof) + { + DbDelete(); + // Try and create the database + err = DbCreate(); + if(err != KErrNone) + { + DbDelete(); + } + } + User::LeaveIfError(err); + CreateCachesL(); + // At this point, its safe to tell the backup interface what file it has to watch + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - registering database filename with backup interface"); + iBackupInterface.BISetDatabaseNameL(DatabaseName()); + LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - end"); + } + +void CLogServDatabaseMarshall::DatabaseCreateL(const TDesC& aName) + { + User::LeaveIfError(iDatabase.Replace(iFsSession, aName)); + CreateTablesL(); + } + +// Note: Number of tables HAS to match KExpectedNumberOfTables +void CLogServDatabaseMarshall::CreateTablesL() + { + DTIBeginWithRollBackProtectionLC(); + + // Create event table + TheSql.Format(KLogTableEventString, KLogMaxRemotePartyLength, KLogMaxSubjectLength, KLogMaxNumberLength); + User::LeaveIfError(iDatabase.Execute(TheSql)); + MakeColumnAutoIncremetingL(KLogNameEventString, KLogFieldIdString); + + // Create event type table + TheSql.Format(KLogTableTypeString, KLogMaxDescriptionLength); + User::LeaveIfError(iDatabase.Execute(TheSql)); + MakeColumnAutoIncremetingL(KLogNameTypeString, KLogFieldIdString); + + // Create string list table + TheSql.Format(KLogTableStringString, KLogMaxSharedStringLength); + User::LeaveIfError(iDatabase.Execute(TheSql)); + MakeColumnAutoIncremetingL(KLogNameStringString, KLogFieldIdString); + + // Create configuration table + TheSql.Copy(KLogTableConfigString); + User::LeaveIfError(iDatabase.Execute(TheSql)); + + // Create the index + CreateIndiciesL(); + + // Set the initial configuration + CreateConfigurationL(); + + // Load standard event types + CreateTypesL(); + + DTICommitAndCancelRollbackProtectionL(); + } + +void CLogServDatabaseMarshall::CreateTypesL(TBool aReadOnly) + { + // Get the array size + TResourceReader reader; + iResourceInterface.CreateResourceReaderLC(reader, R_LOG_INITIAL_EVENTS, CLogServResourceInterpreter::ELogWrap); + + // Create them + DTICacheTypes().CreateStandardTypesL(reader, aReadOnly); + + CleanupStack::PopAndDestroy(); // reader + } + +void CLogServDatabaseMarshall::CreateIndiciesL() + { + // Get the array size + TResourceReader reader; + iResourceInterface.CreateResourceReaderLC(reader, R_LOG_INDEXES, CLogServResourceInterpreter::ELogWrap); + + const TInt indexes = reader.ReadInt16(); + + // Read in the array + for(TInt c1 = 0; c1 < indexes; c1++) + { + const TPtrC name(reader.ReadTPtrC()); + const TPtrC table(reader.ReadTPtrC()); + + // Get the number of keys + const TInt keys = reader.ReadInt16(); + + CDbKey* key = CDbKey::NewLC(); + + for(TInt c2 = 0; c2 < keys; c2++) + { + TPtrC col = reader.ReadTPtrC(); + TUint order = reader.ReadUint16(); + TInt len = reader.ReadInt16(); + + // Add the key + key->AddL(TDbKeyCol(col, len, (TDbKeyCol::TOrder)order)); + } + + // Make key unique if required + if (reader.ReadInt8()) + key->MakeUnique(); + + // Set comparison + const TDbTextComparison comparison = static_cast(reader.ReadInt8()); + key->SetComparison(comparison); + + // Create the index + User::LeaveIfError(iDatabase.CreateIndex(name, table, *key)); + + CleanupStack::PopAndDestroy(key); + } + + CleanupStack::PopAndDestroy(); // reader + } + +void CLogServDatabaseMarshall::CreateConfigurationL() + { + // Load the resource/repository file default configuration + // The precedence is given to the reading from the repository file. + TLogConfig config; + + CRepository* repository = NULL; + TRAPD(res, repository = CRepository::NewL(KUidLogengRepository)); + if (res == KErrNone) + { + CleanupStack::PushL(repository); + ReadRepositoryFileConfigurationL(config, *repository); + CleanupStack::PopAndDestroy(repository); + } + else if (res == KErrCorrupt) + { + User::Leave(res); + } + else + { + ReadResourceFileConfigurationL(config); + } + // Insert the column + TheSql.Format(KLogSqlInsertConfigString, config.iMaxLogSize, config.iMaxRecentLogSize, config.iMaxEventAge); + User::LeaveIfError(iDatabase.Execute(TheSql)); + } + +void CLogServDatabaseMarshall::ReadRepositoryFileConfigurationL(TLogConfig& aConfig, CRepository& repository) const + { + TInt maxLogSize; + TInt maxRecentLogSize; + TInt maxEventAge; + // + User::LeaveIfError(repository.Get(KMaxLogSizeRepKey, maxLogSize)); + aConfig.iMaxLogSize = static_cast (maxLogSize); + User::LeaveIfError(repository.Get(KMaxRecentLogSizeRepKey, maxRecentLogSize)); + aConfig.iMaxRecentLogSize = static_cast (maxRecentLogSize); + User::LeaveIfError(repository.Get(KMaxEventAgeRepKey, maxEventAge)); + aConfig.iMaxEventAge = static_cast (maxEventAge); + } + +void CLogServDatabaseMarshall::ReadResourceFileConfigurationL(TLogConfig& aConfig) const + { + TResourceReader reader; + iResourceInterface.CreateResourceReaderLC(reader, R_LOG_INITIAL_CONFIG, CLogServResourceInterpreter::ELogWrap); + // + aConfig.iMaxLogSize = static_cast(reader.ReadUint16()); + aConfig.iMaxRecentLogSize = static_cast(reader.ReadUint8()); + aConfig.iMaxEventAge = static_cast(reader.ReadUint32()); + // + CleanupStack::PopAndDestroy(); // reader + } + +void CLogServDatabaseMarshall::MakeColumnAutoIncremetingL(const TDesC& aTable, const TDesC& aColumn) + { + CDbColSet* newTable = iDatabase.ColSetL(aTable); + CleanupStack::PushL(newTable); + + const TDbCol* oldCol = newTable->Col(aColumn); + __ASSERT_DEBUG(oldCol != NULL, Panic(ELogNoSuchColumn)); + + TDbCol newCol = *oldCol; + newCol.iAttributes |= TDbCol::EAutoIncrement; + + newTable->Remove(aColumn); + newTable->AddL(newCol); + + User::LeaveIfError(iDatabase.DropTable(aTable)); + User::LeaveIfError(iDatabase.CreateTable(aTable, *newTable)); + + CleanupStack::PopAndDestroy(newTable); + } +