os/persistentdata/loggingservices/eventlogger/LogServ/src/LOGQUERY.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/LOGQUERY.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,478 @@
     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 "LOGQUERY.H"
    1.20 +#include "logservpanic.h"
    1.21 +#include "LogServDatabaseTransactionInterface.h"
    1.22 +#include "LogServDatabaseChangeInterface.h"
    1.23 +#include "LogServSqlStrings.h"
    1.24 +#include "LogDynBuf.h"
    1.25 +
    1.26 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.27 +/////////////////////////         RLogDbTable             /////////////////////////////////////////////////////////
    1.28 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.29 +
    1.30 +/**
    1.31 +RLogDbTable "resource acquisition" method.
    1.32 +Opens the specified database table with the required access mode.
    1.33 +If the database indexes are damaged, before the "table open" operation, an attempt will be made to recover the databasde.
    1.34 +If the table is opened successfully, the current RLogDbTable object will be put on the cleanup stack. The caller is
    1.35 +responsible for the destruction of the RLogDbTable object. 
    1.36 +
    1.37 +@param aDb RDbDatabase reference
    1.38 +@param aTblName Table name
    1.39 +@param aAccess Table access mode, one of RDbRowSet::TAccess enum item values
    1.40 +
    1.41 +@leave  KErrNoMemory, an out of memory condition has occurred;
    1.42 +                      Note that the function may leave with database specific errors and
    1.43 +                      other system-wide error codes.
    1.44 +*/
    1.45 +void RLogDbTable::OpenLC(RDbDatabase& aDb, const TDesC& aTblName, RDbRowSet::TAccess aAccess)
    1.46 +    {
    1.47 +    if(aDb.IsDamaged())
    1.48 +        {
    1.49 +        User::LeaveIfError(aDb.Recover());
    1.50 +        }
    1.51 +    __ASSERT_DEBUG(!aDb.IsDamaged(), Panic(ELogDatabaseDamaged2));
    1.52 +    CleanupClosePushL(*this);
    1.53 +    User::LeaveIfError(RDbTable::Open(aDb, aTblName, aAccess));
    1.54 +    }
    1.55 +
    1.56 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.57 +/////////////////////////         RLogEventDbTable             ////////////////////////////////////////////////////
    1.58 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.59 +
    1.60 +TDbColNo RLogEventDbTable::iIdColNo = 0;
    1.61 +TDbColNo RLogEventDbTable::iTypeColNo = 0;
    1.62 +TDbColNo RLogEventDbTable::iRemotePartyColNo = 0;
    1.63 +TDbColNo RLogEventDbTable::iDirectionColNo = 0;
    1.64 +TDbColNo RLogEventDbTable::iTimeColNo = 0;
    1.65 +TDbColNo RLogEventDbTable::iDurationTypeColNo = 0;
    1.66 +TDbColNo RLogEventDbTable::iDurationColNo = 0;
    1.67 +TDbColNo RLogEventDbTable::iStatusColNo = 0;
    1.68 +TDbColNo RLogEventDbTable::iSubjectColNo = 0;
    1.69 +TDbColNo RLogEventDbTable::iNumberColNo = 0;
    1.70 +TDbColNo RLogEventDbTable::iContactColNo = 0;
    1.71 +TDbColNo RLogEventDbTable::iLinkColNo = 0;
    1.72 +TDbColNo RLogEventDbTable::iDataColNo = 0;
    1.73 +TDbColNo RLogEventDbTable::iFlagColNo[] = {0, 0, 0, 0};
    1.74 +TDbColNo RLogEventDbTable::iRecentColNo = 0;
    1.75 +TDbColNo RLogEventDbTable::iDuplicateColNo = 0;
    1.76 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
    1.77 +TDbColNo RLogEventDbTable::iSimIdColNo = 0;
    1.78 +#endif
    1.79 +
    1.80 +/**
    1.81 +RLogEventDbTable "resource acquisition" method.
    1.82 +Opens the "Event" database table with the required access mode.
    1.83 +If the database indexes are damaged, before the "table open" operation, an attempt will be made to recover the databasde.
    1.84 +If the table is opened successfully, the current RLogEventDbTable object will be put on the cleanup stack. The caller is
    1.85 +responsible for the destruction of the RLogEventDbTable object. 
    1.86 +
    1.87 +@param aDb RDbDatabase reference
    1.88 +@param aAccess Table access mode, one of RDbRowSet::TAccess enum item values
    1.89 +
    1.90 +@leave  KErrNoMemory, an out of memory condition has occurred;
    1.91 +                      Note that the function may leave with database specific errors and
    1.92 +                      other system-wide error codes.
    1.93 +*/
    1.94 +void RLogEventDbTable::OpenLC(RDbDatabase& aDb, RDbRowSet::TAccess aAccess)
    1.95 +    {
    1.96 +    RLogDbTable::OpenLC(aDb, KLogNameEventString, aAccess);
    1.97 +    InitializeColumnsL();
    1.98 +    }
    1.99 +
   1.100 +/**
   1.101 +Initializes the static data members ("Event" table column numbers) of the RLogEventDbTable class.
   1.102 +The initialization happens just once, during the construction of the first object of RLogEventDbTable type. 
   1.103 +
   1.104 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.105 +                      Note that the function may leave with database specific errors and
   1.106 +                      other system-wide error codes.
   1.107 +*/
   1.108 +void RLogEventDbTable::InitializeColumnsL()
   1.109 +    {
   1.110 +    if(RLogEventDbTable::iIdColNo == 0)
   1.111 +        {
   1.112 +        CDbColSet* colset = ColSetL();
   1.113 +        RLogEventDbTable::iIdColNo = colset->ColNo(KLogFieldIdString);
   1.114 +        RLogEventDbTable::iTypeColNo = colset->ColNo(KLogFieldEventTypeString);
   1.115 +        RLogEventDbTable::iRemotePartyColNo = colset->ColNo(KLogFieldEventRemoteString);
   1.116 +        RLogEventDbTable::iDirectionColNo = colset->ColNo(KLogFieldEventDirectionString);
   1.117 +        RLogEventDbTable::iTimeColNo = colset->ColNo(KLogFieldEventTimeString);
   1.118 +        RLogEventDbTable::iDurationTypeColNo = colset->ColNo(KLogFieldEventDTypeString);
   1.119 +        RLogEventDbTable::iDurationColNo = colset->ColNo(KLogFieldEventDurationString);
   1.120 +        RLogEventDbTable::iStatusColNo = colset->ColNo(KLogFieldEventStatusString);
   1.121 +        RLogEventDbTable::iSubjectColNo = colset->ColNo(KLogFieldEventSubjectString);
   1.122 +        RLogEventDbTable::iNumberColNo = colset->ColNo(KLogFieldEventNumberString);
   1.123 +        RLogEventDbTable::iContactColNo = colset->ColNo(KLogFieldEventContactString);
   1.124 +        RLogEventDbTable::iLinkColNo = colset->ColNo(KLogFieldEventLinkString);
   1.125 +        RLogEventDbTable::iDataColNo = colset->ColNo(KLogFieldEventDataString);
   1.126 +        for(TInt i=0;i<KLogFlagsCount;++i)
   1.127 +            {
   1.128 +            TDbColName colname;
   1.129 +            colname.Format(KLogFieldEventFlagString, i + 1);
   1.130 +            RLogEventDbTable::iFlagColNo[i] = colset->ColNo(colname);
   1.131 +            __ASSERT_DEBUG(RLogEventDbTable::iFlagColNo[i] > 0, User::Invariant());
   1.132 +            }
   1.133 +        RLogEventDbTable::iRecentColNo = colset->ColNo(KLogFieldEventRecentString);
   1.134 +        RLogEventDbTable::iDuplicateColNo = colset->ColNo(KLogFieldEventDuplicateString);
   1.135 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
   1.136 +        RLogEventDbTable::iSimIdColNo = colset->ColNo(KLogFieldEventSimId);
   1.137 +#endif        
   1.138 +        delete colset;
   1.139 +        }
   1.140 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
   1.141 +    __ASSERT_DEBUG(RLogEventDbTable::iIdColNo > 0 && 
   1.142 +            RLogEventDbTable::iTypeColNo > 0 &&
   1.143 +            RLogEventDbTable::iRemotePartyColNo > 0 &&
   1.144 +            RLogEventDbTable::iDirectionColNo > 0 &&
   1.145 +            RLogEventDbTable::iTimeColNo > 0 &&
   1.146 +            RLogEventDbTable::iDurationTypeColNo > 0 &&
   1.147 +            RLogEventDbTable::iDurationColNo > 0 &&
   1.148 +            RLogEventDbTable::iStatusColNo > 0 &&
   1.149 +            RLogEventDbTable::iSubjectColNo > 0 &&
   1.150 +            RLogEventDbTable::iNumberColNo > 0 &&
   1.151 +            RLogEventDbTable::iContactColNo > 0 &&
   1.152 +            RLogEventDbTable::iLinkColNo > 0 &&
   1.153 +            RLogEventDbTable::iDataColNo > 0 && 
   1.154 +            RLogEventDbTable::iRecentColNo > 0 &&
   1.155 +            RLogEventDbTable::iDuplicateColNo > 0 && 
   1.156 +            RLogEventDbTable::iSimIdColNo > 0, User::Invariant());
   1.157 +#else
   1.158 +    __ASSERT_DEBUG(RLogEventDbTable::iIdColNo > 0 && 
   1.159 +            RLogEventDbTable::iTypeColNo > 0 &&
   1.160 +            RLogEventDbTable::iRemotePartyColNo > 0 &&
   1.161 +            RLogEventDbTable::iDirectionColNo > 0 &&
   1.162 +            RLogEventDbTable::iTimeColNo > 0 &&
   1.163 +            RLogEventDbTable::iDurationTypeColNo > 0 &&
   1.164 +            RLogEventDbTable::iDurationColNo > 0 &&
   1.165 +            RLogEventDbTable::iStatusColNo > 0 &&
   1.166 +            RLogEventDbTable::iSubjectColNo > 0 &&
   1.167 +            RLogEventDbTable::iNumberColNo > 0 &&
   1.168 +            RLogEventDbTable::iContactColNo > 0 &&
   1.169 +            RLogEventDbTable::iLinkColNo > 0 &&
   1.170 +            RLogEventDbTable::iDataColNo > 0 && 
   1.171 +            RLogEventDbTable::iRecentColNo > 0 &&
   1.172 +            RLogEventDbTable::iDuplicateColNo > 0, User::Invariant());
   1.173 +#endif
   1.174 +    }
   1.175 +
   1.176 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.177 +/////////////////////////         RLogConfigDbTable             ///////////////////////////////////////////////////
   1.178 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.179 +
   1.180 +TDbColNo RLogConfigDbTable::iSizeColNo = 0;
   1.181 +TDbColNo RLogConfigDbTable::iRecentColNo = 0;
   1.182 +TDbColNo RLogConfigDbTable::iAgeColNo = 0;
   1.183 +
   1.184 +/**
   1.185 +RLogConfigDbTable "resource acquisition" method.
   1.186 +Opens the "Config" database table with the required access mode.
   1.187 +If the database indexes are damaged, before the "table open" operation, an attempt will be made to recover the databasde.
   1.188 +If the table is opened successfully, the current RLogConfigDbTable object will be put on the cleanup stack. The caller is
   1.189 +responsible for the destruction of the RLogConfigDbTable object. 
   1.190 +
   1.191 +@param aDb RDbDatabase reference
   1.192 +@param aAccess Table access mode, one of RDbRowSet::TAccess enum item values
   1.193 +
   1.194 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.195 +                      Note that the function may leave with database specific errors and
   1.196 +                      other system-wide error codes.
   1.197 +*/
   1.198 +void RLogConfigDbTable::OpenLC(RDbDatabase& aDb, RDbRowSet::TAccess aAccess)
   1.199 +    {
   1.200 +    RLogDbTable::OpenLC(aDb, KLogNameConfigString, aAccess);
   1.201 +    InitializeColumnsL();
   1.202 +    }
   1.203 +
   1.204 +/**
   1.205 +Initializes the static data members ("Config" table column numbers) of the RLogConfigDbTable class.
   1.206 +The initialization happens just once, during the construction of the first object of RLogConfigDbTable type. 
   1.207 +
   1.208 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.209 +                      Note that the function may leave with database specific errors and
   1.210 +                      other system-wide error codes.
   1.211 +*/
   1.212 +void RLogConfigDbTable::InitializeColumnsL()
   1.213 +    {
   1.214 +    if(RLogConfigDbTable::iSizeColNo == 0)
   1.215 +        {
   1.216 +        CDbColSet* colset = ColSetL();
   1.217 +        RLogConfigDbTable::iSizeColNo = colset->ColNo(KLogFieldConfigSizeString);
   1.218 +        RLogConfigDbTable::iRecentColNo = colset->ColNo(KLogFieldConfigRecentString);
   1.219 +        RLogConfigDbTable::iAgeColNo = colset->ColNo(KLogFieldConfigAgeString);
   1.220 +        delete colset;
   1.221 +        }
   1.222 +    __ASSERT_DEBUG(RLogConfigDbTable::iSizeColNo > 0 && 
   1.223 +            RLogConfigDbTable::iRecentColNo > 0 &&
   1.224 +            RLogConfigDbTable::iAgeColNo > 0, User::Invariant());
   1.225 +    }
   1.226 +
   1.227 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.228 +/////////////////////////         RLogDbView             //////////////////////////////////////////////////////////
   1.229 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.230 +
   1.231 +/**
   1.232 +RLogDbView "resource acquisition" method.
   1.233 +Prepares a database view with the passed as a parameter SQL and with the required access mode.
   1.234 +If the database indexes are damaged, before the "prepare view" operation, an attempt will be made to recover the databasde.
   1.235 +If the view is prepared successfully, the current RLogDbView object will be put on the cleanup stack and all records
   1.236 +evaluated. The caller is responsible for the destruction of the RLogDbView object. 
   1.237 +
   1.238 +@param aDb RDbDatabase reference
   1.239 +@param aQuery View SQL statement 
   1.240 +@param aAccess View access mode, one of RDbRowSet::TAccess enum item values
   1.241 +
   1.242 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.243 +                      Note that the function may leave with database specific errors and
   1.244 +                      other system-wide error codes.
   1.245 +*/
   1.246 +void RLogDbView::PrepareLC(RDbDatabase& aDb, const TDesC& aQuery, RDbRowSet::TAccess aAccess)
   1.247 +	{
   1.248 +	if(aDb.IsDamaged())
   1.249 +		{
   1.250 +		User::LeaveIfError(aDb.Recover());
   1.251 +		}
   1.252 +	__ASSERT_DEBUG(!aDb.IsDamaged(), Panic(ELogDatabaseDamaged2));
   1.253 +	CleanupClosePushL(*this);
   1.254 +	User::LeaveIfError(RDbView::Prepare(aDb, TDbQuery(aQuery, EDbCompareFolded), aAccess));
   1.255 +	User::LeaveIfError(RDbView::EvaluateAll());
   1.256 +	}
   1.257 +
   1.258 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.259 +/////////////////////////         Global functions             ////////////////////////////////////////////////////
   1.260 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.261 +
   1.262 +/**
   1.263 +Runs the KLogSqlGetRecent SQL query and puts the IDs of the retrieved events into the aEventIds output array.
   1.264 +This happens only if the retrieved events count is bigger than the aMaxRecentLogSize parameter. 
   1.265 +
   1.266 +@param aDb A MLogServDatabaseTransactionInterface reference
   1.267 +@param aRecentListId Recent list Id
   1.268 +@param aMaxRecentLogSize Max recent list size
   1.269 +@param aEventIds Output parameter. The function will put it on the cleanup stack and fill it with
   1.270 +                 the events ids from the recent list. The caller is responsible for the destruction of
   1.271 +                 the aEventIds parameter.
   1.272 +
   1.273 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.274 +               Note that the function may leave with database specific errors and
   1.275 +                other system-wide error codes.
   1.276 +
   1.277 +@internalComponent 
   1.278 +*/
   1.279 +void LogGetRecentEventsLC(MLogServDatabaseTransactionInterface& aDb, TLogRecentList aRecentListId, 
   1.280 +                          TLogRecentSize aMaxRecentLogSize, RArray<TLogId>& aEventIds)
   1.281 +    {
   1.282 +    CleanupClosePushL(aEventIds);
   1.283 +    TheSql.Format(KLogSqlGetRecent, aRecentListId);
   1.284 +    RLogDbView view;                
   1.285 +    view.PrepareLC(aDb.DTIDatabase(), TheSql, RDbRowSet::EReadOnly);
   1.286 +    TInt count = view.CountL() - aMaxRecentLogSize;
   1.287 +    if(count > 0)
   1.288 +        {
   1.289 +        (void)view.LastL();//If "count > 0", then there is at least one record => LastL() cannot return EFalse. 
   1.290 +        static TDbColNo idColNo = 0;
   1.291 +        if(idColNo == 0)
   1.292 +            {
   1.293 +            CDbColSet* colset = view.ColSetL();
   1.294 +            idColNo = colset->ColNo(KLogFieldIdString);
   1.295 +            delete colset;
   1.296 +            }
   1.297 +        aEventIds.ReserveL(count);
   1.298 +        do
   1.299 +            {
   1.300 +            view.GetL();
   1.301 +            aEventIds.AppendL(view.ColInt32(idColNo));
   1.302 +            }
   1.303 +        while(--count && view.PreviousL());
   1.304 +        }
   1.305 +    CleanupStack::PopAndDestroy(&view);
   1.306 +    }
   1.307 +
   1.308 +/**
   1.309 +The function accepts an array of event IDs as a parameter, prepares an UPDATE SQL query using those IDs and
   1.310 +puts the constructed query into aSqlBuf output parameter.
   1.311 + 
   1.312 +@param aEventIds Array with event Ids, used for the construction of the SQL statement
   1.313 +@param aSqlBuf Output parameter. A reference to RLogDynBuf object where the SQL is constructed.
   1.314 + 
   1.315 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.316 + 
   1.317 +@internalComponent 
   1.318 +*/
   1.319 +static void LogBuildPurgeRecentSqlL(const RArray<TLogId>& aEventIds, RLogDynBuf& aSqlBuf)
   1.320 +    {
   1.321 +    __ASSERT_DEBUG(aEventIds.Count() > 0, User::Invariant());
   1.322 +    aSqlBuf.SetLength(0);
   1.323 +    aSqlBuf.AppendL(KLogSqlRemoveDuplicateEvents);
   1.324 +    for(TInt i=0,count=aEventIds.Count();i<count;++i)
   1.325 +        {
   1.326 +        TBuf<20> num;//buf size of 20 is enough for a 32-bit number
   1.327 +        num.AppendNum(aEventIds[i]);
   1.328 +        aSqlBuf.AppendL(KIdEqStr);
   1.329 +        aSqlBuf.AppendL(num);
   1.330 +        aSqlBuf.AppendL(KLogOr);
   1.331 +        aSqlBuf.AppendL(KDuplicateEqStr);
   1.332 +        aSqlBuf.AppendL(num);
   1.333 +        aSqlBuf.AppendL(KLogOr);
   1.334 +        }
   1.335 +    aSqlBuf.SetLength(aSqlBuf.Length() - KLogOr().Length()); 
   1.336 +    }
   1.337 +
   1.338 +/**
   1.339 +The function accepts an array of event IDs as a parameter, prepares an UPDATE SQL query and executes
   1.340 +the query.
   1.341 +The MLogServDatabaseChangeInterface interface will be used to collect the information about the IDs of the purged events.
   1.342 +Later that information will be used if there are any outstanding notification requests waiting for completion.  
   1.343 +If the count of the aEventIds elements is 0, then no query will be prepared and executed.
   1.344 +  
   1.345 +@param aDb A reference to MLogServDatabaseTransactionInterface interface
   1.346 +@param aEventIds Array with event Ids, used for the construction of the SQL statement
   1.347 +  
   1.348 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.349 +               Note that the function may leave with database specific errors and
   1.350 +                other system-wide error codes.
   1.351 +  
   1.352 +@internalComponent 
   1.353 +*/
   1.354 +void LogPurgeRecentEventsL(MLogServDatabaseTransactionInterface& aDb, const RArray<TLogId>& aEventIds)
   1.355 +    {
   1.356 +    TInt count = aEventIds.Count();
   1.357 +    if(count == 0)
   1.358 +        {
   1.359 +        return;
   1.360 +        }
   1.361 +    RLogDynBuf sqlBuf;
   1.362 +    sqlBuf.CreateLC(sizeof(KLogSqlRemoveDuplicateEvents) + count * 32);//32 - approx - length of "Duplicate=N OR Id=N"
   1.363 +    LogBuildPurgeRecentSqlL(aEventIds, sqlBuf);
   1.364 +    User::LeaveIfError(aDb.DTIExecuteSql(sqlBuf.DesC()));
   1.365 +    CleanupStack::PopAndDestroy(&sqlBuf);
   1.366 +    for(TInt i=0;i<count;++i)
   1.367 +        {
   1.368 +        // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
   1.369 +        aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, aEventIds[i]);
   1.370 +        }
   1.371 +    }
   1.372 +
   1.373 +/**
   1.374 +If the number of the events in the "Event" table is bigger than the aMaxLogSize parameter, 
   1.375 +the oldest events will be deleted from the table.
   1.376 +The MLogServDatabaseChangeInterface interface will be used to collect the information about the IDs of the deleted events.
   1.377 +Later that information will be used if there are any outstanding notification requests waiting for completion.  
   1.378 +If the number of the events in the "Event" table is less than the aMaxLogSize parameter, then the function does nothing. 
   1.379 + 
   1.380 +@param aDb A reference to MLogServDatabaseTransactionInterface interface
   1.381 +@param aTbl A reference to RLogEventDbTable object
   1.382 +@param aMaxLogSize The max number of events allowed to exist in the "Event" table
   1.383 +@param aCountPlus Integer, added to aMaxLogSize during the "max log size" calculations 
   1.384 +  
   1.385 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.386 +               Note that the function may leave with database specific errors and
   1.387 +                other system-wide error codes.
   1.388 + 
   1.389 +@internalComponent 
   1.390 +*/
   1.391 +void LogPurgeMainL(MLogServDatabaseTransactionInterface& aDb, RLogEventDbTable& aTbl, 
   1.392 +                   TLogSize aMaxLogSize, TInt aCountPlus)
   1.393 +    {
   1.394 +    User::LeaveIfError(aTbl.SetIndex(KLogNameEventIdx1));
   1.395 +    TInt count = aTbl.CountL() + aCountPlus - aMaxLogSize;
   1.396 +    if(count > 0)
   1.397 +        {
   1.398 +        (void)aTbl.FirstL();//If "count > 0", then there is at least one record => FirstL() cannot return EFalse. 
   1.399 +        TBool commit = !aDb.DTIInTransaction();
   1.400 +        if(commit)
   1.401 +            {
   1.402 +            aDb.DTIBeginWithRollBackProtectionLC();
   1.403 +            }
   1.404 +        do
   1.405 +            {
   1.406 +            aTbl.GetL(); 
   1.407 +            TLogId id = aTbl.ColInt32(RLogEventDbTable::iIdColNo);
   1.408 +            aTbl.DeleteL();
   1.409 +            aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventDeleted, id);
   1.410 +            }
   1.411 +        while(--count && aTbl.NextL());
   1.412 +        if(commit)
   1.413 +            {
   1.414 +            aDb.DTICommitAndCancelRollbackProtectionL();
   1.415 +            }
   1.416 +        }
   1.417 +    }
   1.418 +
   1.419 +/**
   1.420 +Updates the event records with "Duplicate" column value equal to aEventId. 
   1.421 +The MLogServDatabaseChangeInterface interface will be used to collect the information about the IDs of the modified events.
   1.422 +Later that information will be used if there are any outstanding notification requests waiting for completion.
   1.423 +If no duplicates of the passed as a parameter event ID exist, then the function does nothing.  
   1.424 + 
   1.425 +@param aDb A reference to MLogServDatabaseTransactionInterface interface
   1.426 +@param aEventId Duplicated event id 
   1.427 +
   1.428 +@leave  KErrNoMemory, an out of memory condition has occurred;
   1.429 +               Note that the function may leave with database specific errors and
   1.430 +                other system-wide error codes.
   1.431 + 
   1.432 +@internalComponent 
   1.433 +*/
   1.434 +void LogResetDuplicatesL(MLogServDatabaseTransactionInterface& aDb, TLogId aEventId)
   1.435 +    {
   1.436 +    TheSql.Format(KLogSqlDuplicateViewString, aEventId, &KNullDesC);
   1.437 +    RLogDbView view;
   1.438 +    view .PrepareLC(aDb.DTIDatabase(), TheSql);
   1.439 +    // Are there any duplicates?
   1.440 +    if(view.FirstL())
   1.441 +        {
   1.442 +        static TDbColNo idColNo = 0;
   1.443 +        static TDbColNo duplicateColNo = 0;
   1.444 +        if(idColNo == 0)
   1.445 +            {
   1.446 +            CDbColSet* colset = view.ColSetL();
   1.447 +            idColNo = colset->ColNo(KLogFieldIdString);
   1.448 +            duplicateColNo = colset->ColNo(KLogFieldEventDuplicateString);
   1.449 +            delete colset;
   1.450 +            }
   1.451 +        TBool commit = !aDb.DTIInTransaction();
   1.452 +        if(commit)
   1.453 +            {
   1.454 +            aDb.DTIBeginWithRollBackProtectionLC();
   1.455 +            }
   1.456 +        // Get the id of the latest event
   1.457 +        view.GetL();
   1.458 +        const TLogId idLatest = view.ColInt32(idColNo);
   1.459 +        // Mark the event as the latest duplicate
   1.460 +        view.UpdateL();
   1.461 +        view.SetColNullL(duplicateColNo);
   1.462 +        view.PutL();
   1.463 +        // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
   1.464 +        aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, idLatest);
   1.465 +        // Reset the duplicate id's of the other duplicates
   1.466 +        while(view.NextL())
   1.467 +            {
   1.468 +            view.UpdateL();
   1.469 +            const TLogId id = view.ColInt32(idColNo);
   1.470 +            view.SetColL(duplicateColNo, idLatest);
   1.471 +            view.PutL();
   1.472 +            // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
   1.473 +            aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
   1.474 +            }
   1.475 +        if(commit)
   1.476 +            {
   1.477 +            aDb.DTICommitAndCancelRollbackProtectionL();
   1.478 +            }
   1.479 +        }
   1.480 +    CleanupStack::PopAndDestroy(&view);
   1.481 +    }