diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/LogServ/src/LOGQUERY.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loggingservices/eventlogger/LogServ/src/LOGQUERY.CPP Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,478 @@ +// 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 "LOGQUERY.H" +#include "logservpanic.h" +#include "LogServDatabaseTransactionInterface.h" +#include "LogServDatabaseChangeInterface.h" +#include "LogServSqlStrings.h" +#include "LogDynBuf.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////// RLogDbTable ///////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +RLogDbTable "resource acquisition" method. +Opens the specified database table with the required access mode. +If the database indexes are damaged, before the "table open" operation, an attempt will be made to recover the databasde. +If the table is opened successfully, the current RLogDbTable object will be put on the cleanup stack. The caller is +responsible for the destruction of the RLogDbTable object. + +@param aDb RDbDatabase reference +@param aTblName Table name +@param aAccess Table access mode, one of RDbRowSet::TAccess enum item values + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. +*/ +void RLogDbTable::OpenLC(RDbDatabase& aDb, const TDesC& aTblName, RDbRowSet::TAccess aAccess) + { + if(aDb.IsDamaged()) + { + User::LeaveIfError(aDb.Recover()); + } + __ASSERT_DEBUG(!aDb.IsDamaged(), Panic(ELogDatabaseDamaged2)); + CleanupClosePushL(*this); + User::LeaveIfError(RDbTable::Open(aDb, aTblName, aAccess)); + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////// RLogEventDbTable //////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TDbColNo RLogEventDbTable::iIdColNo = 0; +TDbColNo RLogEventDbTable::iTypeColNo = 0; +TDbColNo RLogEventDbTable::iRemotePartyColNo = 0; +TDbColNo RLogEventDbTable::iDirectionColNo = 0; +TDbColNo RLogEventDbTable::iTimeColNo = 0; +TDbColNo RLogEventDbTable::iDurationTypeColNo = 0; +TDbColNo RLogEventDbTable::iDurationColNo = 0; +TDbColNo RLogEventDbTable::iStatusColNo = 0; +TDbColNo RLogEventDbTable::iSubjectColNo = 0; +TDbColNo RLogEventDbTable::iNumberColNo = 0; +TDbColNo RLogEventDbTable::iContactColNo = 0; +TDbColNo RLogEventDbTable::iLinkColNo = 0; +TDbColNo RLogEventDbTable::iDataColNo = 0; +TDbColNo RLogEventDbTable::iFlagColNo[] = {0, 0, 0, 0}; +TDbColNo RLogEventDbTable::iRecentColNo = 0; +TDbColNo RLogEventDbTable::iDuplicateColNo = 0; +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM +TDbColNo RLogEventDbTable::iSimIdColNo = 0; +#endif + +/** +RLogEventDbTable "resource acquisition" method. +Opens the "Event" database table with the required access mode. +If the database indexes are damaged, before the "table open" operation, an attempt will be made to recover the databasde. +If the table is opened successfully, the current RLogEventDbTable object will be put on the cleanup stack. The caller is +responsible for the destruction of the RLogEventDbTable object. + +@param aDb RDbDatabase reference +@param aAccess Table access mode, one of RDbRowSet::TAccess enum item values + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. +*/ +void RLogEventDbTable::OpenLC(RDbDatabase& aDb, RDbRowSet::TAccess aAccess) + { + RLogDbTable::OpenLC(aDb, KLogNameEventString, aAccess); + InitializeColumnsL(); + } + +/** +Initializes the static data members ("Event" table column numbers) of the RLogEventDbTable class. +The initialization happens just once, during the construction of the first object of RLogEventDbTable type. + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. +*/ +void RLogEventDbTable::InitializeColumnsL() + { + if(RLogEventDbTable::iIdColNo == 0) + { + CDbColSet* colset = ColSetL(); + RLogEventDbTable::iIdColNo = colset->ColNo(KLogFieldIdString); + RLogEventDbTable::iTypeColNo = colset->ColNo(KLogFieldEventTypeString); + RLogEventDbTable::iRemotePartyColNo = colset->ColNo(KLogFieldEventRemoteString); + RLogEventDbTable::iDirectionColNo = colset->ColNo(KLogFieldEventDirectionString); + RLogEventDbTable::iTimeColNo = colset->ColNo(KLogFieldEventTimeString); + RLogEventDbTable::iDurationTypeColNo = colset->ColNo(KLogFieldEventDTypeString); + RLogEventDbTable::iDurationColNo = colset->ColNo(KLogFieldEventDurationString); + RLogEventDbTable::iStatusColNo = colset->ColNo(KLogFieldEventStatusString); + RLogEventDbTable::iSubjectColNo = colset->ColNo(KLogFieldEventSubjectString); + RLogEventDbTable::iNumberColNo = colset->ColNo(KLogFieldEventNumberString); + RLogEventDbTable::iContactColNo = colset->ColNo(KLogFieldEventContactString); + RLogEventDbTable::iLinkColNo = colset->ColNo(KLogFieldEventLinkString); + RLogEventDbTable::iDataColNo = colset->ColNo(KLogFieldEventDataString); + for(TInt i=0;iColNo(colname); + __ASSERT_DEBUG(RLogEventDbTable::iFlagColNo[i] > 0, User::Invariant()); + } + RLogEventDbTable::iRecentColNo = colset->ColNo(KLogFieldEventRecentString); + RLogEventDbTable::iDuplicateColNo = colset->ColNo(KLogFieldEventDuplicateString); +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM + RLogEventDbTable::iSimIdColNo = colset->ColNo(KLogFieldEventSimId); +#endif + delete colset; + } +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM + __ASSERT_DEBUG(RLogEventDbTable::iIdColNo > 0 && + RLogEventDbTable::iTypeColNo > 0 && + RLogEventDbTable::iRemotePartyColNo > 0 && + RLogEventDbTable::iDirectionColNo > 0 && + RLogEventDbTable::iTimeColNo > 0 && + RLogEventDbTable::iDurationTypeColNo > 0 && + RLogEventDbTable::iDurationColNo > 0 && + RLogEventDbTable::iStatusColNo > 0 && + RLogEventDbTable::iSubjectColNo > 0 && + RLogEventDbTable::iNumberColNo > 0 && + RLogEventDbTable::iContactColNo > 0 && + RLogEventDbTable::iLinkColNo > 0 && + RLogEventDbTable::iDataColNo > 0 && + RLogEventDbTable::iRecentColNo > 0 && + RLogEventDbTable::iDuplicateColNo > 0 && + RLogEventDbTable::iSimIdColNo > 0, User::Invariant()); +#else + __ASSERT_DEBUG(RLogEventDbTable::iIdColNo > 0 && + RLogEventDbTable::iTypeColNo > 0 && + RLogEventDbTable::iRemotePartyColNo > 0 && + RLogEventDbTable::iDirectionColNo > 0 && + RLogEventDbTable::iTimeColNo > 0 && + RLogEventDbTable::iDurationTypeColNo > 0 && + RLogEventDbTable::iDurationColNo > 0 && + RLogEventDbTable::iStatusColNo > 0 && + RLogEventDbTable::iSubjectColNo > 0 && + RLogEventDbTable::iNumberColNo > 0 && + RLogEventDbTable::iContactColNo > 0 && + RLogEventDbTable::iLinkColNo > 0 && + RLogEventDbTable::iDataColNo > 0 && + RLogEventDbTable::iRecentColNo > 0 && + RLogEventDbTable::iDuplicateColNo > 0, User::Invariant()); +#endif + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////// RLogConfigDbTable /////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TDbColNo RLogConfigDbTable::iSizeColNo = 0; +TDbColNo RLogConfigDbTable::iRecentColNo = 0; +TDbColNo RLogConfigDbTable::iAgeColNo = 0; + +/** +RLogConfigDbTable "resource acquisition" method. +Opens the "Config" database table with the required access mode. +If the database indexes are damaged, before the "table open" operation, an attempt will be made to recover the databasde. +If the table is opened successfully, the current RLogConfigDbTable object will be put on the cleanup stack. The caller is +responsible for the destruction of the RLogConfigDbTable object. + +@param aDb RDbDatabase reference +@param aAccess Table access mode, one of RDbRowSet::TAccess enum item values + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. +*/ +void RLogConfigDbTable::OpenLC(RDbDatabase& aDb, RDbRowSet::TAccess aAccess) + { + RLogDbTable::OpenLC(aDb, KLogNameConfigString, aAccess); + InitializeColumnsL(); + } + +/** +Initializes the static data members ("Config" table column numbers) of the RLogConfigDbTable class. +The initialization happens just once, during the construction of the first object of RLogConfigDbTable type. + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. +*/ +void RLogConfigDbTable::InitializeColumnsL() + { + if(RLogConfigDbTable::iSizeColNo == 0) + { + CDbColSet* colset = ColSetL(); + RLogConfigDbTable::iSizeColNo = colset->ColNo(KLogFieldConfigSizeString); + RLogConfigDbTable::iRecentColNo = colset->ColNo(KLogFieldConfigRecentString); + RLogConfigDbTable::iAgeColNo = colset->ColNo(KLogFieldConfigAgeString); + delete colset; + } + __ASSERT_DEBUG(RLogConfigDbTable::iSizeColNo > 0 && + RLogConfigDbTable::iRecentColNo > 0 && + RLogConfigDbTable::iAgeColNo > 0, User::Invariant()); + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////// RLogDbView ////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +RLogDbView "resource acquisition" method. +Prepares a database view with the passed as a parameter SQL and with the required access mode. +If the database indexes are damaged, before the "prepare view" operation, an attempt will be made to recover the databasde. +If the view is prepared successfully, the current RLogDbView object will be put on the cleanup stack and all records +evaluated. The caller is responsible for the destruction of the RLogDbView object. + +@param aDb RDbDatabase reference +@param aQuery View SQL statement +@param aAccess View access mode, one of RDbRowSet::TAccess enum item values + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. +*/ +void RLogDbView::PrepareLC(RDbDatabase& aDb, const TDesC& aQuery, RDbRowSet::TAccess aAccess) + { + if(aDb.IsDamaged()) + { + User::LeaveIfError(aDb.Recover()); + } + __ASSERT_DEBUG(!aDb.IsDamaged(), Panic(ELogDatabaseDamaged2)); + CleanupClosePushL(*this); + User::LeaveIfError(RDbView::Prepare(aDb, TDbQuery(aQuery, EDbCompareFolded), aAccess)); + User::LeaveIfError(RDbView::EvaluateAll()); + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////// Global functions //////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** +Runs the KLogSqlGetRecent SQL query and puts the IDs of the retrieved events into the aEventIds output array. +This happens only if the retrieved events count is bigger than the aMaxRecentLogSize parameter. + +@param aDb A MLogServDatabaseTransactionInterface reference +@param aRecentListId Recent list Id +@param aMaxRecentLogSize Max recent list size +@param aEventIds Output parameter. The function will put it on the cleanup stack and fill it with + the events ids from the recent list. The caller is responsible for the destruction of + the aEventIds parameter. + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. + +@internalComponent +*/ +void LogGetRecentEventsLC(MLogServDatabaseTransactionInterface& aDb, TLogRecentList aRecentListId, + TLogRecentSize aMaxRecentLogSize, RArray& aEventIds) + { + CleanupClosePushL(aEventIds); + TheSql.Format(KLogSqlGetRecent, aRecentListId); + RLogDbView view; + view.PrepareLC(aDb.DTIDatabase(), TheSql, RDbRowSet::EReadOnly); + TInt count = view.CountL() - aMaxRecentLogSize; + if(count > 0) + { + (void)view.LastL();//If "count > 0", then there is at least one record => LastL() cannot return EFalse. + static TDbColNo idColNo = 0; + if(idColNo == 0) + { + CDbColSet* colset = view.ColSetL(); + idColNo = colset->ColNo(KLogFieldIdString); + delete colset; + } + aEventIds.ReserveL(count); + do + { + view.GetL(); + aEventIds.AppendL(view.ColInt32(idColNo)); + } + while(--count && view.PreviousL()); + } + CleanupStack::PopAndDestroy(&view); + } + +/** +The function accepts an array of event IDs as a parameter, prepares an UPDATE SQL query using those IDs and +puts the constructed query into aSqlBuf output parameter. + +@param aEventIds Array with event Ids, used for the construction of the SQL statement +@param aSqlBuf Output parameter. A reference to RLogDynBuf object where the SQL is constructed. + +@leave KErrNoMemory, an out of memory condition has occurred; + +@internalComponent +*/ +static void LogBuildPurgeRecentSqlL(const RArray& aEventIds, RLogDynBuf& aSqlBuf) + { + __ASSERT_DEBUG(aEventIds.Count() > 0, User::Invariant()); + aSqlBuf.SetLength(0); + aSqlBuf.AppendL(KLogSqlRemoveDuplicateEvents); + for(TInt i=0,count=aEventIds.Count();i num;//buf size of 20 is enough for a 32-bit number + num.AppendNum(aEventIds[i]); + aSqlBuf.AppendL(KIdEqStr); + aSqlBuf.AppendL(num); + aSqlBuf.AppendL(KLogOr); + aSqlBuf.AppendL(KDuplicateEqStr); + aSqlBuf.AppendL(num); + aSqlBuf.AppendL(KLogOr); + } + aSqlBuf.SetLength(aSqlBuf.Length() - KLogOr().Length()); + } + +/** +The function accepts an array of event IDs as a parameter, prepares an UPDATE SQL query and executes +the query. +The MLogServDatabaseChangeInterface interface will be used to collect the information about the IDs of the purged events. +Later that information will be used if there are any outstanding notification requests waiting for completion. +If the count of the aEventIds elements is 0, then no query will be prepared and executed. + +@param aDb A reference to MLogServDatabaseTransactionInterface interface +@param aEventIds Array with event Ids, used for the construction of the SQL statement + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. + +@internalComponent +*/ +void LogPurgeRecentEventsL(MLogServDatabaseTransactionInterface& aDb, const RArray& aEventIds) + { + TInt count = aEventIds.Count(); + if(count == 0) + { + return; + } + RLogDynBuf sqlBuf; + sqlBuf.CreateLC(sizeof(KLogSqlRemoveDuplicateEvents) + count * 32);//32 - approx - length of "Duplicate=N OR Id=N" + LogBuildPurgeRecentSqlL(aEventIds, sqlBuf); + User::LeaveIfError(aDb.DTIExecuteSql(sqlBuf.DesC())); + CleanupStack::PopAndDestroy(&sqlBuf); + for(TInt i=0;i 0) + { + (void)aTbl.FirstL();//If "count > 0", then there is at least one record => FirstL() cannot return EFalse. + TBool commit = !aDb.DTIInTransaction(); + if(commit) + { + aDb.DTIBeginWithRollBackProtectionLC(); + } + do + { + aTbl.GetL(); + TLogId id = aTbl.ColInt32(RLogEventDbTable::iIdColNo); + aTbl.DeleteL(); + aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventDeleted, id); + } + while(--count && aTbl.NextL()); + if(commit) + { + aDb.DTICommitAndCancelRollbackProtectionL(); + } + } + } + +/** +Updates the event records with "Duplicate" column value equal to aEventId. +The MLogServDatabaseChangeInterface interface will be used to collect the information about the IDs of the modified events. +Later that information will be used if there are any outstanding notification requests waiting for completion. +If no duplicates of the passed as a parameter event ID exist, then the function does nothing. + +@param aDb A reference to MLogServDatabaseTransactionInterface interface +@param aEventId Duplicated event id + +@leave KErrNoMemory, an out of memory condition has occurred; + Note that the function may leave with database specific errors and + other system-wide error codes. + +@internalComponent +*/ +void LogResetDuplicatesL(MLogServDatabaseTransactionInterface& aDb, TLogId aEventId) + { + TheSql.Format(KLogSqlDuplicateViewString, aEventId, &KNullDesC); + RLogDbView view; + view .PrepareLC(aDb.DTIDatabase(), TheSql); + // Are there any duplicates? + if(view.FirstL()) + { + static TDbColNo idColNo = 0; + static TDbColNo duplicateColNo = 0; + if(idColNo == 0) + { + CDbColSet* colset = view.ColSetL(); + idColNo = colset->ColNo(KLogFieldIdString); + duplicateColNo = colset->ColNo(KLogFieldEventDuplicateString); + delete colset; + } + TBool commit = !aDb.DTIInTransaction(); + if(commit) + { + aDb.DTIBeginWithRollBackProtectionLC(); + } + // Get the id of the latest event + view.GetL(); + const TLogId idLatest = view.ColInt32(idColNo); + // Mark the event as the latest duplicate + view.UpdateL(); + view.SetColNullL(duplicateColNo); + view.PutL(); + // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed + aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, idLatest); + // Reset the duplicate id's of the other duplicates + while(view.NextL()) + { + view.UpdateL(); + const TLogId id = view.ColInt32(idColNo); + view.SetColL(duplicateColNo, idLatest); + view.PutL(); + // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed + aDb.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id); + } + if(commit) + { + aDb.DTICommitAndCancelRollbackProtectionL(); + } + } + CleanupStack::PopAndDestroy(&view); + }