loggingservices/eventlogger/LogServ/src/LogServCacheStrings.cpp
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2002-2009 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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "LogServCacheStrings.h"
       
    17 #include "LogServDatabaseTransactionInterface.h"
       
    18 #include "logservpanic.h"
       
    19 #include "LogServSqlStrings.h"
       
    20 
       
    21 /**
       
    22 Strings array granularity.
       
    23 @internalComponent
       
    24 */
       
    25 const TInt KLogNumberOfInitialStrings = 16;
       
    26 
       
    27 /////////////////////////////////////////////////////////////////////////////////////////
       
    28 // -----> CLogServCacheStrings (source)
       
    29 /////////////////////////////////////////////////////////////////////////////////////////
       
    30 
       
    31 CLogServCacheStrings::CLogServCacheStrings(MLogServDatabaseTransactionInterface& aDatabase) :
       
    32 	iDatabase(aDatabase), 
       
    33 	iStrings(KLogNumberOfInitialStrings)
       
    34 	{
       
    35 	}
       
    36 
       
    37 CLogServCacheStrings::~CLogServCacheStrings()
       
    38 	{
       
    39 	DestroyCache();
       
    40 	}
       
    41 
       
    42 void CLogServCacheStrings::DestroyCache()
       
    43 	{
       
    44 	for(TInt i=iStrings.Count()-1;i>=0;--i)
       
    45 		{
       
    46 		TLogServCacheStringEntry::DeleteEntry(iStrings[i]);
       
    47 		}
       
    48 	iStrings.Close();
       
    49 	}
       
    50 
       
    51 void CLogServCacheStrings::ConstructL()
       
    52 	{
       
    53 	ReadStringsFromDatabaseL();
       
    54 	}
       
    55 
       
    56 CLogServCacheStrings* CLogServCacheStrings::NewL(MLogServDatabaseTransactionInterface& aDatabase)
       
    57 	{
       
    58 	CLogServCacheStrings* self = new(ELeave) CLogServCacheStrings(aDatabase);
       
    59 	CleanupStack::PushL(self);
       
    60 	self->ConstructL();
       
    61 	CleanupStack::Pop(self);
       
    62 	return self;
       
    63 	}
       
    64 
       
    65 /////////////////////////////////////////////////////////////////////////////////////////
       
    66 /////////////////////////////////////////////////////////////////////////////////////////
       
    67 /////////////////////////////////////////////////////////////////////////////////////////
       
    68 
       
    69 /**
       
    70 Find the descriptor corresponding to a given string id. KNullDesC if the id is not found.
       
    71 */
       
    72 const TPtrC CLogServCacheStrings::FindString(TLogStringId aId) const
       
    73 	{
       
    74 	if(aId != KLogNullStringId)
       
    75 		{
       
    76 		for(TInt i=iStrings.Count()-1;i>=0;--i)
       
    77 			{
       
    78 			if(iStrings[i]->iId == aId)
       
    79 				{
       
    80 				return iStrings[i]->String();	
       
    81 				}
       
    82 			}
       
    83 		}
       
    84 	return KNullDesC();
       
    85 	}
       
    86 
       
    87 
       
    88 /**
       
    89 Find the id of a given string. KLogNullStringId if no string is found.
       
    90 */
       
    91 TLogStringId CLogServCacheStrings::FindId(const TDesC& aString)
       
    92 	{
       
    93 	if(aString.Length() == 0)
       
    94 		{
       
    95 		return KLogNullStringId;	
       
    96 		}
       
    97 	TInt position = iStrings.FindInOrder(aString, &CLogServCacheStrings::Compare1);
       
    98 	return position >= 0 ? iStrings[position]->iId : KLogNullStringId;
       
    99 	}
       
   100 
       
   101 /**
       
   102 Find the id of a given string. Add the string to the cache if the string is not there.
       
   103 If the aString length is 0, then do not search the cache, do not add the string, just return KLogNullStringId.
       
   104 If the string has to be added - the string will be added to the cache and
       
   105 a new record will be inserted into the database.
       
   106 If the database is in transaction, the string in the cache will have its "dirty" flag set. During the rollback
       
   107 (if a rollback occurs) all strings with "dirty" flag set will be removed from the cache.
       
   108 The idea is to keep the cache content consistent with the database content.
       
   109 */
       
   110 TLogStringId CLogServCacheStrings::GetIdL(const TDesC& aString)
       
   111 	{
       
   112 	if(aString.Length() == 0)
       
   113 		{
       
   114 		return KLogNullStringId;	
       
   115 		}
       
   116 	TLogStringId id = FindId(aString);
       
   117 	if(id == KLogNullStringId)
       
   118 		{
       
   119 		id = DoAddStringL(aString);	
       
   120 		}
       
   121 	return id;
       
   122 	}
       
   123 
       
   124 /**
       
   125 Clears the dirty flag of the cache entries that have been added during the last transaction.
       
   126 */
       
   127 void CLogServCacheStrings::Commit()
       
   128 	{
       
   129 	if(iDirty)
       
   130 		{
       
   131 		for(TInt i=iStrings.Count()-1;i>=0;--i)
       
   132 			{
       
   133 			iStrings[i]->iDirty = EFalse;
       
   134 			}
       
   135 		iDirty = EFalse;	
       
   136 		}
       
   137 	}
       
   138 
       
   139 
       
   140 /**
       
   141 Removes any strings added to the cache of strings since the beginning of last transaction (with iDirty flag set).
       
   142 */
       
   143 void CLogServCacheStrings::Rollback()
       
   144 	{
       
   145 	if(iDirty)
       
   146 		{
       
   147 		for(TInt i=iStrings.Count()-1;i>=0;--i)
       
   148 			{
       
   149 			if(iStrings[i]->iDirty)
       
   150 				{
       
   151 				TLogServCacheStringEntry::DeleteEntry(iStrings[i]);
       
   152 				iStrings.Remove(i);
       
   153 				}
       
   154 			}
       
   155 		iDirty = EFalse;	
       
   156 		}
       
   157 	}
       
   158 
       
   159 /////////////////////////////////////////////////////////////////////////////////////////
       
   160 /////////////////////////////////////////////////////////////////////////////////////////
       
   161 /////////////////////////////////////////////////////////////////////////////////////////
       
   162 
       
   163 void CLogServCacheStrings::ReadStringsFromDatabaseL()
       
   164 	{
       
   165 	DestroyCache();
       
   166 	RDbTable tbl;
       
   167 	CleanupClosePushL(tbl);
       
   168 	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameStringString, RDbRowSet::EReadOnly));
       
   169 	if(tbl.FirstL())
       
   170 		{
       
   171 		InitializeColNumsL(tbl);
       
   172 		iStrings.ReserveL(tbl.CountL());
       
   173 		do
       
   174 			{
       
   175 			tbl.GetL();			
       
   176 			const TLogStringId id = tbl.ColInt16(iIdColNo);
       
   177 			const TPtrC pString(tbl.ColDes(iStringColNo));
       
   178 			TLinearOrder<TLogServCacheStringEntry*> orderer(&CLogServCacheStrings::Compare2);
       
   179 			TLogServCacheStringEntry* entry = TLogServCacheStringEntry::NewEntryL(id, pString);
       
   180 			TInt err = iStrings.InsertInOrder(entry, orderer);
       
   181 			__ASSERT_ALWAYS(err == KErrNone, Panic(ELogStringsCacheReserved));
       
   182 			}
       
   183 		while(tbl.NextL());		
       
   184 		}
       
   185 	CleanupStack::PopAndDestroy(&tbl);
       
   186 	}
       
   187 
       
   188 //Atomic "add string to cache" operation.
       
   189 TLogStringId CLogServCacheStrings::DoAddStringL(const TDesC& aString)
       
   190 	{
       
   191 	//Reserve space for the new string in the cache
       
   192 	iStrings.ReserveL(iStrings.Count() + 1);
       
   193 	//Open the database table and push it on the cleanup stack.
       
   194 	//If the InitializeColNumsL() operation leaves then the table will be closed automatically.
       
   195 	RDbTable tbl;
       
   196 	CleanupClosePushL(tbl);
       
   197 	User::LeaveIfError(tbl.Open(iDatabase.DTIDatabase(), KLogNameStringString));
       
   198 	InitializeColNumsL(tbl);
       
   199 	//Allocate space for the new record in the table. Push the Cancel() function on the cleanup stack.
       
   200 	//If some of the next calls leaves, the insert operation will be automatically cancelled.
       
   201 	tbl.InsertL();
       
   202 	const TLogStringId id = tbl.ColInt16(iIdColNo);
       
   203 	tbl.SetColL(iStringColNo, aString);
       
   204 	//Create new cache entry and push it on the cleanup stack.
       
   205 	TLogServCacheStringEntry* entry = TLogServCacheStringEntry::NewEntryLC(id, aString, iDatabase.DTIInTransaction());
       
   206 	//Finish the "insert record" operation. If PutL() leaves, then:
       
   207 	//  - the new cache entry is deleted
       
   208 	//  - the insert operation is cancelled
       
   209 	//  - the table is closed
       
   210 	tbl.PutL();
       
   211 	//Pop the entry and the Cancel() from the cleanup stack. Close the table.
       
   212 	CleanupStack::Pop();//TLogServCacheStringEntry
       
   213 	CleanupStack::PopAndDestroy(&tbl);
       
   214 	//The next operation is guaranteed to be a non-failing "add entry" operation.
       
   215 	TLinearOrder<TLogServCacheStringEntry*> orderer(&CLogServCacheStrings::Compare2);
       
   216 	TInt err = iStrings.InsertInOrder(entry, orderer);
       
   217 	__ASSERT_ALWAYS(err == KErrNone, Panic(ELogStringsCacheReserved));
       
   218 	//Mark the cache as dirty. Later if there was an outstanding transaction and that transaction failed, 
       
   219 	//The database rollback operation will restore the original state of the table. 
       
   220 	//The CLogServCacheStrings::RollbackAddStringsL() will remove from the cache all "dirty" strings.
       
   221 	iDirty = ETrue;
       
   222 	return id;
       
   223 	}
       
   224 
       
   225 TInt CLogServCacheStrings::Compare1(const TDesC* aString, TLogServCacheStringEntry* const& aRight)
       
   226 	{
       
   227 	__ASSERT_DEBUG(aString != NULL, Panic(ELogStringsCacheNullArg1));
       
   228 	__ASSERT_DEBUG(aRight != NULL, Panic(ELogStringsCacheNullArg1));
       
   229 	return aString->Compare(aRight->String());
       
   230 	}
       
   231 
       
   232 TInt CLogServCacheStrings::Compare2(TLogServCacheStringEntry* const& aLeft, TLogServCacheStringEntry* const& aRight)
       
   233 	{
       
   234 	__ASSERT_DEBUG(aLeft != NULL, Panic(ELogStringsCacheNullArg2));
       
   235 	__ASSERT_DEBUG(aRight != NULL, Panic(ELogStringsCacheNullArg2));
       
   236 	return aLeft->String().Compare(aRight->String());
       
   237 	}
       
   238 
       
   239 void CLogServCacheStrings::InitializeColNumsL(RDbRowSet& aRowSet)
       
   240 	{
       
   241 	if(iIdColNo == 0)
       
   242 		{
       
   243 		CDbColSet* colset = aRowSet.ColSetL();
       
   244 		iIdColNo = colset->ColNo(KLogFieldStringIdString);
       
   245 		iStringColNo = colset->ColNo(KLogFieldStringTextString);
       
   246 		delete colset;
       
   247 		}
       
   248 	__ASSERT_DEBUG(iIdColNo > 0, Panic(ELogInvalidStringColNo));
       
   249 	__ASSERT_DEBUG(iStringColNo > 0, Panic(ELogInvalidStringColNo));
       
   250 	}
       
   251 
       
   252 void CLogServCacheStrings::TLogServCacheStringEntry::CleanupEntry(TAny* aEntry)
       
   253 	{
       
   254 	TLogServCacheStringEntry* entry = reinterpret_cast <TLogServCacheStringEntry*> (aEntry);
       
   255 	CLogServCacheStrings::TLogServCacheStringEntry::DeleteEntry(entry);
       
   256 	}