os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServViewChangeManager.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/loggingservices/eventlogger/LogServ/src/LogServViewChangeManager.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,214 @@
1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "LogServViewChangeManager.h"
1.20 +#include <s32mem.h>
1.21 +#include "logservpanic.h"
1.22 +#include "LogServDatabaseChangeInterface.h"
1.23 +
1.24 +// Constants
1.25 +const TInt KLogServViewChangeDefinitionGranularity = 10;
1.26 +const TInt KLogServViewChangeQueueGranularity = 3;
1.27 +const TInt KLogServViewChangeBufferGranularity = 40;
1.28 +
1.29 +
1.30 +/////////////////////////////////////////////////////////////////////////////////////////
1.31 +// -----> CLogServViewChangeManager (source)
1.32 +/////////////////////////////////////////////////////////////////////////////////////////
1.33 +
1.34 +CLogServViewChangeManager::CLogServViewChangeManager(MLogServDatabaseChangeInterface& aChangeInterface)
1.35 +: iChangeInterface(aChangeInterface), iPendingChanges(KLogServViewChangeQueueGranularity)
1.36 + {
1.37 + }
1.38 +
1.39 +CLogServViewChangeManager::~CLogServViewChangeManager()
1.40 + {
1.41 + delete iTransientChangeDefinition;
1.42 + //
1.43 + iPendingChanges.ResetAndDestroy();
1.44 + iPendingChanges.Close();
1.45 + }
1.46 +
1.47 +void CLogServViewChangeManager::ConstructL()
1.48 + {
1.49 + iTransientChangeDefinition = CLogChangeDefinition::NewL(KLogServViewChangeDefinitionGranularity);
1.50 + }
1.51 +
1.52 +CLogServViewChangeManager* CLogServViewChangeManager::NewL(MLogServDatabaseChangeInterface& aChangeInterface)
1.53 + {
1.54 + CLogServViewChangeManager* self = new(ELeave) CLogServViewChangeManager(aChangeInterface);
1.55 + CleanupStack::PushL(self);
1.56 + self->ConstructL();
1.57 + CleanupStack::Pop(self);
1.58 + return self;
1.59 + }
1.60 +
1.61 +/////////////////////////////////////////////////////////////////////////////////////////
1.62 +/////////////////////////////////////////////////////////////////////////////////////////
1.63 +/////////////////////////////////////////////////////////////////////////////////////////
1.64 +
1.65 +void CLogServViewChangeManager::ChangeTransactionPrepare()
1.66 + {
1.67 + iTransientChangeDefinition->Reset();
1.68 + }
1.69 +
1.70 +void CLogServViewChangeManager::ChangeTransactionSubmitL(TLogId aId, TLogDatabaseChangeType aType, TInt aViewIndex)
1.71 + {
1.72 + iTransientChangeDefinition->AddL(aId, aType, aViewIndex);
1.73 + }
1.74 +
1.75 +void CLogServViewChangeManager::ChangeTransactionCommitL()
1.76 + {
1.77 + // We can only tell the client-side view change observer about the changes if:
1.78 + //
1.79 + // (2) we actually have something to tell the client views (some changes)
1.80 + // (3) we have an outstanding client-side change message pointer
1.81 + //
1.82 + const TInt count = iTransientChangeDefinition->Count();
1.83 + if (count > 0) // (2)
1.84 + {
1.85 + // Do we have any existing pending changes? We can't alter the contents of the
1.86 + // first pending change, since the client may already be preparing a client-side
1.87 + // buffer of the requisite size. We can, however, combine the 2nd batch of changes
1.88 + // with this new set so there is less IPC required (although more memory).
1.89 + const TInt pendingChangeCount = iPendingChanges.Count();
1.90 + if (pendingChangeCount >= 2)
1.91 + {
1.92 + CLogChangeDefinition* changeDef = CLogChangeDefinition::NewL();
1.93 + CleanupStack::PushL(changeDef);
1.94 + //
1.95 + CBufBase* buffer = iPendingChanges[1];
1.96 + RBufReadStream readStream(*buffer);
1.97 + //
1.98 + readStream >> *changeDef;
1.99 +
1.100 + // Add new changes
1.101 + TLogId logId = KLogNullId;
1.102 + TLogDatabaseChangeType type = ELogChangeTypeUndefined;
1.103 + TInt viewIndex = 0;
1.104 + //
1.105 + for(TInt i=0; i<count; i++)
1.106 + {
1.107 + type = iTransientChangeDefinition->At(i, logId, viewIndex);
1.108 + changeDef->AddL(logId, type, viewIndex);
1.109 + }
1.110 +
1.111 + // Write the whole lot out again
1.112 + buffer->Delete(0, buffer->Size());
1.113 +
1.114 + RBufWriteStream writeStream(*buffer);
1.115 + writeStream << *changeDef;
1.116 + buffer->Compress();
1.117 + CleanupStack::PopAndDestroy(changeDef);
1.118 + }
1.119 + else
1.120 + {
1.121 + CBufBase* buffer = CBufFlat::NewL(KLogServViewChangeBufferGranularity);
1.122 + CleanupStack::PushL(buffer);
1.123 +
1.124 + // Externalize changes
1.125 + RBufWriteStream stream(*buffer);
1.126 + stream << *iTransientChangeDefinition;
1.127 + buffer->Compress();
1.128 +
1.129 + // Add to container
1.130 + User::LeaveIfError(iPendingChanges.Append(buffer));
1.131 + CleanupStack::Pop(buffer);
1.132 + }
1.133 +
1.134 + // Notify if necessary - handles (3) implicitly
1.135 + NotifyClient();
1.136 + }
1.137 +
1.138 + // Free some memory
1.139 + iTransientChangeDefinition->Reset();
1.140 + }
1.141 +
1.142 +/////////////////////////////////////////////////////////////////////////////////////////
1.143 +/////////////////////////////////////////////////////////////////////////////////////////
1.144 +/////////////////////////////////////////////////////////////////////////////////////////
1.145 +
1.146 +void CLogServViewChangeManager::DeliverChangesL(const RMessage2& aMessage)
1.147 + {
1.148 + if (iPendingChanges.Count())
1.149 + {
1.150 + CBufBase* headItem = iPendingChanges[0];
1.151 + //
1.152 + const TInt expectedChangesSize = aMessage.Int1();
1.153 + const TPtr8 pBufferContents(headItem->Ptr(0));
1.154 +
1.155 + // Check buffer size is as we expect
1.156 + if (expectedChangesSize != pBufferContents.Size())
1.157 + ::PanicClientL(aMessage, ELogViewBadClientSideChangeBufferSize);
1.158 + else
1.159 + {
1.160 + // Write back to client-side
1.161 + aMessage.WriteL(2, pBufferContents);
1.162 +
1.163 + // Remove the item
1.164 + iPendingChanges.Remove(0);
1.165 + delete headItem;
1.166 + }
1.167 + }
1.168 + else
1.169 + ::PanicClientL(aMessage, ELogViewNoPendingChangesToDeliver);
1.170 + }
1.171 +
1.172 +/////////////////////////////////////////////////////////////////////////////////////////
1.173 +/////////////////////////////////////////////////////////////////////////////////////////
1.174 +/////////////////////////////////////////////////////////////////////////////////////////
1.175 +
1.176 +void CLogServViewChangeManager::RequestChangeNotifications(const RMessage2& aMessage)
1.177 + {
1.178 + if (iClientSideChangeMessage == RMessagePtr2())
1.179 + {
1.180 + // Notify if we have any cached changes...
1.181 + iClientSideChangeMessage = aMessage;
1.182 + NotifyClient();
1.183 + }
1.184 + else
1.185 + PanicClient(aMessage, ELogViewChangeRequestAlreadyIssued);
1.186 + }
1.187 +
1.188 +void CLogServViewChangeManager::RequestChangeNotificationsCancel()
1.189 + {
1.190 + if (iClientSideChangeMessage != RMessagePtr2())
1.191 + CompleteClientChangeMessage(KErrCancel);
1.192 +
1.193 + // Zap all the pending changes too
1.194 + iPendingChanges.ResetAndDestroy();
1.195 + iPendingChanges.GranularCompress();
1.196 + }
1.197 +
1.198 +/////////////////////////////////////////////////////////////////////////////////////////
1.199 +/////////////////////////////////////////////////////////////////////////////////////////
1.200 +/////////////////////////////////////////////////////////////////////////////////////////
1.201 +
1.202 +void CLogServViewChangeManager::NotifyClient()
1.203 + {
1.204 + const TInt count = iPendingChanges.Count();
1.205 + if (iClientSideChangeMessage != RMessagePtr2() && count)
1.206 + {
1.207 + CBufBase* headItem = iPendingChanges[0];
1.208 + const TInt messageSize = headItem->Size();
1.209 + CompleteClientChangeMessage(messageSize);
1.210 + }
1.211 + }
1.212 +
1.213 +void CLogServViewChangeManager::CompleteClientChangeMessage(TInt aCompletionCode)
1.214 + {
1.215 + __ASSERT_ALWAYS(iClientSideChangeMessage != RMessagePtr2(), Panic(ELogViewNoClientChangeMessageOutstanding));
1.216 + iClientSideChangeMessage.Complete(aCompletionCode);
1.217 + }