|
1 /* |
|
2 * Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Sensor server channel buffer implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "sensrvdefines.h" |
|
20 #include "sensrvchannel.h" |
|
21 #include "sensrvpluginproxy.h" |
|
22 #include "sensrvchannelbuffer.h" |
|
23 #include "sensrvchannellistener.h" |
|
24 |
|
25 |
|
26 // --------------------------------------------------------------------------- |
|
27 // 2-phase constructor |
|
28 // --------------------------------------------------------------------------- |
|
29 // |
|
30 CSensrvChannelBuffer* CSensrvChannelBuffer::NewL(TInt aItemSize, |
|
31 TInt aBufferLength) |
|
32 { |
|
33 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::NewL(aItemSize: %d, aBufferLength: %d)" ), aItemSize, aBufferLength ) ); |
|
34 |
|
35 CSensrvChannelBuffer* self = new( ELeave ) CSensrvChannelBuffer(aItemSize, aBufferLength); |
|
36 |
|
37 CleanupStack::PushL( self ); |
|
38 self->ConstructL(); |
|
39 CleanupStack::Pop( self ); |
|
40 |
|
41 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::NewL - return 0x%x" ), self ) ); |
|
42 |
|
43 return self; |
|
44 } |
|
45 |
|
46 // --------------------------------------------------------------------------- |
|
47 // C++ constructor |
|
48 // --------------------------------------------------------------------------- |
|
49 // |
|
50 CSensrvChannelBuffer::CSensrvChannelBuffer(TInt aItemSize, |
|
51 TInt aBufferLength) |
|
52 : iItemSize(aItemSize), |
|
53 iBufferLength(aBufferLength < KSensrvMinimumBufferLength ? KSensrvMinimumBufferLength : aBufferLength), |
|
54 iLatestWrittenItemIndex( KErrNotFound ) |
|
55 { |
|
56 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CSensrvChannelBuffer()" )) ); |
|
57 |
|
58 // Nothing to do |
|
59 |
|
60 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CSensrvChannelBuffer - return" ) ) ); |
|
61 } |
|
62 |
|
63 // --------------------------------------------------------------------------- |
|
64 // 2nd phase of construction |
|
65 // --------------------------------------------------------------------------- |
|
66 // |
|
67 void CSensrvChannelBuffer::ConstructL() |
|
68 { |
|
69 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::ConstructL()" ) ) ); |
|
70 |
|
71 // Check parameter validity here, as constructor cannot leave. |
|
72 TInt bufferSize = iItemSize*iBufferLength; |
|
73 if ( iItemSize <= 0 |
|
74 || iBufferLength <= 0 |
|
75 || (KMaxTInt/iItemSize) <= iBufferLength ) |
|
76 { |
|
77 ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::ConstructL - ERROR: Invalid parameters" ) ) ); |
|
78 User::Leave(KErrArgument); |
|
79 } |
|
80 |
|
81 // Construct buffer |
|
82 iBuffer = HBufC8::NewL(bufferSize); |
|
83 |
|
84 BUFFER_TRACE( ( _L( "#### CSensrvChannelBuffer::ConstructL(): iBufferLength: %d" ), iBufferLength ) ); |
|
85 |
|
86 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::ConstructL - return" ) ) ); |
|
87 } |
|
88 |
|
89 // --------------------------------------------------------------------------- |
|
90 // Destructor |
|
91 // --------------------------------------------------------------------------- |
|
92 // |
|
93 CSensrvChannelBuffer::~CSensrvChannelBuffer() |
|
94 { |
|
95 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::~CSensrvChannelBuffer()" ) ) ); |
|
96 |
|
97 delete iBuffer; |
|
98 |
|
99 iTailIndexArray.ResetAndDestroy(); |
|
100 |
|
101 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::~CSensrvChannelBuffer - return" ) ) ); |
|
102 } |
|
103 |
|
104 // --------------------------------------------------------------------------- |
|
105 // Get pointer to next free block (the beginning of head index item) |
|
106 // Invalidate next aCount items and move indexes accordingly. |
|
107 // --------------------------------------------------------------------------- |
|
108 // |
|
109 TUint8* CSensrvChannelBuffer::GetFreeBlock(TInt aCount) |
|
110 { |
|
111 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetFreeBlock(aCount: %d)" ), aCount ) ); |
|
112 |
|
113 __ASSERT_ALWAYS(aCount <= iBufferLength, User::Panic(KSensrvPanicCategory, ESensrvPanicOutOfBounds)); |
|
114 __ASSERT_ALWAYS(!iRequestedFreeBlockLength, User::Panic(KSensrvPanicCategory, ESensrvPanicPreviousBlockNotYetWritten)); |
|
115 |
|
116 // Check if there is enough space in the end of the buffer to allocate continuous |
|
117 // block of aCount items |
|
118 if (iHeadIndex + aCount > iBufferLength) |
|
119 { |
|
120 // No room, invalidate the end of buffer and move head to start of buffer. |
|
121 InvalidateRange(iBufferLength); |
|
122 iHeadIndex = 0; |
|
123 } |
|
124 else |
|
125 { |
|
126 // There is room at end of buffer, do nothing |
|
127 } |
|
128 |
|
129 // Invalidate desired range |
|
130 InvalidateRange(aCount); |
|
131 |
|
132 // Get head pointer |
|
133 TUint8* ptr = const_cast<TUint8*>(iBuffer->Ptr()); |
|
134 ptr += iHeadIndex*iItemSize; |
|
135 |
|
136 iRequestedFreeBlockLength = aCount; |
|
137 |
|
138 DEBUG_PRINT_BUFFER; |
|
139 |
|
140 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetFreeBlock - return %d" ), ptr ) ); |
|
141 |
|
142 return ptr; |
|
143 } |
|
144 |
|
145 // --------------------------------------------------------------------------- |
|
146 // Validate specified count of items and adjust indexes. |
|
147 // Head index is moved aCount items forward, as well as iValidEndIndex, |
|
148 // if that is at head. |
|
149 // --------------------------------------------------------------------------- |
|
150 // |
|
151 void CSensrvChannelBuffer::WroteBlock(TInt aCount) |
|
152 { |
|
153 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::WroteBlock(aCount: %d)" ), aCount ) ); |
|
154 |
|
155 __ASSERT_ALWAYS(iRequestedFreeBlockLength >= aCount, User::Panic(KSensrvPanicCategory, ESensrvPanicRequestedFreeBlockTooSmall)); |
|
156 |
|
157 // Negative count indicates an error |
|
158 TInt total(iHeadIndex + aCount); |
|
159 |
|
160 if (aCount < 0 || total > iBufferLength) |
|
161 { |
|
162 ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::WroteBlock - Invalid count: %d, iBufferLength: %d, iHeadIndex: %d" ), aCount, iBufferLength, iHeadIndex ) ); |
|
163 } |
|
164 else if (aCount) |
|
165 { |
|
166 // Store the latest written item index to be used as initial data |
|
167 iLatestWrittenItemIndex = total - 1; |
|
168 |
|
169 iHeadIndex = total; |
|
170 |
|
171 if (iValidEndIndex < iHeadIndex) |
|
172 { |
|
173 iValidEndIndex = iHeadIndex; |
|
174 } |
|
175 |
|
176 if (iHeadIndex == iBufferLength) |
|
177 { |
|
178 iHeadIndex = 0; |
|
179 } |
|
180 |
|
181 for(TInt i = 0; i < iTailIndexArray.Count(); i++) |
|
182 { |
|
183 UpdateDataAvailable(*(iTailIndexArray[i]), ETrue); |
|
184 } |
|
185 } |
|
186 else |
|
187 { |
|
188 // Nothing to do when count is zero |
|
189 } |
|
190 |
|
191 iRequestedFreeBlockLength = 0; |
|
192 |
|
193 DEBUG_PRINT_BUFFER; |
|
194 } |
|
195 |
|
196 // --------------------------------------------------------------------------- |
|
197 // Cancels any outstanding free block request |
|
198 // --------------------------------------------------------------------------- |
|
199 // |
|
200 void CSensrvChannelBuffer::CancelFreeBlock() |
|
201 { |
|
202 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CancelFreeBlock()" ) ) ); |
|
203 |
|
204 iRequestedFreeBlockLength = 0; |
|
205 |
|
206 DEBUG_PRINT_BUFFER; |
|
207 |
|
208 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CancelFreeBlock - return" ) ) ); |
|
209 } |
|
210 |
|
211 // --------------------------------------------------------------------------- |
|
212 // Adds a listener tail index |
|
213 // --------------------------------------------------------------------------- |
|
214 // |
|
215 TInt CSensrvChannelBuffer::AddListener(CSensrvChannelListener* aListener, |
|
216 TSensrvTailIndexItem*& aTailItem, |
|
217 CSensrvChannelListener::TSensrvChannelListenerState aState) |
|
218 { |
|
219 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::AddListener(aListener: 0x%x, <retval>, aState: %d)" ), aListener, aState ) ); |
|
220 |
|
221 __ASSERT_ALWAYS(aListener, User::Panic(KSensrvPanicCategory, ESensrvPanicNullListener)); |
|
222 __ASSERT_ALWAYS(GetTailIndex(aListener) == KErrNotFound, User::Panic(KSensrvPanicCategory, ESensrvPanicDuplicateListener)); |
|
223 |
|
224 aTailItem = new TSensrvTailIndexItem(aListener); |
|
225 |
|
226 TInt err(KErrNoMemory); |
|
227 |
|
228 if (aTailItem) |
|
229 { |
|
230 if (aState == CSensrvChannelListener::EChannelListenerStateDataListening) |
|
231 { |
|
232 // If no outstanding request for data block (i.e. first listener), |
|
233 // initialize index to head index. |
|
234 if (iRequestedFreeBlockLength) |
|
235 { |
|
236 aTailItem->iDataTailIndex = KSensrvChannelBufferUninitializedTail; |
|
237 } |
|
238 else |
|
239 { |
|
240 aTailItem->iDataTailIndex = iHeadIndex; |
|
241 } |
|
242 } |
|
243 else if (aState == CSensrvChannelListener::EChannelListenerStateConditionListening) |
|
244 { |
|
245 // Unlike data, conditions are available immediately, regardless of |
|
246 // current listening state. Each condition set will individually |
|
247 // be evaluated if it should ignore new data. |
|
248 aTailItem->iConditionTailIndex = iHeadIndex; |
|
249 } |
|
250 else |
|
251 { |
|
252 ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::AddListener - ERROR: Invalid state: %d" ), aState ) ); |
|
253 } |
|
254 |
|
255 |
|
256 err = iTailIndexArray.Append(aTailItem); |
|
257 |
|
258 if (err != KErrNone) |
|
259 { |
|
260 delete aTailItem; |
|
261 aTailItem = NULL; |
|
262 } |
|
263 } |
|
264 |
|
265 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::AddListener - return %d, aTailItem: 0x%x" ), err, aTailItem ) ); |
|
266 |
|
267 return err; |
|
268 } |
|
269 |
|
270 // --------------------------------------------------------------------------- |
|
271 // Removes a listener tail index |
|
272 // --------------------------------------------------------------------------- |
|
273 // |
|
274 void CSensrvChannelBuffer::RemoveListener(CSensrvChannelListener* aListener) |
|
275 { |
|
276 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::DeleteListener(aListener: 0x%x)" ), aListener ) ); |
|
277 |
|
278 __ASSERT_ALWAYS(aListener, User::Panic(KSensrvPanicCategory, ESensrvPanicNullListener)); |
|
279 TBool removed(EFalse); |
|
280 |
|
281 for(TInt i = 0; !removed && i < iTailIndexArray.Count(); i++) |
|
282 { |
|
283 if (iTailIndexArray[i]->iListener == aListener) |
|
284 { |
|
285 delete iTailIndexArray[i]; |
|
286 iTailIndexArray.Remove(i); |
|
287 removed = ETrue; |
|
288 } |
|
289 } |
|
290 |
|
291 // Clear requested free block length |
|
292 if( iTailIndexArray.Count() == 0 ) |
|
293 { |
|
294 CancelFreeBlock(); |
|
295 } |
|
296 |
|
297 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::DeleteListener - return (removed: %d)" ), removed ) ); |
|
298 } |
|
299 |
|
300 // --------------------------------------------------------------------------- |
|
301 // Get new data for listener to transaction data item |
|
302 // --------------------------------------------------------------------------- |
|
303 // |
|
304 void CSensrvChannelBuffer::GetMessageData(TSensrvTailIndexItem* aTailItem, |
|
305 CSensrvChannelListener::TChannelDataMessage& aMessageData, |
|
306 TInt aCount) |
|
307 { |
|
308 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetMessageData(aCount: %d)" ), aCount ) ); |
|
309 |
|
310 if( aTailItem == NULL ) |
|
311 return; |
|
312 |
|
313 TBool done(EFalse); |
|
314 TInt actualCount(aCount > aTailItem->iDataAvailable ? aTailItem->iDataAvailable : aCount); |
|
315 |
|
316 // Get tail item pointer |
|
317 TUint8* startPtr = const_cast<TUint8*>(iBuffer->Ptr()); |
|
318 TUint8* tailPtr = startPtr + aTailItem->iDataTailIndex*iItemSize; |
|
319 |
|
320 TPtrC8* activePart = &aMessageData.iFirstDataPart; |
|
321 |
|
322 aMessageData.iDataLostCount = aTailItem->iDataLostCount; |
|
323 |
|
324 while (!done) |
|
325 { |
|
326 TInt available(0); |
|
327 |
|
328 // Adjust tail index |
|
329 if (!aTailItem->iDataAvailable) |
|
330 { |
|
331 // No new data available, do nothing |
|
332 BUFFER_TRACE((_L("#### No more data available"))); |
|
333 done = ETrue; |
|
334 } |
|
335 else if ( aTailItem->iDataTailIndex < iHeadIndex ) |
|
336 { |
|
337 // Data available up to head index |
|
338 available = iHeadIndex - aTailItem->iDataTailIndex; |
|
339 TInt remainder = actualCount - aMessageData.iDataItemCount; |
|
340 if (remainder < available) |
|
341 { |
|
342 available = remainder; |
|
343 } |
|
344 BUFFER_TRACE((_L("#### More data was available"))); |
|
345 done = ETrue; |
|
346 } |
|
347 else // iTailIndexArray[index].iDataTailIndex >= iHeadIndex |
|
348 { |
|
349 // New data available up to iValidEndIndex and possibly more again from start |
|
350 // Only possible to get here on first pass. |
|
351 available = iValidEndIndex - aTailItem->iDataTailIndex; |
|
352 if (actualCount <= available) |
|
353 { |
|
354 available = actualCount; |
|
355 done = ETrue; // No second pass needed |
|
356 BUFFER_TRACE((_L("#### Just single block of data was available"))); |
|
357 } |
|
358 else |
|
359 { |
|
360 BUFFER_TRACE((_L("#### Possibly second block of data available"))); |
|
361 } |
|
362 } |
|
363 |
|
364 aTailItem->iDataTailIndex += available; |
|
365 activePart->Set(tailPtr, available*iItemSize); |
|
366 aMessageData.iDataItemCount += available; |
|
367 |
|
368 // Roll tail index over to zero if at end of buffer, |
|
369 // unless valid buffer ends at head index, in which case |
|
370 // SSY has reserved a block beginning from iValidEndIndex, |
|
371 // and we should wait for new data at current index. |
|
372 if (aTailItem->iDataTailIndex == iValidEndIndex && iValidEndIndex != iHeadIndex) |
|
373 { |
|
374 aTailItem->iDataTailIndex = 0; |
|
375 tailPtr = startPtr; |
|
376 activePart = &aMessageData.iSecondDataPart; |
|
377 } |
|
378 |
|
379 UpdateDataAvailable(*aTailItem, EFalse); |
|
380 } |
|
381 |
|
382 aTailItem->iDataLostCount = 0; |
|
383 |
|
384 DEBUG_PRINT_BUFFER; |
|
385 |
|
386 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetMessageData - return" ) ) ); |
|
387 } |
|
388 |
|
389 // --------------------------------------------------------------------------- |
|
390 // Get new data for condition listener. |
|
391 // Always get all the data available. |
|
392 // --------------------------------------------------------------------------- |
|
393 // |
|
394 void CSensrvChannelBuffer::GetConditionData(TSensrvTailIndexItem* aTailItem, |
|
395 CSensrvChannelListener::TChannelDataParts& aDataParts) |
|
396 { |
|
397 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetConditionData" ) ) ); |
|
398 |
|
399 if( aTailItem == NULL ) |
|
400 return; |
|
401 |
|
402 TInt actualCount1(0); |
|
403 TInt actualCount2(0); |
|
404 |
|
405 // Condition data is always cleared at every new data notification, so |
|
406 // it is unlikely that it ever will build up to more than maximum buffering count, |
|
407 // or have two parts, unless SSY thread somehow manages to call BufferFilled twice |
|
408 // or more times in a row without new data handling on server main thread. |
|
409 // However, it is theoretically possible, so check the available count |
|
410 // and need for multiple parts. |
|
411 // If further optimization of condition checking is required, this possibility can |
|
412 // probably be quite safely ignored and second data part gotten rid of. |
|
413 if (!aTailItem->iConditionDataAvailable) |
|
414 { |
|
415 // No new data available, do nothing |
|
416 BUFFER_TRACE((_L("#### No more condition data available"))); |
|
417 } |
|
418 else if (aTailItem->iConditionTailIndex >= iHeadIndex) |
|
419 { |
|
420 // Condition tail after (or at) head, so get up to end of the buffer |
|
421 // and again from the beginning up to the head |
|
422 actualCount1 = iValidEndIndex - aTailItem->iConditionTailIndex; |
|
423 actualCount2 = iHeadIndex; |
|
424 BUFFER_TRACE((_L("#### Two parts of condition data available"))); |
|
425 } |
|
426 else |
|
427 { |
|
428 // Condition tail before head, so get up to head |
|
429 actualCount1 = iHeadIndex - aTailItem->iConditionTailIndex; |
|
430 BUFFER_TRACE((_L("#### One part of condition data available"))); |
|
431 } |
|
432 |
|
433 // Get data parts |
|
434 TUint8* startPtr = const_cast<TUint8*>(iBuffer->Ptr()); |
|
435 TUint8* tailPtr = startPtr + aTailItem->iConditionTailIndex*iItemSize; |
|
436 |
|
437 aDataParts.iFirstDataPart.Set(tailPtr, actualCount1*iItemSize); |
|
438 aDataParts.iSecondDataPart.Set(startPtr, actualCount2*iItemSize); |
|
439 |
|
440 // Reset tail |
|
441 aTailItem->iConditionTailIndex = iHeadIndex; |
|
442 aTailItem->iConditionDataAvailable = 0; |
|
443 |
|
444 DEBUG_PRINT_BUFFER; |
|
445 |
|
446 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetConditionData - return" ) ) ); |
|
447 } |
|
448 |
|
449 // --------------------------------------------------------------------------- |
|
450 // Invalidates range of items starting from head index. |
|
451 // Adjusts valid and tail indexes accordingly. |
|
452 // --------------------------------------------------------------------------- |
|
453 // |
|
454 void CSensrvChannelBuffer::InvalidateRange(TInt aCount) |
|
455 { |
|
456 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::InvalidateRange(aCount: %d)" ), aCount ) ); |
|
457 |
|
458 TInt invalidEnd(iHeadIndex+aCount); |
|
459 |
|
460 // Data loss occurs for items between iHeadIndex and invalidIndex, |
|
461 // but only up to iValidEndIndex |
|
462 TInt dataLossIndex(0); |
|
463 if (invalidEnd > iValidEndIndex) |
|
464 { |
|
465 dataLossIndex = iValidEndIndex; |
|
466 } |
|
467 else |
|
468 { |
|
469 dataLossIndex = invalidEnd; |
|
470 } |
|
471 |
|
472 // Update tail indexes and data lost for tail indexes in invalidated area |
|
473 for(TInt i = 0; i < iTailIndexArray.Count(); i++) |
|
474 { |
|
475 if ( iTailIndexArray[i]->iDataAvailable |
|
476 && iTailIndexArray[i]->iDataTailIndex >= iHeadIndex |
|
477 && iTailIndexArray[i]->iDataTailIndex < invalidEnd) |
|
478 { |
|
479 // Indicate missed data |
|
480 iTailIndexArray[i]->iDataLostCount += dataLossIndex - iTailIndexArray[i]->iDataTailIndex; |
|
481 |
|
482 // Move tail to end of invalid range |
|
483 if (invalidEnd >= iValidEndIndex) |
|
484 { |
|
485 // Roll tail to zero index at end of valid buffer. |
|
486 iTailIndexArray[i]->iDataTailIndex = 0; |
|
487 } |
|
488 else |
|
489 { |
|
490 iTailIndexArray[i]->iDataTailIndex = invalidEnd; |
|
491 } |
|
492 |
|
493 // It is necessary to update available amount after invalidation ate some of it. |
|
494 UpdateDataAvailable(*(iTailIndexArray[i]), EFalse); |
|
495 } |
|
496 else |
|
497 { |
|
498 // Do not adjust, as tail is before head, at head (with no unread data), |
|
499 // or beyond invalidation range. |
|
500 // -> It cannot be affected by the invalidation |
|
501 } |
|
502 |
|
503 // Update condition tail index. Should very rarely if ever come here. |
|
504 // Only possible if SSY thread is able to make multiple buffer fills |
|
505 // before server gets to handle new data available. |
|
506 if ( iTailIndexArray[i]->iConditionDataAvailable |
|
507 && iTailIndexArray[i]->iConditionTailIndex >= iHeadIndex |
|
508 && iTailIndexArray[i]->iConditionTailIndex < invalidEnd ) |
|
509 { |
|
510 if (invalidEnd >= iValidEndIndex) |
|
511 { |
|
512 // Roll tail to zero index at end of valid buffer. |
|
513 iTailIndexArray[i]->iConditionTailIndex = 0; |
|
514 } |
|
515 else |
|
516 { |
|
517 iTailIndexArray[i]->iConditionTailIndex = invalidEnd; |
|
518 } |
|
519 |
|
520 // It is necessary to update available amount after invalidation ate some of it. |
|
521 UpdateDataAvailable(*(iTailIndexArray[i]), EFalse); |
|
522 } |
|
523 else |
|
524 { |
|
525 // Do not adjust, as tail is before head, at head (with no unread data), |
|
526 // or beyond invalidation range. |
|
527 // -> It cannot be affected by the invalidation |
|
528 } |
|
529 } |
|
530 |
|
531 // Valid data ends at head index, unless it was beyond invalidated range. |
|
532 if (invalidEnd >= iValidEndIndex) |
|
533 { |
|
534 iValidEndIndex = iHeadIndex; |
|
535 } |
|
536 |
|
537 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::InvalidateRange - return" ) ) ); |
|
538 } |
|
539 |
|
540 // --------------------------------------------------------------------------- |
|
541 // Checks how much new data is available for listener. |
|
542 // |
|
543 // The data available is iHeadIndex - iDataTailIndex if iHeadIndex |
|
544 // is larger than iTailIndex, or iBufferLength - iDataTailIndex + iHeadIndex, |
|
545 // if iHeadIndex is smaller than iTailIndex. |
|
546 // --------------------------------------------------------------------------- |
|
547 // |
|
548 void CSensrvChannelBuffer::UpdateDataAvailable(TSensrvTailIndexItem& aTailItem, |
|
549 TBool aMoreData) |
|
550 { |
|
551 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::UpdateDataAvailable(aTailItem.iListener: 0x%x, aMoreData: %d)" ), aTailItem.iListener, aMoreData ) ); |
|
552 |
|
553 // Update data available |
|
554 if (aTailItem.iDataTailIndex != KSensrvChannelBufferUnusedTail) |
|
555 { |
|
556 if (aTailItem.iDataTailIndex == KSensrvChannelBufferUninitializedTail) |
|
557 { |
|
558 aTailItem.iDataAvailable = 0; |
|
559 aTailItem.iDataTailIndex = iHeadIndex; |
|
560 } |
|
561 else if (aTailItem.iDataTailIndex == iHeadIndex) |
|
562 { |
|
563 if (aMoreData) |
|
564 { |
|
565 // The amount of available data increased with this update; |
|
566 // being at head index means that buffer is full |
|
567 aTailItem.iDataAvailable = iValidEndIndex; |
|
568 } |
|
569 else |
|
570 { |
|
571 // The amount of data potentially decreased with this update; |
|
572 // being at headindex means there is no data available |
|
573 aTailItem.iDataAvailable = 0; |
|
574 } |
|
575 } |
|
576 else if (aTailItem.iDataTailIndex < iHeadIndex) |
|
577 { |
|
578 aTailItem.iDataAvailable = iHeadIndex - aTailItem.iDataTailIndex; |
|
579 } |
|
580 else // aTailItem.iDataTailIndex > iHeadIndex |
|
581 { |
|
582 aTailItem.iDataAvailable = iValidEndIndex - aTailItem.iDataTailIndex + iHeadIndex; |
|
583 } |
|
584 } |
|
585 |
|
586 // Update condition data available |
|
587 if (aTailItem.iConditionTailIndex != KSensrvChannelBufferUnusedTail) |
|
588 { |
|
589 if (aTailItem.iConditionTailIndex == KSensrvChannelBufferUninitializedTail) |
|
590 { |
|
591 aTailItem.iConditionDataAvailable = 0; |
|
592 aTailItem.iConditionTailIndex = iHeadIndex; |
|
593 } |
|
594 else if (aTailItem.iConditionTailIndex == iHeadIndex) |
|
595 { |
|
596 if (aMoreData) |
|
597 { |
|
598 // The amount of available data increased with this update; |
|
599 // being at head index means that buffer is full |
|
600 aTailItem.iConditionDataAvailable = iValidEndIndex; |
|
601 } |
|
602 else |
|
603 { |
|
604 // The amount of data potentially decreased with this update; |
|
605 // being at headindex means there is no data available |
|
606 aTailItem.iConditionDataAvailable = 0; |
|
607 } |
|
608 } |
|
609 else if (aTailItem.iConditionTailIndex < iHeadIndex) |
|
610 { |
|
611 aTailItem.iConditionDataAvailable = iHeadIndex - aTailItem.iConditionTailIndex; |
|
612 } |
|
613 else // aTailItem.iConditionTailIndex > iHeadIndex |
|
614 { |
|
615 aTailItem.iConditionDataAvailable = iValidEndIndex - aTailItem.iConditionTailIndex + iHeadIndex; |
|
616 } |
|
617 } |
|
618 |
|
619 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::UpdateDataAvailable - return. Data available: %d" ), aTailItem.iDataAvailable ) ); |
|
620 } |
|
621 |
|
622 // --------------------------------------------------------------------------- |
|
623 // Returns tail index for listener |
|
624 // --------------------------------------------------------------------------- |
|
625 // |
|
626 TInt CSensrvChannelBuffer::GetTailIndex(CSensrvChannelListener* aListener) |
|
627 { |
|
628 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetTailIndex(aListener: 0x%x)" ), aListener ) ); |
|
629 |
|
630 TInt index(0); |
|
631 |
|
632 for(TInt i = 0; !index && i < iTailIndexArray.Count(); i++) |
|
633 { |
|
634 if (iTailIndexArray[i]->iListener == aListener) |
|
635 { |
|
636 index = i; |
|
637 } |
|
638 } |
|
639 |
|
640 if (!index) |
|
641 { |
|
642 index = KErrNotFound; |
|
643 } |
|
644 |
|
645 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetTailIndex - return %d" ), index ) ); |
|
646 |
|
647 return index; |
|
648 } |
|
649 |
|
650 #ifdef BUFFER_TRACE_DEBUG |
|
651 // --------------------------------------------------------------------------- |
|
652 // Prints out buffer details with RDebug |
|
653 // --------------------------------------------------------------------------- |
|
654 // |
|
655 void CSensrvChannelBuffer::DebugPrintBuffer() |
|
656 { |
|
657 BUFFER_TRACE((_L("#### iHeadIndex: %d, iValidEndIndex: %d, iRequestedFreeBlockLength: %d"), iHeadIndex, iValidEndIndex, iRequestedFreeBlockLength)); |
|
658 for(TInt i = 0; i < iTailIndexArray.Count(); i++) |
|
659 { |
|
660 BUFFER_TRACE((_L("#### iListener: 0x%x, iDataTailIndex: %d, iConditionTailIndex: %d, iDataLostCount: %d, iDataAvailable: %d, iConditionDataAvailable: %d"), |
|
661 iTailIndexArray[i]->iListener, |
|
662 iTailIndexArray[i]->iDataTailIndex, |
|
663 iTailIndexArray[i]->iConditionTailIndex, |
|
664 iTailIndexArray[i]->iDataLostCount, |
|
665 iTailIndexArray[i]->iDataAvailable, |
|
666 iTailIndexArray[i]->iConditionDataAvailable)); |
|
667 } |
|
668 } |
|
669 #endif // BUFFER_TRACE_DEBUG |
|
670 |
|
671 |
|
672 // --------------------------------------------------------------------------- |
|
673 // Get the initial data for listener to transaction data item |
|
674 // --------------------------------------------------------------------------- |
|
675 // |
|
676 void CSensrvChannelBuffer::GetInitialMessageData( CSensrvChannelListener::TChannelDataMessage& aMessageData ) |
|
677 { |
|
678 COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetInitialMessageData iLatestWrittenItemIndex %d" ), |
|
679 iLatestWrittenItemIndex ) ); |
|
680 |
|
681 aMessageData.iDataItemCount = 0; |
|
682 aMessageData.iDataLostCount = 0; |
|
683 |
|
684 if ( iLatestWrittenItemIndex >= 0 ) |
|
685 { |
|
686 TUint8* itemPtr = const_cast<TUint8*>( iBuffer->Ptr() ) + iLatestWrittenItemIndex * iItemSize; |
|
687 aMessageData.iFirstDataPart.Set( itemPtr, iItemSize ); |
|
688 aMessageData.iSecondDataPart.Set( KNullDesC8 ); |
|
689 aMessageData.iDataItemCount = 1; |
|
690 } |
|
691 |
|
692 COMPONENT_TRACE( _L( "Sensor Server - CSensrvChannelBuffer::GetInitialMessageData - return" ) ); |
|
693 } |
|
694 |