--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/loggingservices/eventlogger/LogServ/src/LogServView.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,861 @@
+// 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 "LogServView.h"
+#include "logpackage.h"
+#include "logservpanic.h"
+#include "LogServBackupInterface.h"
+#include "LogServViewChangeManager.h"
+#include "LogServDatabaseChangeInterface.h"
+#include "LogServCacheTypes.h"
+#include "LogServSqlStrings.h"
+#include "LOGFILTQ.H"
+
+// Constants
+const TInt KLogViewContentsGranuality = 20;
+const TInt KLogViewLockStatusEventGranularity = 3;
+
+TDbColNo CLogServViewBase::iIdColNo = 0;
+TDbColNo CLogServViewBase::iTypeColNo = 0;
+TDbColNo CLogServViewBase::iFlagColNo[] = {0, 0, 0, 0};
+
+TDbColNo CLogServViewRecent::iIdColNo = 0;
+TDbColNo CLogServViewRecent::iRecentColNo = 0;
+TDbColNo CLogServViewRecent::iDuplicateColNo = 0;
+
+//diagnostic message for the platform security
+const char* KIgnoreDiagnostic = "This diagnostic message does not indicate an error, please ignore it";
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// -----> CLogServViewBase (source)
+/////////////////////////////////////////////////////////////////////////////////////////
+CLogServViewBase::CLogServViewBase(MLogServDatabaseTransactionInterface& aDatabase,
+ MLogServBackupInterface& aBackupInterface,
+ CLogPackage& aPackage, TLogViewType aType, TLogViewId aViewId,
+ const RMessage2& aMessage) :
+ iDatabase(aDatabase),
+ iPackage(aPackage),
+ iBackupInterface(aBackupInterface),
+ iType(aType),
+ iViewId(aViewId),
+ iMessage (aMessage)
+ {
+ }
+
+CLogServViewBase::~CLogServViewBase()
+ {
+ iDatabase.DTIChangeInterface().DCIRequestChangeNotificationsCancel(*this);
+ iBackupInterface.BIObserverRemove(*this);
+ //
+ iViewContents.Close();
+ //
+ iStandardTypeSecurityCache.Close();
+ //
+ delete iLockChangeObserver;
+ delete iSql;
+ delete iChangeManager;
+ }
+
+
+void CLogServViewBase::ConstructL()
+ {
+ // Handles changes for this view
+ iChangeManager = CLogServViewChangeManager::NewL(iDatabase.DTIChangeInterface());
+
+ // Register for change events
+ iDatabase.DTIChangeInterface().DCIRequestChangeNotificationsL(*this);
+
+ // Register for backup events
+ iBackupInterface.BIObserverAddL(*this, MLogServBackupInterface::EObjectView);
+
+ // Observes when the view is locked/unlocked due to a backup
+ iLockChangeObserver = CLogServViewLockObserver::NewL(iBackupInterface);
+
+ const RArray<TUid>& arrTUids = iDatabase.DTIUidsOfStandardTypes();
+ TInt count = arrTUids.Count();
+ iStandardTypeSecurityCache.ReserveL(count);
+ for(TInt i=0; i < count; i++)
+ {
+ SStandardTypeSecurity securitySetting;
+ securitySetting.eventType = arrTUids[i];
+ securitySetting.readAccess = iDatabase.DTIIsAllowed(EReadOp, iMessage, arrTUids[i], KIgnoreDiagnostic);
+ securitySetting.writeAccess = iDatabase.DTIIsAllowed(EWriteOp, iMessage, arrTUids[i], KIgnoreDiagnostic);
+ TInt err = iStandardTypeSecurityCache.Append(securitySetting);
+ __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
+ }
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewBase::DCOHandleChangeEventsL(const CLogChangeDefinition& aChanges)
+ {
+ // Just return if the view isn't setup
+ if (!iSql)
+ return;
+
+ TRAPD(error, DoHandleChangeEventsL(aChanges));
+ if (error != KErrNone)
+ {
+ iViewContents.Close();
+ iViewContentsReady = EFalse;
+ iRebuildViewContents = ETrue;
+ }
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewBase::BOHandleEventL(TLogServBackupEvent aEvent)
+ {
+ switch(aEvent)
+ {
+ case EBackupStarting:
+ iViewContents.Close();
+ iViewContentsReady = EFalse;
+ break;
+ case EBackupEnded:
+ RebuildViewL();
+ break;
+ }
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma BullseyeCoverage off
+
+/**
+Remove an entry from the view.
+By default you can't remove an event from a view.
+*/
+void CLogServViewBase::RemoveL(const RMessage2& /*aMessage*/)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+/**
+By default you can't clear duplicates from a view
+*/
+void CLogServViewBase::ClearDuplicatesL(const RMessage2& /*aMessage*/)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+#pragma BullseyeCoverage on
+
+/**
+Set the flags of all the entries in the view.
+*/
+void CLogServViewBase::SetFlagsL(const RMessage2& aMessage)
+ {
+ if (ViewIsReady())
+ {
+ // Flags from client
+ const TLogFlags flags = static_cast<TLogFlags>(aMessage.Int2());
+ RLogDbView view;
+ view.PrepareLC(iDatabase.DTIDatabase(), *iSql);
+ InitializeColumnsL(view);
+ if(view.FirstL())
+ {
+ iDatabase.DTIBeginWithRollBackProtectionLC();
+ // Iterate through the events
+ do
+ {
+ // Get current event id
+ view.GetL();
+ const TLogId id = view.ColInt32(CLogServViewBase::iIdColNo);
+ TUint8 eventTypeIndex = view.ColUint8(CLogServViewBase::iTypeColNo);
+ if(IsAllowed(EWriteOp, eventTypeIndex))
+ {
+ // Make the change
+ view.UpdateL();
+ TInt bit = KLogFlagsCount;
+ while(bit--)
+ {
+ const TBool flagIsSet = flags & (0x1 << bit) ? 1 : 0;
+ view.SetColL(CLogServViewBase::iFlagColNo[bit], flagIsSet);
+ }
+ view.PutL();
+ iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChanged, id);
+ }
+ }
+ while(view.NextL());
+ iDatabase.DTICommitAndCancelRollbackProtectionL();
+ }
+ CleanupStack::PopAndDestroy(&view);
+ }
+ else
+ ::PanicClientL(aMessage, ELogViewRecentViewNotYetReadyForFlagSetting);
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+The client has requested change notifications
+*/
+void CLogServViewBase::RequestChangeNotifications(const RMessage2& aMessage)
+ {
+ iChangeManager->RequestChangeNotifications(aMessage);
+ }
+
+/**
+The client has cancelled a previous change notification request
+*/
+void CLogServViewBase::RequestChangeNotificationsCancel()
+ {
+ iChangeManager->RequestChangeNotificationsCancel();
+ }
+
+/**
+The client has requested lock status change notifications
+*/
+void CLogServViewBase::RequestLockStatusChanges(const RMessage2& aMessage)
+ {
+ iLockChangeObserver->RequestLockStatusChanges(aMessage);
+ }
+
+/**
+The client has cancelled a previous change notification request
+*/
+void CLogServViewBase::RequestLockStatusChangesCancel()
+ {
+ iLockChangeObserver->RequestLockStatusChangesCancel();
+ }
+
+/**
+The client has requested the current list of changes
+*/
+void CLogServViewBase::RequestChangesL(const RMessage2& aMessage)
+ {
+ if (!iSql)
+ ::PanicClientL(aMessage, ELogViewNotSetupForChangesFetch);
+ else
+ iChangeManager->DeliverChangesL(aMessage);
+ }
+
+/**
+Set up the server-side view based upon the client-side filter. This
+method essentially fetches a client-side filter and then dynamically
+executes the associated SELECT statement on the database to build up
+a view. This view is then cached in terms of the entry ids (iViewContents).
+*/
+void CLogServViewBase::SetupL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
+ {
+ // Get the query string
+ const TPtrC pSQL(GetQueryStringL(aMessage, aFilterType));
+ HBufC* buf = pSQL.AllocLC();
+ // Setup the contents
+ PrepareViewContentsL(pSQL);
+ // Tidy up
+ CleanupStack::Pop(buf);
+ delete iSql;
+ iSql = buf;
+ }
+
+/**
+Returns the number of entries in this view
+*/
+TInt CLogServViewBase::Count() const
+ {
+ return const_cast<CLogServViewBase*>(this)->RebuildViewContentsIfNecessary() ? 0 : iViewContents.Count();
+ }
+
+/**
+Get the log id at the specified index
+*/
+TLogId CLogServViewBase::At(TInt aIndex) const
+ {
+ return (TUint)aIndex < iViewContents.Count() ? iViewContents[aIndex] : KLogNullId;
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewBase::DestroyList(TAny *aPtr)
+ {
+ CLogFilterList* filter = reinterpret_cast<CLogFilterList*>(aPtr);
+ filter->ResetAndDestroy();
+ delete filter;
+ }
+
+void CLogServViewBase::InitializeColumnsL(RDbRowSet& aRowSet)
+ {
+ if(CLogServViewBase::iIdColNo == 0)
+ {
+ CDbColSet* colset = aRowSet.ColSetL();
+ CLogServViewBase::iIdColNo = colset->ColNo(KLogFieldIdString);
+ CLogServViewBase::iTypeColNo = colset->ColNo(KLogFieldEventTypeString);
+ for(TInt i=0;i<KLogFlagsCount;++i)
+ {
+ TDbColName colname;
+ colname.Format(KLogFieldEventFlagString, i + 1);
+ CLogServViewBase::iFlagColNo[i] = colset->ColNo(colname);
+ __ASSERT_DEBUG(CLogServViewBase::iFlagColNo[i] > 0, User::Invariant());
+ }
+ delete colset;
+ }
+ __ASSERT_DEBUG(CLogServViewBase::iIdColNo > 0 && CLogServViewBase::iTypeColNo > 0, User::Invariant());
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewBase::ResetViewContentsL(RDbRowSet& aRowSet)
+ {
+ // Get the view contents
+ RArray<TLogId> viewContents(KLogViewContentsGranuality);
+ CleanupClosePushL(viewContents);
+ viewContents.ReserveL(aRowSet.CountL());
+ if(aRowSet.FirstL())
+ {
+ do
+ {
+ // Get the id at the current position
+ aRowSet.GetL();
+ const TLogId id = aRowSet.ColInt32(CLogServViewBase::iIdColNo);
+ TUint8 eventTypeIndex = aRowSet.ColUint8(CLogServViewBase::iTypeColNo);
+ if(IsAllowed(EReadOp, eventTypeIndex))
+ {
+ TInt err = viewContents.Append(id);
+ __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
+ }
+ }
+ while(aRowSet.NextL());
+ }
+ // Tidy up - don't leave from below here
+ CleanupStack::Pop(&viewContents);
+ iViewContents.Close();
+ iViewContents = viewContents;
+ iViewContentsReady = ETrue;
+ }
+
+void CLogServViewBase::PrepareViewContentsL(const TDesC& aSQL)
+ {
+ // Generate the view
+ RLogDbView view;
+ view.PrepareLC(iDatabase.DTIDatabase(), aSQL);
+ InitializeColumnsL(view);
+ // Reset the view
+ ResetViewContentsL(view);
+ CleanupStack::PopAndDestroy(&view);
+ }
+
+void CLogServViewBase::RebuildViewL()
+ {
+ if (iSql && iSql->Length())
+ PrepareViewContentsL(*iSql);
+ }
+
+//
+// The last change notification indication was not handled correctly.
+// Attempt to re-initialise the view
+//
+TInt CLogServViewBase::RebuildViewContentsIfNecessary()
+ {
+ TInt error = KErrNone;
+ //
+ if (iRebuildViewContents && iSql && iSql->Length())
+ {
+ TRAP(error,
+
+ RebuildViewL();
+
+ // The view is okay now
+ iRebuildViewContents = EFalse;
+ );
+ }
+ return error;
+ }
+
+void CLogServViewBase::DoHandleChangeEventsL(const CLogChangeDefinition& aChanges)
+ {
+ if(!ViewIsReady())
+ {
+ return;
+ }
+
+ // Generate the view
+ RLogDbView view;
+ view.PrepareLC(iDatabase.DTIDatabase(), *iSql);
+ InitializeColumnsL(view);
+ _LIT(KLogIdQuery, "Id = %d");
+ TBuf<15> find;
+ TInt changeIndex;
+
+ // Prepare for a change transaction
+ iChangeManager->ChangeTransactionPrepare();
+
+ const TInt count = aChanges.Count();
+ for(TInt i=0; i<count; i++)
+ {
+ // Fetch the change details
+ TLogId logId = KLogNullId;
+ TLogDatabaseChangeType type = aChanges.At(i, logId);
+
+ // Mark the insertion position as 'not found'
+ changeIndex = KErrNotFound;
+
+ // Format the find query
+ find.Format(KLogIdQuery, logId);
+
+ // Handle the various change descriptions
+ switch(type)
+ {
+ case ELogChangeTypeEventAdded:
+ {
+ __ASSERT_DEBUG(iViewContents.Find(logId) == KErrNotFound, Panic(ELogEventAlreadyInView));
+
+ // See if the event is in the view
+ if(view.FirstL())
+ {
+ const TDbQuery dbQuery(find);
+ changeIndex = view.FindL(RDbRowSet::EForwards, dbQuery);
+ if (changeIndex >= 0)
+ {
+ view.GetL();
+ TUint8 eventTypeIndex = view.ColUint8(CLogServViewBase::iTypeColNo);
+ if (IsAllowed(EReadOp, eventTypeIndex))
+ User::LeaveIfError(iViewContents.Insert(logId, changeIndex));
+
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventAdded, changeIndex);
+ }
+ }
+ }
+ break;
+ case ELogChangeTypeEventChanged:
+ case ELogChangeTypeEventChangedHidden:
+ {
+ // See if the event is in the view
+ if (view.FirstL() && (changeIndex = view.FindL(RDbRowSet::EForwards, TDbQuery(find))) >= KErrNone)
+ {
+ // If the event was already in the view then it has changed otherwise it's been added
+ const TInt findIndex = iViewContents.Find(logId);
+ if (findIndex >= KErrNone)
+ {
+ // If the item that changed also caused its position within the view to be altered
+ // then we need to simulate a delete, followed by an addition
+ if (findIndex != changeIndex)
+ {
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventDeleted, findIndex);
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventAdded, changeIndex);
+ }
+ // Only tell the view if the CLogEvent has changed
+ else if (type != ELogChangeTypeEventChangedHidden)
+ {
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventChanged, changeIndex);
+ }
+ }
+ else
+ {
+ User::LeaveIfError(iViewContents.Insert(logId, changeIndex));
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventAdded, changeIndex);
+
+ // Update the type to indicate that this change action
+ // really resulted in an addition
+ type = ELogChangeTypeEventAdded;
+ }
+ }
+ else
+ {
+ changeIndex = iViewContents.Find(logId);
+
+ // If it used to be in the view then it's been removed because it's
+ // not in there anymore
+ if (changeIndex >= KErrNone)
+ {
+ iViewContents.Remove(changeIndex);
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventDeleted, changeIndex);
+
+ // Update the type to indicate that this change action
+ // really resulted in a deletion
+ type = ELogChangeTypeEventDeleted;
+ }
+ }
+ }
+ break;
+ case ELogChangeTypeEventDeleted:
+ {
+ changeIndex = iViewContents.Find(logId);
+
+ // If it used to be in the view then tell it about the deletion
+ if (changeIndex >= KErrNone)
+ {
+ iViewContents.Remove(changeIndex);
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventDeleted, changeIndex);
+ }
+ }
+ break;
+ case ELogChangeTypeLogCleared:
+ {
+ RebuildViewL();
+ iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeLogCleared, 0);
+ }
+ break;
+ default:
+ __ASSERT_DEBUG(EFalse, Panic(ELogUnrecognizedChangeType));
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&view);
+
+ // Commit the transaction. Will notify client if necessary
+ iChangeManager->ChangeTransactionCommitL();
+ }
+
+TBool CLogServViewBase::IsAllowed(TEventOp aEventOp, TUint8 aEventTypeIndex)
+ {
+ TBool result = ETrue;
+
+ const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindById(aEventTypeIndex);
+ TUid eventTypeUid = entry.iEventType->Uid();
+ TInt count = iStandardTypeSecurityCache.Count();
+
+ for(TInt i=0;i<count;++i)
+ {
+ if (eventTypeUid == iStandardTypeSecurityCache[i].eventType)
+ {
+ result = (aEventOp == EWriteOp) ? iStandardTypeSecurityCache[i].writeAccess : iStandardTypeSecurityCache[i].readAccess;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// -----> CLogServViewLockObserver (source)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CLogServViewLockObserver::CLogServViewLockObserver(MLogServBackupInterface& aBackupInterface)
+: iBackupInterface(aBackupInterface), iLockEvents(KLogViewLockStatusEventGranularity)
+ {
+ }
+
+CLogServViewLockObserver::~CLogServViewLockObserver()
+ {
+ iBackupInterface.BIObserverRemove(*this);
+ iLockEvents.Close();
+ }
+
+void CLogServViewLockObserver::ConstructL()
+ {
+ // Register for backup events
+ iBackupInterface.BIObserverAddL(*this, MLogServBackupInterface::EObjectViewLock);
+ }
+
+CLogServViewLockObserver* CLogServViewLockObserver::NewL(MLogServBackupInterface& aBackupInterface)
+ {
+ CLogServViewLockObserver* self = new(ELeave) CLogServViewLockObserver(aBackupInterface);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CLogServViewLockObserver::BOHandleEventL(TLogServBackupEvent aEvent)
+ {
+ // Map event
+ TLogViewLockStatus status = ELogViewWindowOpen;
+ if (aEvent == MLogServBackupObserver::EBackupStarting)
+ status = ELogViewWindowLocked;
+
+ // Cache or complete immediately
+ if (!HaveLockStatusChangePointer())
+ User::LeaveIfError(iLockEvents.Append(status));
+ else
+ CompleteLockStatusChangeMessage(status);
+ }
+
+/**
+The client has requested lock status change notifications
+*/
+void CLogServViewLockObserver::RequestLockStatusChanges(const RMessage2& aMessage)
+ {
+ if (!HaveLockStatusChangePointer())
+ {
+ iLockStatusChangeMessage = aMessage;
+
+ // Already have one cached event
+ if (iLockEvents.Count())
+ {
+ CompleteLockStatusChangeMessage(iLockEvents[0]);
+ iLockEvents.Remove(0);
+ }
+ }
+ else
+ PanicClient(aMessage, ELogViewLockStatusChangeRequestAlreadyIssued);
+ }
+
+/**
+The client has cancelled a previous change notification request
+*/
+void CLogServViewLockObserver::RequestLockStatusChangesCancel()
+ {
+ if (HaveLockStatusChangePointer())
+ CompleteLockStatusChangeMessage(KErrCancel);
+ }
+
+void CLogServViewLockObserver::CompleteLockStatusChangeMessage(TInt aCompletionCode)
+ {
+ __ASSERT_ALWAYS(HaveLockStatusChangePointer(), Panic(ELogViewNoLockStatusChangeMessage));
+ iLockStatusChangeMessage.Complete(aCompletionCode);
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// -----> CLogServViewEvent (source)
+/////////////////////////////////////////////////////////////////////////////////////////
+CLogServViewEvent::CLogServViewEvent(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
+: CLogServViewBase(aDatabase, aBackupInterface, aPackage, ELogViewTypeEvent, aViewId, aMessage)
+ {
+ }
+
+CLogServViewEvent* CLogServViewEvent::NewL(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
+ {
+ CLogServViewEvent* self = new(ELeave) CLogServViewEvent(aDatabase, aBackupInterface, aPackage, aViewId, aMessage);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Setup the view
+Fetch the client-side SQL query string which this view uses to obtain a data-set.
+*/
+TPtrC CLogServViewEvent::GetQueryStringL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
+ {
+ // Read stuff from the client
+ iPackage.ResizeL(aMessage.GetDesLengthL(2));
+ aMessage.ReadL(2, iPackage.Ptr());
+
+ // Decode the parameters we've read from the client
+ CLogFilterList* filter = new(ELeave)CLogFilterList;
+ CleanupStack::PushL(TCleanupItem(DestroyList, filter));
+ iPackage.GetLogFilterListL(*filter);
+ RLogDynBuf expr;
+ TLogFilterExprBuilder exprBuilder(iDatabase);
+ exprBuilder.BuildExprLC(expr, *filter, KLogWhere, aFilterType);
+ // Generate the query string that will be used
+ TheSql.Format(KLogSqlEventViewString, &KLogViewSelectColList, &expr.DesC());
+ CleanupStack::PopAndDestroy(2, filter);
+ return TheSql;
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// -----> CLogServViewRecent (source)
+/////////////////////////////////////////////////////////////////////////////////////////
+CLogServViewRecent::CLogServViewRecent(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
+: CLogServViewBase(aDatabase, aBackupInterface, aPackage, ELogViewTypeRecent, aViewId, aMessage)
+ {
+ }
+
+CLogServViewRecent* CLogServViewRecent::NewL(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
+ {
+ CLogServViewRecent* self = new(ELeave) CLogServViewRecent(aDatabase, aBackupInterface, aPackage, aViewId, aMessage);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Setup the view
+Fetch the client-side SQL query string which this view uses to obtain a data-set.
+*/
+TPtrC CLogServViewRecent::GetQueryStringL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
+ {
+ // Read stuff from the client
+ iPackage.ResizeL(aMessage.GetDesLengthL(2));
+ aMessage.ReadL(2, iPackage.Ptr());
+
+ // Decode the parameters we've read from the client
+ CLogFilterList* filter = new(ELeave)CLogFilterList;
+ CleanupStack::PushL(TCleanupItem(DestroyList, filter));
+ iPackage.GetLogFilterListL(*filter);
+ RLogDynBuf expr;
+ TLogFilterExprBuilder exprBuilder(iDatabase);
+ exprBuilder.BuildExprLC(expr, *filter, KLogAnd, aFilterType);
+ iRecentList = static_cast<TLogRecentList>(aMessage.Int3());
+ // Generate the view that will be used
+ if (iRecentList == KLogNullRecentList)
+ {
+ TheSql.Format(KLogSqlAllRecentViewString, &KLogViewSelectColList, &expr.DesC());
+ }
+ else
+ {
+ TheSql.Format(KLogSqlRecentViewString, &KLogViewSelectColList, iRecentList, &expr.DesC());
+ }
+ CleanupStack::PopAndDestroy(2, filter);
+ return TheSql;
+ }
+
+/**
+Remove an entry from the view.
+Note the client can call this even if the view isn't valid.
+*/
+void CLogServViewRecent::RemoveL(const RMessage2& aMessage)
+ {
+ if(! aMessage.HasCapability(ECapabilityWriteDeviceData))
+ User::Leave(KErrPermissionDenied);
+
+ const TLogId id = static_cast<TLogId>(aMessage.Int2());
+ TBuf<20> num;
+ num.AppendNum(id);
+
+ iDatabase.DTIBeginWithRollBackProtectionLC();
+
+ TheSql.Copy(KLogSqlRemoveDuplicateEvents);
+ TheSql.Append(KIdEqStr);
+ TheSql.Append(num);
+ TheSql.Append(KLogOr);
+ TheSql.Append(KDuplicateEqStr);
+ TheSql.Append(num);
+ User::LeaveIfError(iDatabase.DTIExecuteSql(TheSql));
+
+ // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
+ iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
+ iDatabase.DTICommitAndCancelRollbackProtectionL();
+ }
+
+/**
+Clear all duplicate events associated with this recent list.
+*/
+void CLogServViewRecent::ClearDuplicatesL(const RMessage2& aMessage)
+ {
+ if(! aMessage.HasCapability(ECapabilityWriteDeviceData))
+ User::Leave(KErrPermissionDenied);
+
+ if (iRecentList > 0)
+ {
+ // Get list of duplicates
+ TheSql.Format(KLogSqlSelectAllDuplicatesString, iRecentList);
+ RLogDbView view;
+ view.PrepareLC(iDatabase.DTIDatabase(), TheSql);
+ InitializeColumns2L(view);
+ if(view.FirstL())
+ {
+ iDatabase.DTIBeginWithRollBackProtectionLC();
+ // Iterate through the events
+ do
+ {
+ // Get current event id
+ view.GetL();
+ const TLogId id = view.ColInt32(CLogServViewRecent::iIdColNo);
+ // Make the change
+ view.UpdateL();
+ view.SetColNullL(CLogServViewRecent::iRecentColNo);
+ view.SetColNullL(CLogServViewRecent::iDuplicateColNo);
+ view.PutL();
+ // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
+ iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
+ }
+ while(view.NextL());
+ iDatabase.DTICommitAndCancelRollbackProtectionL();
+ }
+ CleanupStack::PopAndDestroy(&view);
+ }
+ else
+ ::PanicClientL(aMessage, ELogInvalidRecentView);
+ }
+
+void CLogServViewRecent::InitializeColumns2L(RDbRowSet& aRowSet)
+ {
+ if(CLogServViewRecent::iIdColNo == 0)
+ {
+ CDbColSet* colset = aRowSet.ColSetL();
+ CLogServViewRecent::iIdColNo = colset->ColNo(KLogFieldIdString);
+ CLogServViewRecent::iRecentColNo = colset->ColNo(KLogFieldEventRecentString);
+ CLogServViewRecent::iDuplicateColNo = colset->ColNo(KLogFieldEventDuplicateString);
+ delete colset;
+ }
+ __ASSERT_DEBUG(CLogServViewRecent::iIdColNo > 0 &&
+ CLogServViewRecent::iRecentColNo > 0 &&
+ CLogServViewRecent::iDuplicateColNo > 0, User::Invariant());
+
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// -----> CLogServViewDuplicate (source)
+/////////////////////////////////////////////////////////////////////////////////////////
+CLogServViewDuplicate::CLogServViewDuplicate(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
+: CLogServViewBase(aDatabase, aBackupInterface, aPackage, ELogViewTypeDuplicate, aViewId, aMessage)
+//
+// Duplicate view
+//
+ {
+ }
+
+CLogServViewDuplicate* CLogServViewDuplicate::NewL(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
+ {
+ CLogServViewDuplicate* self = new(ELeave) CLogServViewDuplicate(aDatabase, aBackupInterface, aPackage, aViewId, aMessage);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Setup the view
+Fetch the client-side SQL query string which this view uses to obtain a data-set.
+*/
+TPtrC CLogServViewDuplicate::GetQueryStringL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
+ {
+ // Read stuff from the client
+ iPackage.ResizeL(aMessage.GetDesLengthL(2));
+ aMessage.ReadL(2, iPackage.Ptr());
+
+ // Decode the parameters we've read from the client
+ CLogFilterList* filter = new(ELeave)CLogFilterList;
+ CleanupStack::PushL(TCleanupItem(DestroyList, filter));
+ iPackage.GetLogFilterListL(*filter);
+ RLogDynBuf expr;
+ TLogFilterExprBuilder exprBuilder(iDatabase);
+ exprBuilder.BuildExprLC(expr, *filter, KLogAnd, aFilterType);
+ iSourceId = (TInt)aMessage.Ptr3();
+ // Generate the view that will be used
+ TheSql.Format(KLogSqlDuplicateViewString2, &KLogViewSelectColList, iSourceId, &expr.DesC());
+ CleanupStack::PopAndDestroy(2, filter);
+ return TheSql;
+ }
+
+/**
+Remove an entry from the view.
+*/
+void CLogServViewDuplicate::RemoveL(const RMessage2& aMessage)
+ {
+ if(! aMessage.HasCapability(ECapabilityWriteDeviceData))
+ User::Leave(KErrPermissionDenied);
+
+ const TLogId id = static_cast<TLogId>(aMessage.Int2());
+
+ iDatabase.DTIBeginWithRollBackProtectionLC();
+
+ // Do the actual work
+ TheSql.Format(KLogSqlRemoveDuplicateString, id, iSourceId);
+ const TInt error = iDatabase.DTIExecuteSql(TheSql);
+ User::LeaveIfError(error);
+ //
+ // This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
+ iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
+ iDatabase.DTICommitAndCancelRollbackProtectionL();
+ }