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