loggingservices/eventlogger/LogServ/src/LogServView.cpp
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 #include "LogServView.h"
       
    16 #include "logpackage.h"
       
    17 #include "logservpanic.h"
       
    18 #include "LogServBackupInterface.h"
       
    19 #include "LogServViewChangeManager.h"
       
    20 #include "LogServDatabaseChangeInterface.h"
       
    21 #include "LogServCacheTypes.h"
       
    22 #include "LogServSqlStrings.h"
       
    23 #include "LOGFILTQ.H"
       
    24 
       
    25 // Constants
       
    26 const TInt KLogViewContentsGranuality = 20;
       
    27 const TInt KLogViewLockStatusEventGranularity = 3;
       
    28 
       
    29 TDbColNo CLogServViewBase::iIdColNo = 0;
       
    30 TDbColNo CLogServViewBase::iTypeColNo = 0;
       
    31 TDbColNo CLogServViewBase::iFlagColNo[] = {0, 0, 0, 0};
       
    32 
       
    33 TDbColNo CLogServViewRecent::iIdColNo = 0;
       
    34 TDbColNo CLogServViewRecent::iRecentColNo = 0;
       
    35 TDbColNo CLogServViewRecent::iDuplicateColNo = 0;
       
    36 
       
    37 //diagnostic message for the platform security
       
    38 const char* KIgnoreDiagnostic = "This diagnostic message does not indicate an error, please ignore it";
       
    39 
       
    40 /////////////////////////////////////////////////////////////////////////////////////////
       
    41 // -----> CLogServViewBase (source)
       
    42 /////////////////////////////////////////////////////////////////////////////////////////
       
    43 CLogServViewBase::CLogServViewBase(MLogServDatabaseTransactionInterface& aDatabase, 
       
    44                                    MLogServBackupInterface& aBackupInterface, 
       
    45                                    CLogPackage& aPackage, TLogViewType aType, TLogViewId aViewId, 
       
    46                                    const RMessage2& aMessage) :
       
    47     iDatabase(aDatabase), 
       
    48     iPackage(aPackage),
       
    49     iBackupInterface(aBackupInterface), 
       
    50     iType(aType), 
       
    51     iViewId(aViewId), 
       
    52     iMessage (aMessage)
       
    53 	{
       
    54 	}
       
    55 
       
    56 CLogServViewBase::~CLogServViewBase()
       
    57 	{
       
    58 	iDatabase.DTIChangeInterface().DCIRequestChangeNotificationsCancel(*this);
       
    59 	iBackupInterface.BIObserverRemove(*this);
       
    60 	//
       
    61 	iViewContents.Close();
       
    62 	//	
       
    63 	iStandardTypeSecurityCache.Close();
       
    64 	//
       
    65 	delete iLockChangeObserver;
       
    66 	delete iSql;
       
    67 	delete iChangeManager;
       
    68 	}
       
    69 
       
    70 
       
    71 void CLogServViewBase::ConstructL()
       
    72 	{
       
    73 	// Handles changes for this view
       
    74 	iChangeManager = CLogServViewChangeManager::NewL(iDatabase.DTIChangeInterface());
       
    75 
       
    76 	// Register for change events
       
    77 	iDatabase.DTIChangeInterface().DCIRequestChangeNotificationsL(*this);
       
    78 
       
    79 	// Register for backup events
       
    80 	iBackupInterface.BIObserverAddL(*this, MLogServBackupInterface::EObjectView);
       
    81 
       
    82 	// Observes when the view is locked/unlocked due to a backup
       
    83 	iLockChangeObserver = CLogServViewLockObserver::NewL(iBackupInterface);
       
    84 
       
    85 	const RArray<TUid>& arrTUids = iDatabase.DTIUidsOfStandardTypes();
       
    86 	TInt count = arrTUids.Count();
       
    87 	iStandardTypeSecurityCache.ReserveL(count);
       
    88 	for(TInt i=0; i < count; i++)
       
    89 		{
       
    90 		SStandardTypeSecurity securitySetting;
       
    91 		securitySetting.eventType = arrTUids[i];
       
    92 		securitySetting.readAccess = iDatabase.DTIIsAllowed(EReadOp, iMessage, arrTUids[i], KIgnoreDiagnostic);
       
    93 		securitySetting.writeAccess = iDatabase.DTIIsAllowed(EWriteOp, iMessage, arrTUids[i], KIgnoreDiagnostic);
       
    94 		TInt err = iStandardTypeSecurityCache.Append(securitySetting);	
       
    95         __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
       
    96 		}
       
    97 	}
       
    98 
       
    99 /////////////////////////////////////////////////////////////////////////////////////////
       
   100 /////////////////////////////////////////////////////////////////////////////////////////
       
   101 /////////////////////////////////////////////////////////////////////////////////////////
       
   102 
       
   103 void CLogServViewBase::DCOHandleChangeEventsL(const CLogChangeDefinition& aChanges)
       
   104 	{
       
   105 	// Just return if the view isn't setup
       
   106 	if	(!iSql)
       
   107 		return;
       
   108 
       
   109 	TRAPD(error, DoHandleChangeEventsL(aChanges));
       
   110 	if	(error != KErrNone)
       
   111 		{
       
   112 		iViewContents.Close();
       
   113 	    iViewContentsReady = EFalse;
       
   114 		iRebuildViewContents = ETrue;
       
   115 		}
       
   116 	}
       
   117 
       
   118 /////////////////////////////////////////////////////////////////////////////////////////
       
   119 /////////////////////////////////////////////////////////////////////////////////////////
       
   120 /////////////////////////////////////////////////////////////////////////////////////////
       
   121 
       
   122 void CLogServViewBase::BOHandleEventL(TLogServBackupEvent aEvent)
       
   123 	{
       
   124 	switch(aEvent)
       
   125 		{
       
   126 	case EBackupStarting:
       
   127 		iViewContents.Close();
       
   128 	    iViewContentsReady = EFalse;
       
   129 		break;
       
   130 	case EBackupEnded:
       
   131 		RebuildViewL();
       
   132 		break;
       
   133 		}
       
   134 	}
       
   135 
       
   136 /////////////////////////////////////////////////////////////////////////////////////////
       
   137 /////////////////////////////////////////////////////////////////////////////////////////
       
   138 /////////////////////////////////////////////////////////////////////////////////////////
       
   139 
       
   140 #pragma BullseyeCoverage off
       
   141 
       
   142 /**
       
   143 Remove an entry from the view.
       
   144 By default you can't remove an event from a view.
       
   145 */
       
   146 void CLogServViewBase::RemoveL(const RMessage2& /*aMessage*/)
       
   147 	{
       
   148 	User::Leave(KErrNotSupported);
       
   149 	}
       
   150 
       
   151 /**
       
   152 By default you can't clear duplicates from a view
       
   153 */
       
   154 void CLogServViewBase::ClearDuplicatesL(const RMessage2& /*aMessage*/)
       
   155 	{
       
   156 	User::Leave(KErrNotSupported);
       
   157 	}
       
   158 
       
   159 #pragma BullseyeCoverage on
       
   160 
       
   161 /**
       
   162 Set the flags of all the entries in the view.
       
   163 */
       
   164 void CLogServViewBase::SetFlagsL(const RMessage2& aMessage)
       
   165 	{
       
   166 	if	(ViewIsReady())
       
   167 		{
       
   168 		// Flags from client
       
   169 		const TLogFlags flags = static_cast<TLogFlags>(aMessage.Int2());
       
   170 		RLogDbView view;
       
   171 		view.PrepareLC(iDatabase.DTIDatabase(), *iSql);
       
   172 		InitializeColumnsL(view);
       
   173 		if(view.FirstL())
       
   174 			{
       
   175             iDatabase.DTIBeginWithRollBackProtectionLC();
       
   176 			// Iterate through the events
       
   177 			do
       
   178 				{
       
   179 				// Get current event id
       
   180 				view.GetL();
       
   181 				const TLogId id = view.ColInt32(CLogServViewBase::iIdColNo);
       
   182 				TUint8 eventTypeIndex = view.ColUint8(CLogServViewBase::iTypeColNo);
       
   183 				if(IsAllowed(EWriteOp, eventTypeIndex))
       
   184 					{
       
   185 					// Make the change
       
   186 					view.UpdateL();
       
   187 		            TInt bit = KLogFlagsCount;
       
   188 		            while(bit--)
       
   189 		                {
       
   190                         const TBool flagIsSet = flags & (0x1 << bit) ? 1 : 0;
       
   191 		                view.SetColL(CLogServViewBase::iFlagColNo[bit], flagIsSet);
       
   192 		                }
       
   193 					view.PutL();
       
   194 					iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChanged, id);
       
   195 					}
       
   196 				}
       
   197 			while(view.NextL());
       
   198 			iDatabase.DTICommitAndCancelRollbackProtectionL();
       
   199 			}
       
   200 		CleanupStack::PopAndDestroy(&view);
       
   201 		}
       
   202 	else
       
   203 		::PanicClientL(aMessage, ELogViewRecentViewNotYetReadyForFlagSetting);
       
   204 	}
       
   205 
       
   206 /////////////////////////////////////////////////////////////////////////////////////////
       
   207 /////////////////////////////////////////////////////////////////////////////////////////
       
   208 /////////////////////////////////////////////////////////////////////////////////////////
       
   209 
       
   210 /**
       
   211 The client has requested change notifications
       
   212 */
       
   213 void CLogServViewBase::RequestChangeNotifications(const RMessage2& aMessage)
       
   214 	{
       
   215 	iChangeManager->RequestChangeNotifications(aMessage);
       
   216 	}
       
   217 
       
   218 /**
       
   219 The client has cancelled a previous change notification request
       
   220 */
       
   221 void CLogServViewBase::RequestChangeNotificationsCancel()
       
   222 	{
       
   223 	iChangeManager->RequestChangeNotificationsCancel();
       
   224 	}
       
   225 
       
   226 /**
       
   227 The client has requested lock status change notifications
       
   228 */
       
   229 void CLogServViewBase::RequestLockStatusChanges(const RMessage2& aMessage)
       
   230 	{
       
   231 	iLockChangeObserver->RequestLockStatusChanges(aMessage);
       
   232 	}
       
   233 
       
   234 /**
       
   235 The client has cancelled a previous change notification request
       
   236 */
       
   237 void CLogServViewBase::RequestLockStatusChangesCancel()
       
   238 	{
       
   239 	iLockChangeObserver->RequestLockStatusChangesCancel();
       
   240 	}
       
   241 
       
   242 /**
       
   243 The client has requested the current list of changes
       
   244 */
       
   245 void CLogServViewBase::RequestChangesL(const RMessage2& aMessage)
       
   246 	{
       
   247 	if	(!iSql)
       
   248 		::PanicClientL(aMessage, ELogViewNotSetupForChangesFetch);
       
   249 	else
       
   250 		iChangeManager->DeliverChangesL(aMessage);
       
   251 	}
       
   252 
       
   253 /**
       
   254 Set up the server-side view based upon the client-side filter. This
       
   255 method essentially fetches a client-side filter and then dynamically
       
   256 executes the associated SELECT statement on the database to build up
       
   257 a view. This view is then cached in terms of the entry ids (iViewContents).
       
   258 */
       
   259 void CLogServViewBase::SetupL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
       
   260 	{
       
   261 	// Get the query string
       
   262 	const TPtrC pSQL(GetQueryStringL(aMessage, aFilterType));
       
   263 	HBufC* buf = pSQL.AllocLC();
       
   264 	// Setup the contents
       
   265 	PrepareViewContentsL(pSQL);
       
   266 	// Tidy up
       
   267 	CleanupStack::Pop(buf);
       
   268 	delete iSql;
       
   269 	iSql = buf;
       
   270 	}
       
   271 
       
   272 /**
       
   273 Returns the number of entries in this view
       
   274 */
       
   275 TInt CLogServViewBase::Count() const
       
   276 	{
       
   277 	return const_cast<CLogServViewBase*>(this)->RebuildViewContentsIfNecessary() ? 0 : iViewContents.Count(); 
       
   278 	}
       
   279 
       
   280 /**
       
   281 Get the log id at the specified index
       
   282 */
       
   283 TLogId CLogServViewBase::At(TInt aIndex) const
       
   284 	{
       
   285 	return (TUint)aIndex < iViewContents.Count() ? iViewContents[aIndex] : KLogNullId;   
       
   286 	}
       
   287 
       
   288 /////////////////////////////////////////////////////////////////////////////////////////
       
   289 /////////////////////////////////////////////////////////////////////////////////////////
       
   290 /////////////////////////////////////////////////////////////////////////////////////////
       
   291 
       
   292 void CLogServViewBase::DestroyList(TAny *aPtr)
       
   293 	{
       
   294 	CLogFilterList* filter = reinterpret_cast<CLogFilterList*>(aPtr);
       
   295 	filter->ResetAndDestroy();
       
   296 	delete filter;
       
   297 	}
       
   298 
       
   299 void CLogServViewBase::InitializeColumnsL(RDbRowSet& aRowSet)
       
   300     {
       
   301     if(CLogServViewBase::iIdColNo == 0)
       
   302         {
       
   303         CDbColSet* colset = aRowSet.ColSetL();
       
   304         CLogServViewBase::iIdColNo = colset->ColNo(KLogFieldIdString);
       
   305         CLogServViewBase::iTypeColNo = colset->ColNo(KLogFieldEventTypeString);
       
   306         for(TInt i=0;i<KLogFlagsCount;++i)
       
   307             {
       
   308             TDbColName colname;
       
   309             colname.Format(KLogFieldEventFlagString, i + 1);
       
   310             CLogServViewBase::iFlagColNo[i] = colset->ColNo(colname);
       
   311             __ASSERT_DEBUG(CLogServViewBase::iFlagColNo[i] > 0, User::Invariant());
       
   312             }
       
   313         delete colset;
       
   314         }
       
   315     __ASSERT_DEBUG(CLogServViewBase::iIdColNo > 0 && CLogServViewBase::iTypeColNo > 0, User::Invariant());  
       
   316     }
       
   317 
       
   318 /////////////////////////////////////////////////////////////////////////////////////////
       
   319 /////////////////////////////////////////////////////////////////////////////////////////
       
   320 /////////////////////////////////////////////////////////////////////////////////////////
       
   321 
       
   322 void CLogServViewBase::ResetViewContentsL(RDbRowSet& aRowSet)
       
   323 	{
       
   324 	// Get the view contents
       
   325 	RArray<TLogId> viewContents(KLogViewContentsGranuality);
       
   326 	CleanupClosePushL(viewContents);
       
   327 	viewContents.ReserveL(aRowSet.CountL());
       
   328 	if(aRowSet.FirstL())
       
   329 		{
       
   330 		do
       
   331 			{
       
   332 			// Get the id at the current position
       
   333 			aRowSet.GetL();
       
   334 			const TLogId id = aRowSet.ColInt32(CLogServViewBase::iIdColNo);
       
   335 			TUint8 eventTypeIndex = aRowSet.ColUint8(CLogServViewBase::iTypeColNo);
       
   336 			if(IsAllowed(EReadOp, eventTypeIndex))
       
   337 			    {
       
   338 				TInt err = viewContents.Append(id);
       
   339 		        __ASSERT_ALWAYS(err == KErrNone, Panic(ELogArrayReserved));
       
   340 			    }
       
   341 			}
       
   342 		while(aRowSet.NextL());
       
   343 		}
       
   344 	// Tidy up - don't leave from below here
       
   345     CleanupStack::Pop(&viewContents);
       
   346 	iViewContents.Close();
       
   347 	iViewContents = viewContents;
       
   348     iViewContentsReady = ETrue;
       
   349 	}
       
   350 
       
   351 void CLogServViewBase::PrepareViewContentsL(const TDesC& aSQL)
       
   352 	{
       
   353 	// Generate the view
       
   354     RLogDbView view;
       
   355     view.PrepareLC(iDatabase.DTIDatabase(), aSQL);
       
   356     InitializeColumnsL(view);
       
   357 	// Reset the view
       
   358 	ResetViewContentsL(view);
       
   359 	CleanupStack::PopAndDestroy(&view);
       
   360 	}
       
   361 
       
   362 void CLogServViewBase::RebuildViewL()
       
   363 	{
       
   364 	if	(iSql && iSql->Length())
       
   365 		PrepareViewContentsL(*iSql);
       
   366 	}
       
   367 
       
   368 //
       
   369 //  The last change notification indication was not handled correctly.
       
   370 //  Attempt to re-initialise the view
       
   371 //
       
   372 TInt CLogServViewBase::RebuildViewContentsIfNecessary()
       
   373 	{
       
   374 	TInt error = KErrNone;
       
   375 	//
       
   376 	if	(iRebuildViewContents && iSql && iSql->Length())
       
   377 		{
       
   378 		TRAP(error, 
       
   379 
       
   380 			RebuildViewL();
       
   381 
       
   382 			// The view is okay now
       
   383 			iRebuildViewContents = EFalse;
       
   384 			);
       
   385 		}
       
   386 	return error;
       
   387 	}
       
   388 
       
   389 void CLogServViewBase::DoHandleChangeEventsL(const CLogChangeDefinition& aChanges)
       
   390 	{
       
   391     if(!ViewIsReady())
       
   392         {
       
   393         return;
       
   394         }
       
   395 	
       
   396 	// Generate the view
       
   397     RLogDbView view;
       
   398     view.PrepareLC(iDatabase.DTIDatabase(), *iSql);
       
   399     InitializeColumnsL(view);
       
   400 	_LIT(KLogIdQuery, "Id = %d");
       
   401 	TBuf<15> find;
       
   402 	TInt changeIndex;
       
   403 
       
   404 	// Prepare for a change transaction
       
   405 	iChangeManager->ChangeTransactionPrepare();
       
   406 
       
   407 	const TInt count = aChanges.Count();
       
   408 	for(TInt i=0; i<count; i++)
       
   409 		{
       
   410 		// Fetch the change details
       
   411 		TLogId logId = KLogNullId;
       
   412 		TLogDatabaseChangeType type = aChanges.At(i, logId);
       
   413 
       
   414 		// Mark the insertion position as 'not found'
       
   415 		changeIndex = KErrNotFound;
       
   416 
       
   417 		// Format the find query
       
   418 		find.Format(KLogIdQuery, logId);
       
   419 
       
   420 		// Handle the various change descriptions
       
   421 		switch(type)
       
   422 			{
       
   423 		case ELogChangeTypeEventAdded:
       
   424 			{
       
   425 			__ASSERT_DEBUG(iViewContents.Find(logId) == KErrNotFound, Panic(ELogEventAlreadyInView));
       
   426 
       
   427 			// See if the event is in the view
       
   428 			if(view.FirstL())
       
   429 				{
       
   430 				const TDbQuery dbQuery(find);
       
   431 				changeIndex = view.FindL(RDbRowSet::EForwards, dbQuery);
       
   432 				if	(changeIndex >= 0)
       
   433 					{
       
   434 					view.GetL();
       
   435 					TUint8 eventTypeIndex = view.ColUint8(CLogServViewBase::iTypeColNo);
       
   436 					if (IsAllowed(EReadOp, eventTypeIndex))
       
   437 						User::LeaveIfError(iViewContents.Insert(logId, changeIndex));
       
   438 					
       
   439 					iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventAdded, changeIndex);
       
   440 					}
       
   441 				}
       
   442 			}
       
   443 			break;
       
   444 		case ELogChangeTypeEventChanged:
       
   445 		case ELogChangeTypeEventChangedHidden:
       
   446 			{
       
   447 			// See if the event is in the view
       
   448 			if	(view.FirstL() && (changeIndex = view.FindL(RDbRowSet::EForwards, TDbQuery(find))) >= KErrNone)
       
   449 				{
       
   450 				// If the event was already in the view then it has changed otherwise it's been added
       
   451 				const TInt findIndex = iViewContents.Find(logId);
       
   452 				if	(findIndex >= KErrNone)
       
   453 					{
       
   454 					// If the item that changed also caused its position within the view to be altered
       
   455 					// then we need to simulate a delete, followed by an addition
       
   456 					if	(findIndex != changeIndex)
       
   457 						{
       
   458 						iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventDeleted, findIndex);
       
   459 						iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventAdded, changeIndex);
       
   460 						}
       
   461 					// Only tell the view if the CLogEvent has changed
       
   462 					else if (type != ELogChangeTypeEventChangedHidden)
       
   463 						{
       
   464 						iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventChanged, changeIndex);
       
   465 						}
       
   466 					}
       
   467 				else
       
   468 					{
       
   469 					User::LeaveIfError(iViewContents.Insert(logId, changeIndex));
       
   470 					iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventAdded, changeIndex);
       
   471 
       
   472 					// Update the type to indicate that this change action
       
   473 					// really resulted in an addition
       
   474 					type = ELogChangeTypeEventAdded;
       
   475 					}
       
   476 				}
       
   477 			else
       
   478 				{
       
   479 				changeIndex = iViewContents.Find(logId);
       
   480 
       
   481 				// If it used to be in the view then it's been removed because it's 
       
   482 				// not in there anymore
       
   483 				if	(changeIndex >= KErrNone)
       
   484 					{
       
   485 					iViewContents.Remove(changeIndex);
       
   486 					iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventDeleted, changeIndex);
       
   487 
       
   488 					// Update the type to indicate that this change action
       
   489 					// really resulted in a deletion
       
   490 					type = ELogChangeTypeEventDeleted;
       
   491 					}
       
   492 				}
       
   493 			}
       
   494 			break;
       
   495 		case ELogChangeTypeEventDeleted:
       
   496 			{
       
   497 			changeIndex = iViewContents.Find(logId);
       
   498 
       
   499 			// If it used to be in the view then tell it about the deletion
       
   500 			if	(changeIndex >= KErrNone)
       
   501 				{
       
   502 				iViewContents.Remove(changeIndex);
       
   503 				iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeEventDeleted, changeIndex);
       
   504 				}
       
   505 			}
       
   506 			break;
       
   507 		case ELogChangeTypeLogCleared:
       
   508 			{
       
   509 			RebuildViewL();
       
   510 			iChangeManager->ChangeTransactionSubmitL(logId, ELogChangeTypeLogCleared, 0);
       
   511 			}
       
   512 			break;
       
   513 		default:
       
   514 			__ASSERT_DEBUG(EFalse, Panic(ELogUnrecognizedChangeType));
       
   515 			break;
       
   516 			}
       
   517 		}
       
   518 
       
   519 	CleanupStack::PopAndDestroy(&view);
       
   520 
       
   521 	// Commit the transaction. Will notify client if necessary
       
   522 	iChangeManager->ChangeTransactionCommitL();
       
   523 	}
       
   524 
       
   525 TBool CLogServViewBase::IsAllowed(TEventOp aEventOp, TUint8 aEventTypeIndex)
       
   526 	{
       
   527 	TBool result = ETrue;
       
   528 
       
   529 	const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindById(aEventTypeIndex);
       
   530 	TUid eventTypeUid = entry.iEventType->Uid();
       
   531 	TInt count = iStandardTypeSecurityCache.Count();
       
   532 		
       
   533 	for(TInt i=0;i<count;++i)
       
   534 		{
       
   535 		if (eventTypeUid == iStandardTypeSecurityCache[i].eventType)
       
   536 			{
       
   537 			result = (aEventOp == EWriteOp) ? iStandardTypeSecurityCache[i].writeAccess : iStandardTypeSecurityCache[i].readAccess;
       
   538 			break;
       
   539 			}
       
   540 		}
       
   541 	
       
   542 	return result;
       
   543 	}
       
   544 
       
   545 /////////////////////////////////////////////////////////////////////////////////////////
       
   546 // -----> CLogServViewLockObserver (source)
       
   547 /////////////////////////////////////////////////////////////////////////////////////////
       
   548 
       
   549 CLogServViewLockObserver::CLogServViewLockObserver(MLogServBackupInterface& aBackupInterface)
       
   550 :	iBackupInterface(aBackupInterface), iLockEvents(KLogViewLockStatusEventGranularity)
       
   551 	{
       
   552 	}
       
   553 
       
   554 CLogServViewLockObserver::~CLogServViewLockObserver()
       
   555 	{
       
   556 	iBackupInterface.BIObserverRemove(*this);
       
   557 	iLockEvents.Close();
       
   558 	}
       
   559 
       
   560 void CLogServViewLockObserver::ConstructL()
       
   561 	{
       
   562 	// Register for backup events
       
   563 	iBackupInterface.BIObserverAddL(*this, MLogServBackupInterface::EObjectViewLock);
       
   564 	}
       
   565 
       
   566 CLogServViewLockObserver* CLogServViewLockObserver::NewL(MLogServBackupInterface& aBackupInterface)
       
   567 	{
       
   568 	CLogServViewLockObserver* self = new(ELeave) CLogServViewLockObserver(aBackupInterface);
       
   569 	CleanupStack::PushL(self);
       
   570 	self->ConstructL();
       
   571 	CleanupStack::Pop(self);
       
   572 	return self;
       
   573 	}
       
   574 
       
   575 void CLogServViewLockObserver::BOHandleEventL(TLogServBackupEvent aEvent)
       
   576 	{
       
   577 	// Map event
       
   578 	TLogViewLockStatus status = ELogViewWindowOpen;
       
   579 	if	(aEvent == MLogServBackupObserver::EBackupStarting)
       
   580 		status = ELogViewWindowLocked;
       
   581 
       
   582 	// Cache or complete immediately
       
   583 	if	(!HaveLockStatusChangePointer())
       
   584 		User::LeaveIfError(iLockEvents.Append(status));
       
   585 	else
       
   586 		CompleteLockStatusChangeMessage(status);
       
   587 	}
       
   588 
       
   589 /**
       
   590 The client has requested lock status change notifications
       
   591 */
       
   592 void CLogServViewLockObserver::RequestLockStatusChanges(const RMessage2& aMessage)
       
   593 	{
       
   594 	if	(!HaveLockStatusChangePointer())
       
   595 		{
       
   596 		iLockStatusChangeMessage = aMessage;
       
   597 		
       
   598 		// Already have one cached event
       
   599 		if	(iLockEvents.Count())
       
   600 			{
       
   601 			CompleteLockStatusChangeMessage(iLockEvents[0]);
       
   602 			iLockEvents.Remove(0);
       
   603 			}
       
   604 		}
       
   605 	else
       
   606 		PanicClient(aMessage, ELogViewLockStatusChangeRequestAlreadyIssued);
       
   607 	}
       
   608 
       
   609 /**
       
   610 The client has cancelled a previous change notification request
       
   611 */
       
   612 void CLogServViewLockObserver::RequestLockStatusChangesCancel()
       
   613 	{
       
   614 	if	(HaveLockStatusChangePointer())
       
   615 		CompleteLockStatusChangeMessage(KErrCancel);
       
   616 	}
       
   617 
       
   618 void  CLogServViewLockObserver::CompleteLockStatusChangeMessage(TInt aCompletionCode)
       
   619 	{
       
   620 	__ASSERT_ALWAYS(HaveLockStatusChangePointer(), Panic(ELogViewNoLockStatusChangeMessage));
       
   621 	iLockStatusChangeMessage.Complete(aCompletionCode);
       
   622 	}
       
   623 
       
   624 /////////////////////////////////////////////////////////////////////////////////////////
       
   625 // -----> CLogServViewEvent (source)
       
   626 /////////////////////////////////////////////////////////////////////////////////////////
       
   627 CLogServViewEvent::CLogServViewEvent(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
       
   628 :	CLogServViewBase(aDatabase, aBackupInterface, aPackage, ELogViewTypeEvent, aViewId, aMessage)
       
   629 	{
       
   630 	}
       
   631 
       
   632 CLogServViewEvent* CLogServViewEvent::NewL(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
       
   633 	{
       
   634 	CLogServViewEvent* self = new(ELeave) CLogServViewEvent(aDatabase, aBackupInterface, aPackage, aViewId, aMessage);
       
   635 	CleanupStack::PushL(self);
       
   636 	self->ConstructL();
       
   637 	CleanupStack::Pop(self);
       
   638 	return self;
       
   639 	}
       
   640 
       
   641 /**
       
   642 Setup the view
       
   643 Fetch the client-side SQL query string which this view uses to obtain a data-set.
       
   644 */
       
   645 TPtrC CLogServViewEvent::GetQueryStringL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType) 
       
   646 	{
       
   647 	// Read stuff from the client
       
   648 	iPackage.ResizeL(aMessage.GetDesLengthL(2));
       
   649 	aMessage.ReadL(2, iPackage.Ptr());
       
   650 
       
   651 	// Decode the parameters we've read from the client
       
   652 	CLogFilterList* filter = new(ELeave)CLogFilterList;
       
   653 	CleanupStack::PushL(TCleanupItem(DestroyList, filter));
       
   654 	iPackage.GetLogFilterListL(*filter);
       
   655 	RLogDynBuf expr;
       
   656     TLogFilterExprBuilder exprBuilder(iDatabase);
       
   657     exprBuilder.BuildExprLC(expr, *filter, KLogWhere, aFilterType);
       
   658     // Generate the query string that will be used
       
   659     TheSql.Format(KLogSqlEventViewString, &KLogViewSelectColList, &expr.DesC());
       
   660     CleanupStack::PopAndDestroy(2, filter);
       
   661 	return TheSql;
       
   662 	}
       
   663 
       
   664 /////////////////////////////////////////////////////////////////////////////////////////
       
   665 // -----> CLogServViewRecent (source)
       
   666 /////////////////////////////////////////////////////////////////////////////////////////
       
   667 CLogServViewRecent::CLogServViewRecent(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
       
   668 :	CLogServViewBase(aDatabase, aBackupInterface, aPackage, ELogViewTypeRecent, aViewId, aMessage)
       
   669 	{
       
   670 	}
       
   671 
       
   672 CLogServViewRecent* CLogServViewRecent::NewL(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
       
   673 	{
       
   674 	CLogServViewRecent* self = new(ELeave) CLogServViewRecent(aDatabase, aBackupInterface, aPackage, aViewId, aMessage);
       
   675 	CleanupStack::PushL(self);
       
   676 	self->ConstructL();
       
   677 	CleanupStack::Pop(self);
       
   678 	return self;
       
   679 	}
       
   680 
       
   681 /**
       
   682 Setup the view
       
   683 Fetch the client-side SQL query string which this view uses to obtain a data-set.
       
   684 */
       
   685 TPtrC CLogServViewRecent::GetQueryStringL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
       
   686 	{
       
   687 	// Read stuff from the client
       
   688 	iPackage.ResizeL(aMessage.GetDesLengthL(2));
       
   689 	aMessage.ReadL(2, iPackage.Ptr());
       
   690 
       
   691 	// Decode the parameters we've read from the client
       
   692 	CLogFilterList* filter = new(ELeave)CLogFilterList;
       
   693 	CleanupStack::PushL(TCleanupItem(DestroyList, filter));
       
   694 	iPackage.GetLogFilterListL(*filter);
       
   695 	RLogDynBuf expr;
       
   696 	TLogFilterExprBuilder exprBuilder(iDatabase);
       
   697 	exprBuilder.BuildExprLC(expr, *filter, KLogAnd, aFilterType);
       
   698     iRecentList = static_cast<TLogRecentList>(aMessage.Int3());
       
   699     // Generate the view that will be used
       
   700     if (iRecentList == KLogNullRecentList)
       
   701         {
       
   702         TheSql.Format(KLogSqlAllRecentViewString, &KLogViewSelectColList, &expr.DesC());
       
   703         }
       
   704     else
       
   705         {
       
   706         TheSql.Format(KLogSqlRecentViewString, &KLogViewSelectColList, iRecentList, &expr.DesC());
       
   707         }
       
   708     CleanupStack::PopAndDestroy(2, filter);
       
   709 	return TheSql;
       
   710 	}
       
   711 
       
   712 /**
       
   713 Remove an entry from the view.
       
   714 Note the client can call this even if the view isn't valid.
       
   715 */
       
   716 void CLogServViewRecent::RemoveL(const RMessage2& aMessage)
       
   717 	{
       
   718 	if(! aMessage.HasCapability(ECapabilityWriteDeviceData))
       
   719 		User::Leave(KErrPermissionDenied);
       
   720 		
       
   721 	const TLogId id = static_cast<TLogId>(aMessage.Int2());
       
   722     TBuf<20> num;
       
   723     num.AppendNum(id);
       
   724 
       
   725 	iDatabase.DTIBeginWithRollBackProtectionLC();
       
   726 	
       
   727     TheSql.Copy(KLogSqlRemoveDuplicateEvents);
       
   728     TheSql.Append(KIdEqStr);
       
   729     TheSql.Append(num);
       
   730     TheSql.Append(KLogOr);
       
   731     TheSql.Append(KDuplicateEqStr);
       
   732     TheSql.Append(num);
       
   733     User::LeaveIfError(iDatabase.DTIExecuteSql(TheSql));
       
   734 
       
   735 	// This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
       
   736 	iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
       
   737 	iDatabase.DTICommitAndCancelRollbackProtectionL();
       
   738 	}
       
   739 
       
   740 /**
       
   741 Clear all duplicate events associated with this recent list.
       
   742 */
       
   743 void CLogServViewRecent::ClearDuplicatesL(const RMessage2& aMessage)
       
   744 	{
       
   745 	if(! aMessage.HasCapability(ECapabilityWriteDeviceData))
       
   746 		User::Leave(KErrPermissionDenied);
       
   747 	
       
   748 	if	(iRecentList > 0)
       
   749 		{
       
   750 		// Get list of duplicates
       
   751 		TheSql.Format(KLogSqlSelectAllDuplicatesString, iRecentList);
       
   752         RLogDbView view;
       
   753         view.PrepareLC(iDatabase.DTIDatabase(), TheSql);
       
   754         InitializeColumns2L(view);
       
   755 		if(view.FirstL())
       
   756 			{
       
   757             iDatabase.DTIBeginWithRollBackProtectionLC();
       
   758 			// Iterate through the events
       
   759 			do
       
   760 				{
       
   761 				// Get current event id
       
   762 				view.GetL();
       
   763 				const TLogId id = view.ColInt32(CLogServViewRecent::iIdColNo);
       
   764 				// Make the change
       
   765 				view.UpdateL();
       
   766 				view.SetColNullL(CLogServViewRecent::iRecentColNo);
       
   767 				view.SetColNullL(CLogServViewRecent::iDuplicateColNo);
       
   768 				view.PutL();
       
   769 				// This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
       
   770 				iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
       
   771 				}
       
   772 			while(view.NextL());
       
   773 			iDatabase.DTICommitAndCancelRollbackProtectionL();
       
   774 			}
       
   775 		CleanupStack::PopAndDestroy(&view);
       
   776 		}
       
   777 	else
       
   778 		::PanicClientL(aMessage, ELogInvalidRecentView);
       
   779 	}
       
   780 
       
   781 void CLogServViewRecent::InitializeColumns2L(RDbRowSet& aRowSet)
       
   782     {
       
   783     if(CLogServViewRecent::iIdColNo == 0)
       
   784         {
       
   785         CDbColSet* colset = aRowSet.ColSetL();
       
   786         CLogServViewRecent::iIdColNo = colset->ColNo(KLogFieldIdString);
       
   787         CLogServViewRecent::iRecentColNo = colset->ColNo(KLogFieldEventRecentString);
       
   788         CLogServViewRecent::iDuplicateColNo = colset->ColNo(KLogFieldEventDuplicateString);
       
   789         delete colset;
       
   790         }
       
   791     __ASSERT_DEBUG(CLogServViewRecent::iIdColNo > 0 && 
       
   792             CLogServViewRecent::iRecentColNo > 0 && 
       
   793             CLogServViewRecent::iDuplicateColNo > 0, User::Invariant());  
       
   794         
       
   795     }
       
   796 
       
   797 /////////////////////////////////////////////////////////////////////////////////////////
       
   798 // -----> CLogServViewDuplicate (source)
       
   799 /////////////////////////////////////////////////////////////////////////////////////////
       
   800 CLogServViewDuplicate::CLogServViewDuplicate(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
       
   801 :	CLogServViewBase(aDatabase, aBackupInterface, aPackage, ELogViewTypeDuplicate, aViewId, aMessage)
       
   802 //
       
   803 //	Duplicate view
       
   804 //
       
   805 	{
       
   806 	}
       
   807 
       
   808 CLogServViewDuplicate* CLogServViewDuplicate::NewL(MLogServDatabaseTransactionInterface& aDatabase, MLogServBackupInterface& aBackupInterface, CLogPackage& aPackage, TLogViewId aViewId, const RMessage2& aMessage)
       
   809 	{
       
   810 	CLogServViewDuplicate* self = new(ELeave) CLogServViewDuplicate(aDatabase, aBackupInterface, aPackage, aViewId, aMessage);
       
   811 	CleanupStack::PushL(self);
       
   812 	self->ConstructL();
       
   813 	CleanupStack::Pop(self);
       
   814 	return self;
       
   815 	}
       
   816 
       
   817 /**
       
   818 Setup the view
       
   819 Fetch the client-side SQL query string which this view uses to obtain a data-set.
       
   820 */
       
   821 TPtrC CLogServViewDuplicate::GetQueryStringL(const RMessage2& aMessage, TLogFilterConstructionType aFilterType)
       
   822 	{
       
   823 	// Read stuff from the client
       
   824 	iPackage.ResizeL(aMessage.GetDesLengthL(2));
       
   825 	aMessage.ReadL(2, iPackage.Ptr());
       
   826 
       
   827 	// Decode the parameters we've read from the client
       
   828 	CLogFilterList* filter = new(ELeave)CLogFilterList;
       
   829 	CleanupStack::PushL(TCleanupItem(DestroyList, filter));
       
   830 	iPackage.GetLogFilterListL(*filter);
       
   831 	RLogDynBuf expr;
       
   832 	TLogFilterExprBuilder exprBuilder(iDatabase);
       
   833 	exprBuilder.BuildExprLC(expr, *filter, KLogAnd, aFilterType);
       
   834 	iSourceId = (TInt)aMessage.Ptr3();
       
   835     // Generate the view that will be used
       
   836     TheSql.Format(KLogSqlDuplicateViewString2, &KLogViewSelectColList, iSourceId, &expr.DesC());
       
   837     CleanupStack::PopAndDestroy(2, filter);
       
   838 	return TheSql;
       
   839 	}
       
   840 
       
   841 /**
       
   842 Remove an entry from the view.
       
   843 */
       
   844 void CLogServViewDuplicate::RemoveL(const RMessage2& aMessage)
       
   845 	{
       
   846 	if(! aMessage.HasCapability(ECapabilityWriteDeviceData))
       
   847 		User::Leave(KErrPermissionDenied);
       
   848 
       
   849 	const TLogId id = static_cast<TLogId>(aMessage.Int2());
       
   850 
       
   851 	iDatabase.DTIBeginWithRollBackProtectionLC();
       
   852 
       
   853 	// Do the actual work
       
   854 	TheSql.Format(KLogSqlRemoveDuplicateString, id, iSourceId);
       
   855 	const TInt error = iDatabase.DTIExecuteSql(TheSql);
       
   856 	User::LeaveIfError(error);
       
   857 	//
       
   858 	// This is a "hidden" change. It may affect the contents of a view, but the actual event hasn't changed
       
   859 	iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventChangedHidden, id);
       
   860 	iDatabase.DTICommitAndCancelRollbackProtectionL();
       
   861 	}