loggingservices/eventlogger/LogServ/src/LogServViewChangeManager.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 
       
    16 #include "LogServViewChangeManager.h"
       
    17 #include <s32mem.h>
       
    18 #include "logservpanic.h"
       
    19 #include "LogServDatabaseChangeInterface.h"
       
    20 
       
    21 // Constants
       
    22 const TInt KLogServViewChangeDefinitionGranularity = 10;
       
    23 const TInt KLogServViewChangeQueueGranularity = 3;
       
    24 const TInt KLogServViewChangeBufferGranularity = 40;
       
    25 
       
    26 
       
    27 /////////////////////////////////////////////////////////////////////////////////////////
       
    28 // -----> CLogServViewChangeManager (source)
       
    29 /////////////////////////////////////////////////////////////////////////////////////////
       
    30 
       
    31 CLogServViewChangeManager::CLogServViewChangeManager(MLogServDatabaseChangeInterface& aChangeInterface)
       
    32 :	iChangeInterface(aChangeInterface), iPendingChanges(KLogServViewChangeQueueGranularity)
       
    33 	{
       
    34 	}
       
    35 
       
    36 CLogServViewChangeManager::~CLogServViewChangeManager()
       
    37 	{
       
    38 	delete iTransientChangeDefinition;
       
    39 	//
       
    40 	iPendingChanges.ResetAndDestroy();
       
    41 	iPendingChanges.Close();
       
    42 	}
       
    43 
       
    44 void CLogServViewChangeManager::ConstructL()
       
    45 	{
       
    46 	iTransientChangeDefinition = CLogChangeDefinition::NewL(KLogServViewChangeDefinitionGranularity);
       
    47 	}
       
    48 
       
    49 CLogServViewChangeManager* CLogServViewChangeManager::NewL(MLogServDatabaseChangeInterface& aChangeInterface)
       
    50 	{
       
    51 	CLogServViewChangeManager* self = new(ELeave) CLogServViewChangeManager(aChangeInterface);
       
    52 	CleanupStack::PushL(self);
       
    53 	self->ConstructL();
       
    54 	CleanupStack::Pop(self);
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 /////////////////////////////////////////////////////////////////////////////////////////
       
    59 /////////////////////////////////////////////////////////////////////////////////////////
       
    60 /////////////////////////////////////////////////////////////////////////////////////////
       
    61 
       
    62 void CLogServViewChangeManager::ChangeTransactionPrepare()
       
    63 	{
       
    64 	iTransientChangeDefinition->Reset();
       
    65 	}
       
    66 
       
    67 void CLogServViewChangeManager::ChangeTransactionSubmitL(TLogId aId, TLogDatabaseChangeType aType, TInt aViewIndex)
       
    68 	{
       
    69 	iTransientChangeDefinition->AddL(aId, aType, aViewIndex);
       
    70 	}
       
    71 
       
    72 void CLogServViewChangeManager::ChangeTransactionCommitL()
       
    73 	{
       
    74 	// We can only tell the client-side view change observer about the changes if:
       
    75 	//
       
    76 	// (2) we actually have something to tell the client views (some changes)
       
    77 	// (3) we have an outstanding client-side change message pointer
       
    78 	//
       
    79 	const TInt count = iTransientChangeDefinition->Count();
       
    80 	if	(count > 0) // (2)
       
    81 		{
       
    82 		// Do we have any existing pending changes? We can't alter the contents of the
       
    83 		// first pending change, since the client may already be preparing a client-side
       
    84 		// buffer of the requisite size. We can, however, combine the 2nd batch of changes
       
    85 		// with this new set so there is less IPC required (although more memory).
       
    86 		const TInt pendingChangeCount = iPendingChanges.Count();
       
    87 		if	(pendingChangeCount >= 2)
       
    88 			{
       
    89 			CLogChangeDefinition* changeDef = CLogChangeDefinition::NewL();
       
    90 			CleanupStack::PushL(changeDef);
       
    91 			//
       
    92 			CBufBase* buffer = iPendingChanges[1];
       
    93 			RBufReadStream readStream(*buffer);
       
    94 			//
       
    95 			readStream >> *changeDef;
       
    96 			
       
    97 			// Add new changes
       
    98 			TLogId logId = KLogNullId;
       
    99 			TLogDatabaseChangeType type = ELogChangeTypeUndefined;
       
   100 			TInt viewIndex = 0;
       
   101 			//
       
   102 			for(TInt i=0; i<count; i++)
       
   103 				{
       
   104 				type = iTransientChangeDefinition->At(i, logId, viewIndex);
       
   105 				changeDef->AddL(logId, type, viewIndex);
       
   106 				}
       
   107 
       
   108 			// Write the whole lot out again
       
   109 			buffer->Delete(0, buffer->Size());
       
   110 
       
   111 			RBufWriteStream writeStream(*buffer);
       
   112 			writeStream << *changeDef;
       
   113 			buffer->Compress();
       
   114 			CleanupStack::PopAndDestroy(changeDef);
       
   115 			}
       
   116 		else
       
   117 			{
       
   118 			CBufBase* buffer = CBufFlat::NewL(KLogServViewChangeBufferGranularity);
       
   119 			CleanupStack::PushL(buffer);
       
   120 
       
   121 			// Externalize changes
       
   122 			RBufWriteStream stream(*buffer);
       
   123 			stream << *iTransientChangeDefinition; 
       
   124 			buffer->Compress();
       
   125 
       
   126 			// Add to container
       
   127 			User::LeaveIfError(iPendingChanges.Append(buffer));
       
   128 			CleanupStack::Pop(buffer);
       
   129 			}
       
   130 
       
   131 		// Notify if necessary - handles (3) implicitly
       
   132 		NotifyClient();
       
   133 		}
       
   134 
       
   135 	// Free some memory
       
   136 	iTransientChangeDefinition->Reset();
       
   137 	}
       
   138 
       
   139 /////////////////////////////////////////////////////////////////////////////////////////
       
   140 /////////////////////////////////////////////////////////////////////////////////////////
       
   141 /////////////////////////////////////////////////////////////////////////////////////////
       
   142 
       
   143 void CLogServViewChangeManager::DeliverChangesL(const RMessage2& aMessage)
       
   144 	{
       
   145 	if	(iPendingChanges.Count())
       
   146 		{
       
   147 		CBufBase* headItem = iPendingChanges[0];
       
   148 		//
       
   149 		const TInt expectedChangesSize = aMessage.Int1();
       
   150 		const TPtr8 pBufferContents(headItem->Ptr(0));
       
   151 
       
   152 		// Check buffer size is as we expect
       
   153 		if	(expectedChangesSize != pBufferContents.Size())
       
   154 			::PanicClientL(aMessage, ELogViewBadClientSideChangeBufferSize);
       
   155 		else
       
   156 			{
       
   157 			// Write back to client-side
       
   158 			aMessage.WriteL(2, pBufferContents);
       
   159 
       
   160 			// Remove the item
       
   161 			iPendingChanges.Remove(0);
       
   162 			delete headItem;
       
   163 			}
       
   164 		}
       
   165 	else
       
   166 		::PanicClientL(aMessage, ELogViewNoPendingChangesToDeliver);
       
   167 	}
       
   168 
       
   169 /////////////////////////////////////////////////////////////////////////////////////////
       
   170 /////////////////////////////////////////////////////////////////////////////////////////
       
   171 /////////////////////////////////////////////////////////////////////////////////////////
       
   172 
       
   173 void CLogServViewChangeManager::RequestChangeNotifications(const RMessage2& aMessage)
       
   174 	{
       
   175     if	(iClientSideChangeMessage == RMessagePtr2())
       
   176 		{
       
   177 		// Notify if we have any cached changes...
       
   178 		iClientSideChangeMessage = aMessage;
       
   179 		NotifyClient();
       
   180 		}
       
   181 	else
       
   182 		PanicClient(aMessage, ELogViewChangeRequestAlreadyIssued);
       
   183 	}
       
   184 
       
   185 void CLogServViewChangeManager::RequestChangeNotificationsCancel()
       
   186 	{
       
   187     if	(iClientSideChangeMessage != RMessagePtr2())
       
   188 		CompleteClientChangeMessage(KErrCancel);
       
   189 
       
   190 	// Zap all the pending changes too
       
   191 	iPendingChanges.ResetAndDestroy();
       
   192 	iPendingChanges.GranularCompress();
       
   193 	}
       
   194 
       
   195 /////////////////////////////////////////////////////////////////////////////////////////
       
   196 /////////////////////////////////////////////////////////////////////////////////////////
       
   197 /////////////////////////////////////////////////////////////////////////////////////////
       
   198 
       
   199 void CLogServViewChangeManager::NotifyClient()
       
   200 	{
       
   201 	const TInt count = iPendingChanges.Count();
       
   202     if	(iClientSideChangeMessage != RMessagePtr2() && count)
       
   203 		{
       
   204 		CBufBase* headItem = iPendingChanges[0];
       
   205 		const TInt messageSize = headItem->Size();
       
   206 		CompleteClientChangeMessage(messageSize);
       
   207 		}
       
   208 	}
       
   209 
       
   210 void CLogServViewChangeManager::CompleteClientChangeMessage(TInt aCompletionCode)
       
   211 	{
       
   212 	__ASSERT_ALWAYS(iClientSideChangeMessage != RMessagePtr2(), Panic(ELogViewNoClientChangeMessageOutstanding));
       
   213 	iClientSideChangeMessage.Complete(aCompletionCode);
       
   214 	}