os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServDatabaseMarshall.cpp
First public contribution.
1 // Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <logclientchangeobserver.h>
17 #include "LogServDatabaseMarshall.h"
18 #include "logservpanic.h"
19 #include "LogServCacheConfig.h"
20 #include "LogServCacheStrings.h"
21 #include "LogServCacheTypes.h"
22 #include "LogServBackupInterface.h"
23 #include "LogServResourceInterpreter.h"
24 #include "LogServDatabaseChangeInterface.h"
25 #include "LogServSqlStrings.h"
26 #include "LOGREPDEFS.H"
30 const TInt KExpectedNumberOfTables = 4; // Should match the code in CreateTablesL
33 _LIT(KLogDatabaseName,"Logdbu.dat");
37 /////////////////////////////////////////////////////////////////////////////////////////
38 // -----> CLogServDatabaseMarshall (source)
39 /////////////////////////////////////////////////////////////////////////////////////////
41 CLogServDatabaseMarshall::CLogServDatabaseMarshall(RFs& aFsSession,
42 CLogServResourceInterpreter& aResourceInterface,
43 MLogServBackupInterface& aBackupInterface)
44 : iFsSession(aFsSession), iResourceInterface(aResourceInterface), iBackupInterface(aBackupInterface)
48 CLogServDatabaseMarshall::~CLogServDatabaseMarshall()
50 iBackupInterface.BIObserverRemove(*this);
60 iStandardTypeUids.Close();
63 void CLogServDatabaseMarshall::ConstructL()
65 iBackupInterface.BIObserverAddL(*this, MLogServBackupInterface::EObjectDatabaseMarshall);
67 iSecurity = CLogServSecurity::NewL(iResourceInterface);
69 iEventType = CLogEventType::NewL();
73 RestoreStandardTypesL();
75 iCacheTypes->CopyStandardTypeUidsL(iStandardTypeUids);
78 CLogServDatabaseMarshall* CLogServDatabaseMarshall::NewL(RFs& aFsSession,
79 CLogServResourceInterpreter& aResourceInterface,
80 MLogServBackupInterface& aBackupInterface)
82 CLogServDatabaseMarshall* self = new(ELeave) CLogServDatabaseMarshall(aFsSession, aResourceInterface, aBackupInterface);
83 CleanupStack::PushL(self);
85 CleanupStack::Pop(self);
89 /////////////////////////////////////////////////////////////////////////////////////////
90 /////////////////////////////////////////////////////////////////////////////////////////
91 /////////////////////////////////////////////////////////////////////////////////////////
93 TInt CLogServDatabaseMarshall::DTIBegin()
95 const TInt backupError = iBackupInterface.BIErrorValueForCurrentState();
96 if (backupError != KErrNone)
99 __ASSERT_DEBUG(!iDatabase.InTransaction(), Panic(ELogBeginInTransaction));
100 return iDatabase.Begin();
103 TInt CLogServDatabaseMarshall::DTICommitAndEnd()
105 __ASSERT_DEBUG(iDatabase.InTransaction(), Panic(ELogCommitNotInTransaction));
106 TInt err = iDatabase.Commit();
107 if (err == KErrNone && iCacheStrings != NULL)
109 iCacheStrings->Commit();
114 void CLogServDatabaseMarshall::DTIRollBack()
116 __ASSERT_DEBUG(iDatabase.InTransaction(), Panic(ELogRollbackNotInTransaction));
117 iDatabase.Rollback();
118 if (iCacheStrings != NULL)
120 iCacheStrings->Rollback();
124 TInt CLogServDatabaseMarshall::DTIExecuteSql(const TDesC& aStatement, TDbTextComparison aComparison)
126 return iDatabase.Execute(aStatement, aComparison);
129 TBool CLogServDatabaseMarshall::DTIInTransaction() const
131 return iDatabase.InTransaction();
134 TBool CLogServDatabaseMarshall::DTIDatabaseIsDamaged() const
136 return iDatabase.IsDamaged();
139 CLogServResourceInterpreter& CLogServDatabaseMarshall::DTIResourceInterface() const
141 return iResourceInterface;
144 MLogServDatabaseChangeInterface& CLogServDatabaseMarshall::DTIChangeInterface() const
146 __ASSERT_ALWAYS(iChangeInterface, Panic(ELogNoChangeInterfacePointer));
147 return *iChangeInterface;
150 CLogServCacheStrings& CLogServDatabaseMarshall::DTICacheStrings() const
152 __ASSERT_ALWAYS(iCacheStrings, Panic(ELogCacheAccessDuringBackupStrings));
153 return *iCacheStrings;
156 CLogServCacheTypes& CLogServDatabaseMarshall::DTICacheTypes() const
158 __ASSERT_ALWAYS(iCacheTypes, Panic(ELogCacheAccessDuringBackupTypes));
162 CLogServCacheConfig& CLogServDatabaseMarshall::DTICacheConfig() const
164 __ASSERT_ALWAYS(iCacheConfig, Panic(ELogCacheAccessDuringBackupConfig));
165 return *iCacheConfig;
168 RDbDatabase& CLogServDatabaseMarshall::DTIDatabase()
173 TBool CLogServDatabaseMarshall::DTIIsAllowed(TEventOp aEventOp, const RMessage2& aMessage, TUid aEventType, const char* aDiagnostic) const
175 return iSecurity->IsAllowed(aMessage, aEventType, aEventOp, aDiagnostic);
178 const RArray<TUid>& CLogServDatabaseMarshall::DTIUidsOfStandardTypes()
180 return iStandardTypeUids;
183 /////////////////////////////////////////////////////////////////////////////////////////
184 /////////////////////////////////////////////////////////////////////////////////////////
185 /////////////////////////////////////////////////////////////////////////////////////////
187 void CLogServDatabaseMarshall::BOHandleEventL(TLogServBackupEvent aEvent)
191 case EBackupStarting:
193 //Destroy config, types and strings caches
196 delete iCacheStrings;
197 iCacheStrings = NULL;
207 // Re-open the database and create config, types and strings caches
209 // reset views as a different database is being restored
210 DTIChangeInterface().DCISubmitGlobalChangeContextL(KLogClientChangeEventRefreshView);
218 /////////////////////////////////////////////////////////////////////////////////////////
219 /////////////////////////////////////////////////////////////////////////////////////////
220 /////////////////////////////////////////////////////////////////////////////////////////
222 void CLogServDatabaseMarshall::DatabaseLocateL()
224 // Get drive for database
225 TDriveUnit driveUnit(static_cast<TInt>(RFs::GetSystemDrive()));
226 TDriveName name(driveUnit.Name());
229 iFsSession.PrivatePath(path);
231 // Ensure database path exists
233 User::LeaveIfError(parse.Set(path, &name, NULL));
234 path = parse.FullName();
236 TInt error = iFsSession.MkDirAll(path);
237 if (error != KErrAlreadyExists)
238 User::LeaveIfError(error);
240 path += KLogDatabaseName;
241 iDatabaseName = path.AllocL();
245 Opens the LogEng database.
246 @return KErrNone, If the "database open" operation completes successfully.
247 If the "database open" operation fails the function returns the repported error code.
248 KErrCorrupt, If the database is opened successfully but is damaged, then the function returns KErrCorrupt.
250 TInt CLogServDatabaseMarshall::DoDbOpen()
252 LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - attempting to open db: %S", iDatabaseName);
253 #ifdef LOGGING_ENABLED
255 if (iFsSession.Entry(*iDatabaseName, entry) == KErrNone)
257 LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - Database file: %S DOES exist", iDatabaseName);
261 LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - Database file: %S NOT FOUND", iDatabaseName);
265 TInt err = iDatabase.Open(iFsSession, DatabaseName());
266 LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - attempting to open DMBS database resulted in error: %d", error);
267 // Check if the database is damaged. If it is set the error to KErrCorrupt so that it
269 if ((err == KErrNone) && iDatabase.IsDamaged())
277 Check if the database table count is the expected one - KExpectedNumberOfTables.
278 @return True, The database tables count is KExpectedNumberOfTables,
279 False, The database tables count is not KExpectedNumberOfTables;
280 @leave KErrNoMemory, an out of memory condition has occurred;
281 Note that the function may leave with database specific errors or
282 other system-wide error codes.
284 TBool CLogServDatabaseMarshall::DbTableCntCheckL()
286 CDbTableNames* tables = iDatabase.TableNamesL();
287 TInt numberOfTables = tables->Count();
289 LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - Number of tables: %d", numberOfTables);
290 return numberOfTables == KExpectedNumberOfTables;
294 Alters the "Event" table if the number column length is not KLogMaxNumberLength.
295 @return KErrNone, The "alter" operation has completed successfully, system wide or database specific error code otherwise.
297 TInt CLogServDatabaseMarshall::AlterEventTblIfOldFmt(CDbColSet& aEventTblColSet)
299 const TDbCol* numberCol = aEventTblColSet.Col(KLogFieldEventNumberString);
300 __ASSERT_DEBUG(numberCol != NULL, User::Invariant());
302 // check the column width is correct
303 if(numberCol->iMaxLength != KLogMaxNumberLength)
305 //The column width is not correct, so this is an old format database.
306 //Modify the database so the number length is KLogMaxNumberLength.
307 (const_cast <TDbCol*> (numberCol))->iMaxLength = KLogMaxNumberLength;
308 err = iDatabase.AlterTable(KLogNameEventString, aEventTblColSet);
313 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM
316 Alters the "Event" table if the the table does not have "SimId" column.
317 @return KErrNone, The "alter" operation has completed successfully, system wide or database specific error code otherwise.
318 @leave KErrNoMemory, an out of memory condition has occurred;
319 Some other failure codes, not related to the "alter" opertaion.
321 TInt CLogServDatabaseMarshall::AlterEventTblIfNoSimIdL(CDbColSet& aEventTblColSet)
322 {//Compiled only when SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM macro is defined
323 const TDbCol* simIdCol = aEventTblColSet.Col(KLogFieldEventSimId);
327 TDbCol col(KLogFieldEventSimId, EDbColUint32);
328 aEventTblColSet.AddL(col);
329 err = iDatabase.AlterTable(KLogNameEventString, aEventTblColSet);
337 Checks the database structure and alters the tables if that's an old format database.
338 @return KErrNone, The "alter" operation has completed successfully, system wide or database specific error code otherwise.
339 @leave KErrNoMemory, an out of memory condition has occurred;
340 Some other failure codes, not related to the "alter" opertaion.
342 TInt CLogServDatabaseMarshall::AlterDbIfOldFmtL()
344 CDbColSet* tableEventCol = iDatabase.ColSetL(KLogNameEventString);
345 CleanupStack::PushL(tableEventCol);
346 //Check for old format database which had MaxNumberLength =32
347 TInt err = AlterEventTblIfOldFmt(*tableEventCol);
348 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM
349 //Check if the "SimId" column is present
352 err = AlterEventTblIfNoSimIdL(*tableEventCol);
355 CleanupStack::PopAndDestroy(tableEventCol);
360 Closes and deletes the LogEng database. In _DEBUG builds the "delete file" error will be printed out.
362 void CLogServDatabaseMarshall::DbDelete()
366 //Do not remove the statement bellow. In _DEBUG builds it forms a single "TInt err2 = iFsSession.Delete(DatabaseName());" statement.
369 iFsSession.Delete(DatabaseName());
371 if((err2 != KErrNone) && (err2 != KErrNotFound))
373 RDebug::Print(_L("CLogServDatabaseMarshall::DatabaseOpenL() - Failed to delete file. Error = %d"), err2);
379 Attempts to create the LogEng database and tables.
380 @return KErrNoNone, The database was created successfully, system wide or database specific error otherwise.
382 TInt CLogServDatabaseMarshall::DbCreate()
384 // Try and create the database
385 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - trying to create database");
386 TRAPD(err, DatabaseCreateL(DatabaseName()));
387 LOGTEXT2("CLogServDatabaseMarshall::DatabaseOpenL() - creation error was: %d", error);
392 Creates config and string LogEng caches. Finishes the initialization of the event types cache.
393 @leave KErrNoMemory, an out of memory condition has occurred;
394 Note that the function may leave with database specific errors or
395 other system-wide error codes.
397 void CLogServDatabaseMarshall::CreateCachesL()
399 // Create other cache objects (these require the database to be already opened)
400 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - creating config cache");
401 iCacheConfig = CLogServCacheConfig::NewL(*this);
402 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - creating string cache");
403 iCacheStrings = CLogServCacheStrings::NewL(*this);
404 // Finish the type cache initialization
405 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - initializing type cache");
406 iCacheTypes->InitializeL();
409 void CLogServDatabaseMarshall::DatabaseOpenL()
411 // Create the cache objects - objects need to be put into the cache as
412 // soon as the database is open.
413 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - creating type cache");
414 iCacheTypes = CLogServCacheTypes::NewL(*this);
415 TInt err = DoDbOpen();
416 // Check we have the expected number of tables
417 if(err == KErrNone && !DbTableCntCheckL())
421 // Check a compaction can be performed. If it can't it indicates a serious problem?
422 if(err == KErrNone && (err = iDatabase.Compact()) != KErrNone)
428 err = CLogServDatabaseMarshall::AlterDbIfOldFmtL();
430 // If the database failed to open, delete and recreate.
431 if(err == KErrNotFound || err == KErrCorrupt || err == KErrArgument || err == KErrEof)
434 // Try and create the database
441 User::LeaveIfError(err);
443 // At this point, its safe to tell the backup interface what file it has to watch
444 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - registering database filename with backup interface");
445 iBackupInterface.BISetDatabaseNameL(DatabaseName());
446 LOGTEXT("CLogServDatabaseMarshall::DatabaseOpenL() - end");
449 void CLogServDatabaseMarshall::DatabaseCreateL(const TDesC& aName)
451 User::LeaveIfError(iDatabase.Replace(iFsSession, aName));
455 // Note: Number of tables HAS to match KExpectedNumberOfTables
456 void CLogServDatabaseMarshall::CreateTablesL()
458 DTIBeginWithRollBackProtectionLC();
460 // Create event table
461 TheSql.Format(KLogTableEventString, KLogMaxRemotePartyLength, KLogMaxSubjectLength, KLogMaxNumberLength);
462 User::LeaveIfError(iDatabase.Execute(TheSql));
463 MakeColumnAutoIncremetingL(KLogNameEventString, KLogFieldIdString);
465 // Create event type table
466 TheSql.Format(KLogTableTypeString, KLogMaxDescriptionLength);
467 User::LeaveIfError(iDatabase.Execute(TheSql));
468 MakeColumnAutoIncremetingL(KLogNameTypeString, KLogFieldIdString);
470 // Create string list table
471 TheSql.Format(KLogTableStringString, KLogMaxSharedStringLength);
472 User::LeaveIfError(iDatabase.Execute(TheSql));
473 MakeColumnAutoIncremetingL(KLogNameStringString, KLogFieldIdString);
475 // Create configuration table
476 TheSql.Copy(KLogTableConfigString);
477 User::LeaveIfError(iDatabase.Execute(TheSql));
482 // Set the initial configuration
483 CreateConfigurationL();
485 // Load standard event types
488 DTICommitAndCancelRollbackProtectionL();
491 void CLogServDatabaseMarshall::CreateTypesL(TBool aReadOnly)
493 // Get the array size
494 TResourceReader reader;
495 iResourceInterface.CreateResourceReaderLC(reader, R_LOG_INITIAL_EVENTS);
498 DTICacheTypes().CreateStandardTypesL(reader, aReadOnly);
500 CleanupStack::PopAndDestroy(); // reader
503 void CLogServDatabaseMarshall::CreateIndiciesL()
505 // Get the array size
506 TResourceReader reader;
507 iResourceInterface.CreateResourceReaderLC(reader, R_LOG_INDEXES);
509 const TInt indexes = reader.ReadInt16();
512 for(TInt c1 = 0; c1 < indexes; c1++)
514 const TPtrC name(reader.ReadTPtrC());
515 const TPtrC table(reader.ReadTPtrC());
517 // Get the number of keys
518 const TInt keys = reader.ReadInt16();
520 CDbKey* key = CDbKey::NewLC();
522 for(TInt c2 = 0; c2 < keys; c2++)
524 TPtrC col = reader.ReadTPtrC();
525 TUint order = reader.ReadUint16();
526 TInt len = reader.ReadInt16();
529 key->AddL(TDbKeyCol(col, len, (TDbKeyCol::TOrder)order));
532 // Make key unique if required
533 if (reader.ReadInt8())
537 const TDbTextComparison comparison = static_cast<TDbTextComparison>(reader.ReadInt8());
538 key->SetComparison(comparison);
541 User::LeaveIfError(iDatabase.CreateIndex(name, table, *key));
543 CleanupStack::PopAndDestroy(key);
546 CleanupStack::PopAndDestroy(); // reader
549 void CLogServDatabaseMarshall::CreateConfigurationL()
551 // Load the resource/repository file default configuration
552 // The precedence is given to the reading from the repository file.
555 CRepository* repository = NULL;
556 TRAPD(res, repository = CRepository::NewL(KUidLogengRepository));
559 CleanupStack::PushL(repository);
560 ReadRepositoryFileConfigurationL(config, *repository);
561 CleanupStack::PopAndDestroy(repository);
563 else if (res == KErrCorrupt)
569 ReadResourceFileConfigurationL(config);
572 TheSql.Format(KLogSqlInsertConfigString, config.iMaxLogSize, config.iMaxRecentLogSize, config.iMaxEventAge);
573 User::LeaveIfError(iDatabase.Execute(TheSql));
576 void CLogServDatabaseMarshall::ReadRepositoryFileConfigurationL(TLogConfig& aConfig, CRepository& repository) const
579 TInt maxRecentLogSize;
582 User::LeaveIfError(repository.Get(KMaxLogSizeRepKey, maxLogSize));
583 aConfig.iMaxLogSize = static_cast<TLogSize> (maxLogSize);
584 User::LeaveIfError(repository.Get(KMaxRecentLogSizeRepKey, maxRecentLogSize));
585 aConfig.iMaxRecentLogSize = static_cast<TLogRecentSize> (maxRecentLogSize);
586 User::LeaveIfError(repository.Get(KMaxEventAgeRepKey, maxEventAge));
587 aConfig.iMaxEventAge = static_cast<TLogAge> (maxEventAge);
590 void CLogServDatabaseMarshall::ReadResourceFileConfigurationL(TLogConfig& aConfig) const
592 TResourceReader reader;
593 iResourceInterface.CreateResourceReaderLC(reader, R_LOG_INITIAL_CONFIG);
595 aConfig.iMaxLogSize = static_cast<TLogSize>(reader.ReadUint16());
596 aConfig.iMaxRecentLogSize = static_cast<TLogRecentSize>(reader.ReadUint8());
597 aConfig.iMaxEventAge = static_cast<TLogAge>(reader.ReadUint32());
599 CleanupStack::PopAndDestroy(); // reader
602 void CLogServDatabaseMarshall::MakeColumnAutoIncremetingL(const TDesC& aTable, const TDesC& aColumn)
604 CDbColSet* newTable = iDatabase.ColSetL(aTable);
605 CleanupStack::PushL(newTable);
607 const TDbCol* oldCol = newTable->Col(aColumn);
608 __ASSERT_DEBUG(oldCol != NULL, Panic(ELogNoSuchColumn));
610 TDbCol newCol = *oldCol;
611 newCol.iAttributes |= TDbCol::EAutoIncrement;
613 newTable->Remove(aColumn);
614 newTable->AddL(newCol);
616 User::LeaveIfError(iDatabase.DropTable(aTable));
617 User::LeaveIfError(iDatabase.CreateTable(aTable, *newTable));
619 CleanupStack::PopAndDestroy(newTable);