|
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 } |