diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/LogServ/src/LogServViewChangeManager.cpp --- /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 +#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; iAt(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); + }