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