--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/loggingservices/eventlogger/LogServ/src/LogServViewChangeManager.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,214 @@
+// 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 "LogServViewChangeManager.h"
+#include <s32mem.h>
+#include "logservpanic.h"
+#include "LogServDatabaseChangeInterface.h"
+
+// Constants
+const TInt KLogServViewChangeDefinitionGranularity = 10;
+const TInt KLogServViewChangeQueueGranularity = 3;
+const TInt KLogServViewChangeBufferGranularity = 40;
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// -----> CLogServViewChangeManager (source)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CLogServViewChangeManager::CLogServViewChangeManager(MLogServDatabaseChangeInterface& aChangeInterface)
+: iChangeInterface(aChangeInterface), iPendingChanges(KLogServViewChangeQueueGranularity)
+ {
+ }
+
+CLogServViewChangeManager::~CLogServViewChangeManager()
+ {
+ delete iTransientChangeDefinition;
+ //
+ iPendingChanges.ResetAndDestroy();
+ iPendingChanges.Close();
+ }
+
+void CLogServViewChangeManager::ConstructL()
+ {
+ iTransientChangeDefinition = CLogChangeDefinition::NewL(KLogServViewChangeDefinitionGranularity);
+ }
+
+CLogServViewChangeManager* CLogServViewChangeManager::NewL(MLogServDatabaseChangeInterface& aChangeInterface)
+ {
+ CLogServViewChangeManager* self = new(ELeave) CLogServViewChangeManager(aChangeInterface);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewChangeManager::ChangeTransactionPrepare()
+ {
+ iTransientChangeDefinition->Reset();
+ }
+
+void CLogServViewChangeManager::ChangeTransactionSubmitL(TLogId aId, TLogDatabaseChangeType aType, TInt aViewIndex)
+ {
+ iTransientChangeDefinition->AddL(aId, aType, aViewIndex);
+ }
+
+void CLogServViewChangeManager::ChangeTransactionCommitL()
+ {
+ // We can only tell the client-side view change observer about the changes if:
+ //
+ // (2) we actually have something to tell the client views (some changes)
+ // (3) we have an outstanding client-side change message pointer
+ //
+ const TInt count = iTransientChangeDefinition->Count();
+ if (count > 0) // (2)
+ {
+ // Do we have any existing pending changes? We can't alter the contents of the
+ // first pending change, since the client may already be preparing a client-side
+ // buffer of the requisite size. We can, however, combine the 2nd batch of changes
+ // with this new set so there is less IPC required (although more memory).
+ const TInt pendingChangeCount = iPendingChanges.Count();
+ if (pendingChangeCount >= 2)
+ {
+ CLogChangeDefinition* changeDef = CLogChangeDefinition::NewL();
+ CleanupStack::PushL(changeDef);
+ //
+ CBufBase* buffer = iPendingChanges[1];
+ RBufReadStream readStream(*buffer);
+ //
+ readStream >> *changeDef;
+
+ // Add new changes
+ TLogId logId = KLogNullId;
+ TLogDatabaseChangeType type = ELogChangeTypeUndefined;
+ TInt viewIndex = 0;
+ //
+ for(TInt i=0; i<count; i++)
+ {
+ type = iTransientChangeDefinition->At(i, logId, viewIndex);
+ changeDef->AddL(logId, type, viewIndex);
+ }
+
+ // Write the whole lot out again
+ buffer->Delete(0, buffer->Size());
+
+ RBufWriteStream writeStream(*buffer);
+ writeStream << *changeDef;
+ buffer->Compress();
+ CleanupStack::PopAndDestroy(changeDef);
+ }
+ else
+ {
+ CBufBase* buffer = CBufFlat::NewL(KLogServViewChangeBufferGranularity);
+ CleanupStack::PushL(buffer);
+
+ // Externalize changes
+ RBufWriteStream stream(*buffer);
+ stream << *iTransientChangeDefinition;
+ buffer->Compress();
+
+ // Add to container
+ User::LeaveIfError(iPendingChanges.Append(buffer));
+ CleanupStack::Pop(buffer);
+ }
+
+ // Notify if necessary - handles (3) implicitly
+ NotifyClient();
+ }
+
+ // Free some memory
+ iTransientChangeDefinition->Reset();
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewChangeManager::DeliverChangesL(const RMessage2& aMessage)
+ {
+ if (iPendingChanges.Count())
+ {
+ CBufBase* headItem = iPendingChanges[0];
+ //
+ const TInt expectedChangesSize = aMessage.Int1();
+ const TPtr8 pBufferContents(headItem->Ptr(0));
+
+ // Check buffer size is as we expect
+ if (expectedChangesSize != pBufferContents.Size())
+ ::PanicClientL(aMessage, ELogViewBadClientSideChangeBufferSize);
+ else
+ {
+ // Write back to client-side
+ aMessage.WriteL(2, pBufferContents);
+
+ // Remove the item
+ iPendingChanges.Remove(0);
+ delete headItem;
+ }
+ }
+ else
+ ::PanicClientL(aMessage, ELogViewNoPendingChangesToDeliver);
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewChangeManager::RequestChangeNotifications(const RMessage2& aMessage)
+ {
+ if (iClientSideChangeMessage == RMessagePtr2())
+ {
+ // Notify if we have any cached changes...
+ iClientSideChangeMessage = aMessage;
+ NotifyClient();
+ }
+ else
+ PanicClient(aMessage, ELogViewChangeRequestAlreadyIssued);
+ }
+
+void CLogServViewChangeManager::RequestChangeNotificationsCancel()
+ {
+ if (iClientSideChangeMessage != RMessagePtr2())
+ CompleteClientChangeMessage(KErrCancel);
+
+ // Zap all the pending changes too
+ iPendingChanges.ResetAndDestroy();
+ iPendingChanges.GranularCompress();
+ }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogServViewChangeManager::NotifyClient()
+ {
+ const TInt count = iPendingChanges.Count();
+ if (iClientSideChangeMessage != RMessagePtr2() && count)
+ {
+ CBufBase* headItem = iPendingChanges[0];
+ const TInt messageSize = headItem->Size();
+ CompleteClientChangeMessage(messageSize);
+ }
+ }
+
+void CLogServViewChangeManager::CompleteClientChangeMessage(TInt aCompletionCode)
+ {
+ __ASSERT_ALWAYS(iClientSideChangeMessage != RMessagePtr2(), Panic(ELogViewNoClientChangeMessageOutstanding));
+ iClientSideChangeMessage.Complete(aCompletionCode);
+ }