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