os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServCacheStrings.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServCacheStrings.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,256 @@
     1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "LogServCacheStrings.h"
    1.20 +#include "LogServDatabaseTransactionInterface.h"
    1.21 +#include "logservpanic.h"
    1.22 +#include "LogServSqlStrings.h"
    1.23 +
    1.24 +/**
    1.25 +Strings array granularity.
    1.26 +@internalComponent
    1.27 +*/
    1.28 +const TInt KLogNumberOfInitialStrings = 16;
    1.29 +
    1.30 +/////////////////////////////////////////////////////////////////////////////////////////
    1.31 +// -----> CLogServCacheStrings (source)
    1.32 +/////////////////////////////////////////////////////////////////////////////////////////
    1.33 +
    1.34 +CLogServCacheStrings::CLogServCacheStrings(MLogServDatabaseTransactionInterface& aDatabase) :
    1.35 +	iDatabase(aDatabase), 
    1.36 +	iStrings(KLogNumberOfInitialStrings)
    1.37 +	{
    1.38 +	}
    1.39 +
    1.40 +CLogServCacheStrings::~CLogServCacheStrings()
    1.41 +	{
    1.42 +	DestroyCache();
    1.43 +	}
    1.44 +
    1.45 +void CLogServCacheStrings::DestroyCache()
    1.46 +	{
    1.47 +	for(TInt i=iStrings.Count()-1;i>=0;--i)
    1.48 +		{
    1.49 +		TLogServCacheStringEntry::DeleteEntry(iStrings[i]);
    1.50 +		}
    1.51 +	iStrings.Close();
    1.52 +	}
    1.53 +
    1.54 +void CLogServCacheStrings::ConstructL()
    1.55 +	{
    1.56 +	ReadStringsFromDatabaseL();
    1.57 +	}
    1.58 +
    1.59 +CLogServCacheStrings* CLogServCacheStrings::NewL(MLogServDatabaseTransactionInterface& aDatabase)
    1.60 +	{
    1.61 +	CLogServCacheStrings* self = new(ELeave) CLogServCacheStrings(aDatabase);
    1.62 +	CleanupStack::PushL(self);
    1.63 +	self->ConstructL();
    1.64 +	CleanupStack::Pop(self);
    1.65 +	return self;
    1.66 +	}
    1.67 +
    1.68 +/////////////////////////////////////////////////////////////////////////////////////////
    1.69 +/////////////////////////////////////////////////////////////////////////////////////////
    1.70 +/////////////////////////////////////////////////////////////////////////////////////////
    1.71 +
    1.72 +/**
    1.73 +Find the descriptor corresponding to a given string id. KNullDesC if the id is not found.
    1.74 +*/
    1.75 +const TPtrC CLogServCacheStrings::FindString(TLogStringId aId) const
    1.76 +	{
    1.77 +	if(aId != KLogNullStringId)
    1.78 +		{
    1.79 +		for(TInt i=iStrings.Count()-1;i>=0;--i)
    1.80 +			{
    1.81 +			if(iStrings[i]->iId == aId)
    1.82 +				{
    1.83 +				return iStrings[i]->String();	
    1.84 +				}
    1.85 +			}
    1.86 +		}
    1.87 +	return KNullDesC();
    1.88 +	}
    1.89 +
    1.90 +
    1.91 +/**
    1.92 +Find the id of a given string. KLogNullStringId if no string is found.
    1.93 +*/
    1.94 +TLogStringId CLogServCacheStrings::FindId(const TDesC& aString)
    1.95 +	{
    1.96 +	if(aString.Length() == 0)
    1.97 +		{
    1.98 +		return KLogNullStringId;	
    1.99 +		}
   1.100 +	TInt position = iStrings.FindInOrder(aString, &CLogServCacheStrings::Compare1);
   1.101 +	return position >= 0 ? iStrings[position]->iId : KLogNullStringId;
   1.102 +	}
   1.103 +
   1.104 +/**
   1.105 +Find the id of a given string. Add the string to the cache if the string is not there.
   1.106 +If the aString length is 0, then do not search the cache, do not add the string, just return KLogNullStringId.
   1.107 +If the string has to be added - the string will be added to the cache and
   1.108 +a new record will be inserted into the database.
   1.109 +If the database is in transaction, the string in the cache will have its "dirty" flag set. During the rollback
   1.110 +(if a rollback occurs) all strings with "dirty" flag set will be removed from the cache.
   1.111 +The idea is to keep the cache content consistent with the database content.
   1.112 +*/
   1.113 +TLogStringId CLogServCacheStrings::GetIdL(const TDesC& aString)
   1.114 +	{
   1.115 +	if(aString.Length() == 0)
   1.116 +		{
   1.117 +		return KLogNullStringId;	
   1.118 +		}
   1.119 +	TLogStringId id = FindId(aString);
   1.120 +	if(id == KLogNullStringId)
   1.121 +		{
   1.122 +		id = DoAddStringL(aString);	
   1.123 +		}
   1.124 +	return id;
   1.125 +	}
   1.126 +
   1.127 +/**
   1.128 +Clears the dirty flag of the cache entries that have been added during the last transaction.
   1.129 +*/
   1.130 +void CLogServCacheStrings::Commit()
   1.131 +	{
   1.132 +	if(iDirty)
   1.133 +		{
   1.134 +		for(TInt i=iStrings.Count()-1;i>=0;--i)
   1.135 +			{
   1.136 +			iStrings[i]->iDirty = EFalse;
   1.137 +			}
   1.138 +		iDirty = EFalse;	
   1.139 +		}
   1.140 +	}
   1.141 +
   1.142 +
   1.143 +/**
   1.144 +Removes any strings added to the cache of strings since the beginning of last transaction (with iDirty flag set).
   1.145 +*/
   1.146 +void CLogServCacheStrings::Rollback()
   1.147 +	{
   1.148 +	if(iDirty)
   1.149 +		{
   1.150 +		for(TInt i=iStrings.Count()-1;i>=0;--i)
   1.151 +			{
   1.152 +			if(iStrings[i]->iDirty)
   1.153 +				{
   1.154 +				TLogServCacheStringEntry::DeleteEntry(iStrings[i]);
   1.155 +				iStrings.Remove(i);
   1.156 +				}
   1.157 +			}
   1.158 +		iDirty = EFalse;	
   1.159 +		}
   1.160 +	}
   1.161 +
   1.162 +/////////////////////////////////////////////////////////////////////////////////////////
   1.163 +/////////////////////////////////////////////////////////////////////////////////////////
   1.164 +/////////////////////////////////////////////////////////////////////////////////////////
   1.165 +
   1.166 +void CLogServCacheStrings::ReadStringsFromDatabaseL()
   1.167 +	{
   1.168 +	DestroyCache();
   1.169 +	RDbTable tbl;
   1.170 +	CleanupClosePushL(tbl);
   1.171 +	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameStringString, RDbRowSet::EReadOnly));
   1.172 +	if(tbl.FirstL())
   1.173 +		{
   1.174 +		InitializeColNumsL(tbl);
   1.175 +		iStrings.ReserveL(tbl.CountL());
   1.176 +		do
   1.177 +			{
   1.178 +			tbl.GetL();			
   1.179 +			const TLogStringId id = tbl.ColInt16(iIdColNo);
   1.180 +			const TPtrC pString(tbl.ColDes(iStringColNo));
   1.181 +			TLinearOrder<TLogServCacheStringEntry*> orderer(&CLogServCacheStrings::Compare2);
   1.182 +			TLogServCacheStringEntry* entry = TLogServCacheStringEntry::NewEntryL(id, pString);
   1.183 +			TInt err = iStrings.InsertInOrder(entry, orderer);
   1.184 +			__ASSERT_ALWAYS(err == KErrNone, Panic(ELogStringsCacheReserved));
   1.185 +			}
   1.186 +		while(tbl.NextL());		
   1.187 +		}
   1.188 +	CleanupStack::PopAndDestroy(&tbl);
   1.189 +	}
   1.190 +
   1.191 +//Atomic "add string to cache" operation.
   1.192 +TLogStringId CLogServCacheStrings::DoAddStringL(const TDesC& aString)
   1.193 +	{
   1.194 +	//Reserve space for the new string in the cache
   1.195 +	iStrings.ReserveL(iStrings.Count() + 1);
   1.196 +	//Open the database table and push it on the cleanup stack.
   1.197 +	//If the InitializeColNumsL() operation leaves then the table will be closed automatically.
   1.198 +	RDbTable tbl;
   1.199 +	CleanupClosePushL(tbl);
   1.200 +	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameStringString));
   1.201 +	InitializeColNumsL(tbl);
   1.202 +	//Allocate space for the new record in the table. Push the Cancel() function on the cleanup stack.
   1.203 +	//If some of the next calls leaves, the insert operation will be automatically cancelled.
   1.204 +	tbl.InsertL();
   1.205 +	const TLogStringId id = tbl.ColInt16(iIdColNo);
   1.206 +	tbl.SetColL(iStringColNo, aString);
   1.207 +	//Create new cache entry and push it on the cleanup stack.
   1.208 +	TLogServCacheStringEntry* entry = TLogServCacheStringEntry::NewEntryLC(id, aString, iDatabase.DTIInTransaction());
   1.209 +	//Finish the "insert record" operation. If PutL() leaves, then:
   1.210 +	//  - the new cache entry is deleted
   1.211 +	//  - the insert operation is cancelled
   1.212 +	//  - the table is closed
   1.213 +	tbl.PutL();
   1.214 +	//Pop the entry and the Cancel() from the cleanup stack. Close the table.
   1.215 +	CleanupStack::Pop();//TLogServCacheStringEntry
   1.216 +	CleanupStack::PopAndDestroy(&tbl);
   1.217 +	//The next operation is guaranteed to be a non-failing "add entry" operation.
   1.218 +	TLinearOrder<TLogServCacheStringEntry*> orderer(&CLogServCacheStrings::Compare2);
   1.219 +	TInt err = iStrings.InsertInOrder(entry, orderer);
   1.220 +	__ASSERT_ALWAYS(err == KErrNone, Panic(ELogStringsCacheReserved));
   1.221 +	//Mark the cache as dirty. Later if there was an outstanding transaction and that transaction failed, 
   1.222 +	//The database rollback operation will restore the original state of the table. 
   1.223 +	//The CLogServCacheStrings::RollbackAddStringsL() will remove from the cache all "dirty" strings.
   1.224 +	iDirty = ETrue;
   1.225 +	return id;
   1.226 +	}
   1.227 +
   1.228 +TInt CLogServCacheStrings::Compare1(const TDesC* aString, TLogServCacheStringEntry* const& aRight)
   1.229 +	{
   1.230 +	__ASSERT_DEBUG(aString != NULL, Panic(ELogStringsCacheNullArg1));
   1.231 +	__ASSERT_DEBUG(aRight != NULL, Panic(ELogStringsCacheNullArg1));
   1.232 +	return aString->Compare(aRight->String());
   1.233 +	}
   1.234 +
   1.235 +TInt CLogServCacheStrings::Compare2(TLogServCacheStringEntry* const& aLeft, TLogServCacheStringEntry* const& aRight)
   1.236 +	{
   1.237 +	__ASSERT_DEBUG(aLeft != NULL, Panic(ELogStringsCacheNullArg2));
   1.238 +	__ASSERT_DEBUG(aRight != NULL, Panic(ELogStringsCacheNullArg2));
   1.239 +	return aLeft->String().Compare(aRight->String());
   1.240 +	}
   1.241 +
   1.242 +void CLogServCacheStrings::InitializeColNumsL(RDbRowSet& aRowSet)
   1.243 +	{
   1.244 +	if(iIdColNo == 0)
   1.245 +		{
   1.246 +		CDbColSet* colset = aRowSet.ColSetL();
   1.247 +		iIdColNo = colset->ColNo(KLogFieldStringIdString);
   1.248 +		iStringColNo = colset->ColNo(KLogFieldStringTextString);
   1.249 +		delete colset;
   1.250 +		}
   1.251 +	__ASSERT_DEBUG(iIdColNo > 0, Panic(ELogInvalidStringColNo));
   1.252 +	__ASSERT_DEBUG(iStringColNo > 0, Panic(ELogInvalidStringColNo));
   1.253 +	}
   1.254 +
   1.255 +void CLogServCacheStrings::TLogServCacheStringEntry::CleanupEntry(TAny* aEntry)
   1.256 +	{
   1.257 +	TLogServCacheStringEntry* entry = reinterpret_cast <TLogServCacheStringEntry*> (aEntry);
   1.258 +	CLogServCacheStrings::TLogServCacheStringEntry::DeleteEntry(entry);
   1.259 +	}