loggingservices/eventlogger/LogServ/src/LogServCacheTypes.cpp
changeset 0 08ec8eefde2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loggingservices/eventlogger/LogServ/src/LogServCacheTypes.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,362 @@
+// 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 "logservpanic.h"
+#include "LogServCacheTypes.h"
+#include "LogServDatabaseTransactionInterface.h"
+#include "LogServResourceInterpreter.h"
+#include "LogServSqlStrings.h"
+
+// Constants
+const TInt KLogNumberOfInitialTypes = 8;
+const TBool KDefaultLoggingSetting = EFalse;
+
+CLogServCacheTypes::CLogServCacheTypes(MLogServDatabaseTransactionInterface& aDatabase) :
+	iDatabase(aDatabase), 
+	iTypes(KLogNumberOfInitialTypes)
+	{
+	}
+
+CLogServCacheTypes::~CLogServCacheTypes()
+	{
+	delete iInvalidCacheEntry.iEventType;
+	DestroyCache();
+	iStandardTypeUids.Close();
+	}
+
+CLogServCacheTypes* CLogServCacheTypes::NewL(MLogServDatabaseTransactionInterface& aDatabase)
+	{
+	CLogServCacheTypes* self = new (ELeave) CLogServCacheTypes(aDatabase);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CLogServCacheTypes::ConstructL()
+	{
+	CLogEventType* invEventType = CLogEventType::NewL();
+	invEventType->SetDescription(KNullDesC);
+	invEventType->SetUid(KNullUid);
+	invEventType->SetLoggingEnabled(KDefaultLoggingSetting);
+	iInvalidCacheEntry.iEventTypeId = KLogNullTypeId;
+	iInvalidCacheEntry.iEventType = invEventType;
+	}
+
+/**
+*/
+const TLogServCacheTypeEntry& CLogServCacheTypes::FindById(TLogTypeId aId) const
+	{
+	__TEST_INVARIANT;
+	for(TInt i=iTypes.Count()-1;i>=0;--i)
+		{
+		if(iTypes[i].iEventTypeId == aId)
+			{
+			return iTypes[i];
+			}
+		}
+	return iInvalidCacheEntry;
+	}
+
+/**
+*/
+const TLogServCacheTypeEntry& CLogServCacheTypes::FindByUid(TUid aUid) const
+	{
+	__TEST_INVARIANT;
+	TInt position = iTypes.FindInOrder(aUid, &CLogServCacheTypes::Compare1);
+	return position >= 0 ? iTypes[position] : iInvalidCacheEntry;
+	}
+
+/**
+Add a new type to the database
+*/
+TLogTypeId CLogServCacheTypes::AddTypeL(const CLogEventType& aEventType)
+	{
+	__TEST_INVARIANT;
+	TInt position = iTypes.FindInOrder(aEventType.Uid(), &CLogServCacheTypes::Compare1);
+	if(position >= 0)
+		{
+		User::Leave(KErrAlreadyExists);
+		}
+	return DoAddTypeL(aEventType);
+	}
+
+/**
+Change an existing type
+*/
+TInt CLogServCacheTypes::ChangeType(const CLogEventType& aEventType)
+	{
+	__TEST_INVARIANT;
+	return DoChangeType(aEventType);
+	}
+
+/**
+Delete an existing type
+*/
+TInt CLogServCacheTypes::DeleteType(TUid aUid)
+	{
+	__TEST_INVARIANT;
+	if(iStandardTypeUids.Find(aUid) >= 0)
+		{
+		return KErrPermissionDenied;
+		}
+	TInt position = iTypes.FindInOrder(aUid, &CLogServCacheTypes::Compare1);	
+	TheSql.Format(KLogSqlDeleteTypeString, aUid);
+	TInt err = iDatabase.DTIExecuteSql(TheSql);
+	if(err >= 0 && position >= 0)
+		{
+		delete iTypes[position].iEventType;
+		iTypes.Remove(position);
+		}
+	return err;	
+	}
+
+/**
+Creates the standard (resource file-defined) log types. Should
+be called from within a transaction only when the database is
+created.
+This method is implicitly called within a transaction by the database marshall
+*/
+void CLogServCacheTypes::CreateStandardTypesL(TResourceReader& aResourceSpecifiedTypes, TBool aReadOnly /*=EFalse*/)
+	{
+	const TInt count = aResourceSpecifiedTypes.ReadInt16();
+	iStandardTypeUids.Reset();
+	iStandardTypeUids.ReserveL(count);
+
+	RDbTable tbl;
+	CleanupClosePushL(tbl);
+	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameTypeString));
+	InitializeColNumsL(tbl);
+	
+	TBool commit = EFalse;
+	if(!iDatabase.DTIInTransaction())
+		{
+		iDatabase.DTIBeginWithRollBackProtectionLC();
+		commit = ETrue;
+		}
+
+	for(TInt i=0;i<count;++i)
+		{
+		TUint uId = aResourceSpecifiedTypes.ReadUint32();
+		TPtrC des = aResourceSpecifiedTypes.ReadTPtrC();
+		TUint enabled = aResourceSpecifiedTypes.ReadUint8();
+		
+		if(!aReadOnly)
+			{
+			tbl.InsertL();
+			tbl.SetColL(iUidColNo, uId);
+			tbl.SetColL(iDescriptionColNo, des);
+			tbl.SetColL(iEnabledColNo, enabled);
+			tbl.PutL();
+			}
+
+		TInt err = iStandardTypeUids.Append(TUid::Uid(uId));
+		__ASSERT_ALWAYS(err == KErrNone, Panic(ELogTypesCacheReserved));
+		}
+		
+	if(commit)
+		{
+		iDatabase.DTICommitAndCancelRollbackProtectionL();
+		}
+	
+	CleanupStack::PopAndDestroy(&tbl);
+	}
+
+/**
+Initialize the cache based upon the database contents. Called whenever
+the database is opened.
+*/
+void CLogServCacheTypes::InitializeL()
+	{
+	__TEST_INVARIANT;
+
+	TLinearOrder<TLogServCacheTypeEntry> orderer(&CLogServCacheTypes::Compare2);
+	DestroyCache();
+	
+	RDbTable tbl;
+	CleanupClosePushL(tbl);
+	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameTypeString, RDbRowSet::EReadOnly));
+	
+	if(tbl.FirstL())
+		{
+		InitializeColNumsL(tbl);
+		const TInt count = tbl.CountL();
+		iTypes.ReserveL(count);
+		do
+			{
+			tbl.GetL();	
+			
+			CLogEventType* eventType = CLogEventType::NewL();
+			eventType->SetUid(TUid::Uid(tbl.ColUint32(iUidColNo)));
+			eventType->SetDescription(tbl.ColDes(iDescriptionColNo));
+			eventType->SetLoggingEnabled(tbl.IsColNull(iEnabledColNo) ? EFalse : tbl.ColUint8(iEnabledColNo));
+			TLogServCacheTypeEntry entry(tbl.ColInt16(iIdColNo), eventType);
+			
+			TInt err = iTypes.InsertInOrder(entry, orderer);
+			__ASSERT_ALWAYS(err == KErrNone, Panic(ELogTypesCacheReserved));
+			}
+		while(tbl.NextL());
+		}
+	
+	CleanupStack::PopAndDestroy(&tbl);
+	}
+
+void CLogServCacheTypes::CopyStandardTypeUidsL(RArray<TUid>& aUidsCopy)
+	{
+	__TEST_INVARIANT;
+	TInt count = iStandardTypeUids.Count();
+	aUidsCopy.ReserveL(aUidsCopy.Count() + count);
+	for(TInt i=0;i<count;++i)
+		{
+		TInt err = aUidsCopy.Append(iStandardTypeUids[i]);	
+		__ASSERT_ALWAYS(err == KErrNone, Panic(ELogTypesCacheReserved));
+		}
+	}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+TLogTypeId CLogServCacheTypes::DoAddTypeL(const CLogEventType& aEventType)
+	{
+	iTypes.ReserveL(iTypes.Count() + 1);
+	
+	CLogEventType* eventType = CLogEventType::NewL();
+	CleanupStack::PushL(eventType);
+	eventType->Copy(aEventType);
+	
+	RDbTable tbl;
+	CleanupClosePushL(tbl);
+	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameTypeString));
+	InitializeColNumsL(tbl);
+	
+	tbl.InsertL();
+	const TLogTypeId id = tbl.ColInt16(iIdColNo);
+	tbl.SetColL(iUidColNo, eventType->Uid().iUid);
+	tbl.SetColL(iDescriptionColNo, eventType->Description());
+	tbl.SetColL(iEnabledColNo, eventType->LoggingEnabled() ? 1 : 0);
+	tbl.PutL();
+
+	TLinearOrder<TLogServCacheTypeEntry> orderer(&CLogServCacheTypes::Compare2);
+	TLogServCacheTypeEntry entry(id, eventType);
+	TInt err = iTypes.InsertInOrder(entry, orderer);
+	__ASSERT_ALWAYS(err == KErrNone, Panic(ELogTypesCacheReserved));
+	
+	CleanupStack::PopAndDestroy(&tbl);
+	CleanupStack::Pop(eventType);
+	return id;
+	}
+
+/**
+If the EventType is standard - i.e. it was defined in LogWrap.rss, then no changes
+are allowed.  Otherwise we can only change the logging status or the description.
+*/
+TInt CLogServCacheTypes::DoChangeType(const CLogEventType& aEventType)
+	{
+	TInt position = iTypes.FindInOrder(aEventType.Uid(), &CLogServCacheTypes::Compare1);
+	if(position < 0)
+		{
+		return position;	
+		}
+
+	if(iStandardTypeUids.Find(aEventType.Uid()) >= 0)	
+		{
+		return KErrPermissionDenied;		// standard built-in type - no changes allowed !
+		}
+	
+	// First update the database (event type table)
+	TheSql.Format(KLogSqlUpdateTypeString, &aEventType.Description(), aEventType.LoggingEnabled(), aEventType.Uid());
+	TInt err = iDatabase.DTIExecuteSql(TheSql);
+	if(err < 0)
+		{
+		return err;	
+		}
+	// Then update the cached entry
+	iTypes[position].iEventType->Copy(aEventType);
+	return KErrNone;
+	}
+
+void CLogServCacheTypes::InitializeColNumsL(RDbRowSet& aRowSet)
+	{
+	if(iIdColNo == 0)
+		{
+		CDbColSet* colset = aRowSet.ColSetL();
+		iIdColNo = colset->ColNo(KLogFieldTypeIdString);
+		iUidColNo = colset->ColNo(KLogFieldTypeUidString);
+		iDescriptionColNo = colset->ColNo(KLogFieldTypeDescriptionString);
+		iEnabledColNo = colset->ColNo(KLogFieldTypeEnabledString);
+		delete colset;
+		}
+	__ASSERT_DEBUG(iIdColNo > 0, Panic(ELogInvalidTypeColNo));
+	__ASSERT_DEBUG(iUidColNo > 0, Panic(ELogInvalidTypeColNo));
+	__ASSERT_DEBUG(iDescriptionColNo > 0, Panic(ELogInvalidTypeColNo));
+	__ASSERT_DEBUG(iEnabledColNo > 0, Panic(ELogInvalidTypeColNo));
+	}
+
+void CLogServCacheTypes::DestroyCache()
+	{
+	for(TInt i=iTypes.Count()-1;i>=0;--i)
+		{
+		delete iTypes[i].iEventType;	
+		}
+	iTypes.Close();		
+	}
+
+TInt CLogServCacheTypes::Compare1(const TUid* aUid, const TLogServCacheTypeEntry& aRight)
+	{
+	__ASSERT_DEBUG(aUid != NULL, Panic(ELogTypeCacheNullArg));
+	if(*aUid == aRight.iEventType->Uid())
+		{
+		return 0;
+		}
+	else if(aUid->iUid < aRight.iEventType->Uid().iUid)
+		{
+		return -1;
+		}
+	return 1;
+	}
+
+TBool CLogServCacheTypes::Compare2(const TLogServCacheTypeEntry& aLeft, const TLogServCacheTypeEntry& aRight)
+	{
+	TUid typeUid = aLeft.iEventType->Uid();
+	return CLogServCacheTypes::Compare1(&typeUid, aRight);
+	}
+
+void CLogServCacheTypes::__DbgTestInvariant() const
+	{
+#ifdef _DEBUG
+	const TInt count = iTypes.Count();
+	for(TInt i=0; i<count;  ++i)
+		{
+		const TLogServCacheTypeEntry& event1 = iTypes[i];
+		__ASSERT_DEBUG(event1.iEventTypeId != KLogNullTypeId, User::Invariant());
+		__ASSERT_DEBUG(event1.iEventType != NULL, User::Invariant());
+		for(TInt j=0; j<count; ++j)
+			{
+			if(j==i)
+				{
+				continue;
+				}
+			const TLogServCacheTypeEntry& event2 = iTypes[j];
+			__ASSERT_DEBUG(event2.iEventTypeId != KLogNullTypeId, User::Invariant());
+			__ASSERT_DEBUG(event2.iEventType != NULL, User::Invariant());
+			
+			__ASSERT_DEBUG(event2.iEventTypeId != event1.iEventTypeId, User::Invariant());
+			__ASSERT_DEBUG(event2.iEventType->Uid() != event1.iEventType->Uid(), User::Invariant());
+			}
+		}
+#endif
+	}