--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sensorservices/sensorserver/src/server/sensrvchannelbuffer.cpp Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,694 @@
+/*
+* Copyright (c) 2006-2008 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: Sensor server channel buffer implementation
+*
+*/
+
+
+#include "sensrvdefines.h"
+#include "sensrvchannel.h"
+#include "sensrvpluginproxy.h"
+#include "sensrvchannelbuffer.h"
+#include "sensrvchannellistener.h"
+
+
+// ---------------------------------------------------------------------------
+// 2-phase constructor
+// ---------------------------------------------------------------------------
+//
+CSensrvChannelBuffer* CSensrvChannelBuffer::NewL(TInt aItemSize,
+ TInt aBufferLength)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::NewL(aItemSize: %d, aBufferLength: %d)" ), aItemSize, aBufferLength ) );
+
+ CSensrvChannelBuffer* self = new( ELeave ) CSensrvChannelBuffer(aItemSize, aBufferLength);
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::NewL - return 0x%x" ), self ) );
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// C++ constructor
+// ---------------------------------------------------------------------------
+//
+CSensrvChannelBuffer::CSensrvChannelBuffer(TInt aItemSize,
+ TInt aBufferLength)
+ : iItemSize(aItemSize),
+ iBufferLength(aBufferLength < KSensrvMinimumBufferLength ? KSensrvMinimumBufferLength : aBufferLength),
+ iLatestWrittenItemIndex( KErrNotFound )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CSensrvChannelBuffer()" )) );
+
+ // Nothing to do
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CSensrvChannelBuffer - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// 2nd phase of construction
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::ConstructL()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::ConstructL()" ) ) );
+
+ // Check parameter validity here, as constructor cannot leave.
+ TInt bufferSize = iItemSize*iBufferLength;
+ if ( iItemSize <= 0
+ || iBufferLength <= 0
+ || (KMaxTInt/iItemSize) <= iBufferLength )
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::ConstructL - ERROR: Invalid parameters" ) ) );
+ User::Leave(KErrArgument);
+ }
+
+ // Construct buffer
+ iBuffer = HBufC8::NewL(bufferSize);
+
+ BUFFER_TRACE( ( _L( "#### CSensrvChannelBuffer::ConstructL(): iBufferLength: %d" ), iBufferLength ) );
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::ConstructL - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CSensrvChannelBuffer::~CSensrvChannelBuffer()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::~CSensrvChannelBuffer()" ) ) );
+
+ delete iBuffer;
+
+ iTailIndexArray.ResetAndDestroy();
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::~CSensrvChannelBuffer - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Get pointer to next free block (the beginning of head index item)
+// Invalidate next aCount items and move indexes accordingly.
+// ---------------------------------------------------------------------------
+//
+TUint8* CSensrvChannelBuffer::GetFreeBlock(TInt aCount)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetFreeBlock(aCount: %d)" ), aCount ) );
+
+ __ASSERT_ALWAYS(aCount <= iBufferLength, User::Panic(KSensrvPanicCategory, ESensrvPanicOutOfBounds));
+ __ASSERT_ALWAYS(!iRequestedFreeBlockLength, User::Panic(KSensrvPanicCategory, ESensrvPanicPreviousBlockNotYetWritten));
+
+ // Check if there is enough space in the end of the buffer to allocate continuous
+ // block of aCount items
+ if (iHeadIndex + aCount > iBufferLength)
+ {
+ // No room, invalidate the end of buffer and move head to start of buffer.
+ InvalidateRange(iBufferLength);
+ iHeadIndex = 0;
+ }
+ else
+ {
+ // There is room at end of buffer, do nothing
+ }
+
+ // Invalidate desired range
+ InvalidateRange(aCount);
+
+ // Get head pointer
+ TUint8* ptr = const_cast<TUint8*>(iBuffer->Ptr());
+ ptr += iHeadIndex*iItemSize;
+
+ iRequestedFreeBlockLength = aCount;
+
+ DEBUG_PRINT_BUFFER;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetFreeBlock - return %d" ), ptr ) );
+
+ return ptr;
+ }
+
+// ---------------------------------------------------------------------------
+// Validate specified count of items and adjust indexes.
+// Head index is moved aCount items forward, as well as iValidEndIndex,
+// if that is at head.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::WroteBlock(TInt aCount)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::WroteBlock(aCount: %d)" ), aCount ) );
+
+ __ASSERT_ALWAYS(iRequestedFreeBlockLength >= aCount, User::Panic(KSensrvPanicCategory, ESensrvPanicRequestedFreeBlockTooSmall));
+
+ // Negative count indicates an error
+ TInt total(iHeadIndex + aCount);
+
+ if (aCount < 0 || total > iBufferLength)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::WroteBlock - Invalid count: %d, iBufferLength: %d, iHeadIndex: %d" ), aCount, iBufferLength, iHeadIndex ) );
+ }
+ else if (aCount)
+ {
+ // Store the latest written item index to be used as initial data
+ iLatestWrittenItemIndex = total - 1;
+
+ iHeadIndex = total;
+
+ if (iValidEndIndex < iHeadIndex)
+ {
+ iValidEndIndex = iHeadIndex;
+ }
+
+ if (iHeadIndex == iBufferLength)
+ {
+ iHeadIndex = 0;
+ }
+
+ for(TInt i = 0; i < iTailIndexArray.Count(); i++)
+ {
+ UpdateDataAvailable(*(iTailIndexArray[i]), ETrue);
+ }
+ }
+ else
+ {
+ // Nothing to do when count is zero
+ }
+
+ iRequestedFreeBlockLength = 0;
+
+ DEBUG_PRINT_BUFFER;
+ }
+
+// ---------------------------------------------------------------------------
+// Cancels any outstanding free block request
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::CancelFreeBlock()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CancelFreeBlock()" ) ) );
+
+ iRequestedFreeBlockLength = 0;
+
+ DEBUG_PRINT_BUFFER;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::CancelFreeBlock - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Adds a listener tail index
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannelBuffer::AddListener(CSensrvChannelListener* aListener,
+ TSensrvTailIndexItem*& aTailItem,
+ CSensrvChannelListener::TSensrvChannelListenerState aState)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::AddListener(aListener: 0x%x, <retval>, aState: %d)" ), aListener, aState ) );
+
+ __ASSERT_ALWAYS(aListener, User::Panic(KSensrvPanicCategory, ESensrvPanicNullListener));
+ __ASSERT_ALWAYS(GetTailIndex(aListener) == KErrNotFound, User::Panic(KSensrvPanicCategory, ESensrvPanicDuplicateListener));
+
+ aTailItem = new TSensrvTailIndexItem(aListener);
+
+ TInt err(KErrNoMemory);
+
+ if (aTailItem)
+ {
+ if (aState == CSensrvChannelListener::EChannelListenerStateDataListening)
+ {
+ // If no outstanding request for data block (i.e. first listener),
+ // initialize index to head index.
+ if (iRequestedFreeBlockLength)
+ {
+ aTailItem->iDataTailIndex = KSensrvChannelBufferUninitializedTail;
+ }
+ else
+ {
+ aTailItem->iDataTailIndex = iHeadIndex;
+ }
+ }
+ else if (aState == CSensrvChannelListener::EChannelListenerStateConditionListening)
+ {
+ // Unlike data, conditions are available immediately, regardless of
+ // current listening state. Each condition set will individually
+ // be evaluated if it should ignore new data.
+ aTailItem->iConditionTailIndex = iHeadIndex;
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::AddListener - ERROR: Invalid state: %d" ), aState ) );
+ }
+
+
+ err = iTailIndexArray.Append(aTailItem);
+
+ if (err != KErrNone)
+ {
+ delete aTailItem;
+ aTailItem = NULL;
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::AddListener - return %d, aTailItem: 0x%x" ), err, aTailItem ) );
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Removes a listener tail index
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::RemoveListener(CSensrvChannelListener* aListener)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::DeleteListener(aListener: 0x%x)" ), aListener ) );
+
+ __ASSERT_ALWAYS(aListener, User::Panic(KSensrvPanicCategory, ESensrvPanicNullListener));
+ TBool removed(EFalse);
+
+ for(TInt i = 0; !removed && i < iTailIndexArray.Count(); i++)
+ {
+ if (iTailIndexArray[i]->iListener == aListener)
+ {
+ delete iTailIndexArray[i];
+ iTailIndexArray.Remove(i);
+ removed = ETrue;
+ }
+ }
+
+ // Clear requested free block length
+ if( iTailIndexArray.Count() == 0 )
+ {
+ CancelFreeBlock();
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::DeleteListener - return (removed: %d)" ), removed ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Get new data for listener to transaction data item
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::GetMessageData(TSensrvTailIndexItem* aTailItem,
+ CSensrvChannelListener::TChannelDataMessage& aMessageData,
+ TInt aCount)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetMessageData(aCount: %d)" ), aCount ) );
+
+ if( aTailItem == NULL )
+ return;
+
+ TBool done(EFalse);
+ TInt actualCount(aCount > aTailItem->iDataAvailable ? aTailItem->iDataAvailable : aCount);
+
+ // Get tail item pointer
+ TUint8* startPtr = const_cast<TUint8*>(iBuffer->Ptr());
+ TUint8* tailPtr = startPtr + aTailItem->iDataTailIndex*iItemSize;
+
+ TPtrC8* activePart = &aMessageData.iFirstDataPart;
+
+ aMessageData.iDataLostCount = aTailItem->iDataLostCount;
+
+ while (!done)
+ {
+ TInt available(0);
+
+ // Adjust tail index
+ if (!aTailItem->iDataAvailable)
+ {
+ // No new data available, do nothing
+ BUFFER_TRACE((_L("#### No more data available")));
+ done = ETrue;
+ }
+ else if ( aTailItem->iDataTailIndex < iHeadIndex )
+ {
+ // Data available up to head index
+ available = iHeadIndex - aTailItem->iDataTailIndex;
+ TInt remainder = actualCount - aMessageData.iDataItemCount;
+ if (remainder < available)
+ {
+ available = remainder;
+ }
+ BUFFER_TRACE((_L("#### More data was available")));
+ done = ETrue;
+ }
+ else // iTailIndexArray[index].iDataTailIndex >= iHeadIndex
+ {
+ // New data available up to iValidEndIndex and possibly more again from start
+ // Only possible to get here on first pass.
+ available = iValidEndIndex - aTailItem->iDataTailIndex;
+ if (actualCount <= available)
+ {
+ available = actualCount;
+ done = ETrue; // No second pass needed
+ BUFFER_TRACE((_L("#### Just single block of data was available")));
+ }
+ else
+ {
+ BUFFER_TRACE((_L("#### Possibly second block of data available")));
+ }
+ }
+
+ aTailItem->iDataTailIndex += available;
+ activePart->Set(tailPtr, available*iItemSize);
+ aMessageData.iDataItemCount += available;
+
+ // Roll tail index over to zero if at end of buffer,
+ // unless valid buffer ends at head index, in which case
+ // SSY has reserved a block beginning from iValidEndIndex,
+ // and we should wait for new data at current index.
+ if (aTailItem->iDataTailIndex == iValidEndIndex && iValidEndIndex != iHeadIndex)
+ {
+ aTailItem->iDataTailIndex = 0;
+ tailPtr = startPtr;
+ activePart = &aMessageData.iSecondDataPart;
+ }
+
+ UpdateDataAvailable(*aTailItem, EFalse);
+ }
+
+ aTailItem->iDataLostCount = 0;
+
+ DEBUG_PRINT_BUFFER;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetMessageData - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Get new data for condition listener.
+// Always get all the data available.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::GetConditionData(TSensrvTailIndexItem* aTailItem,
+ CSensrvChannelListener::TChannelDataParts& aDataParts)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetConditionData" ) ) );
+
+ if( aTailItem == NULL )
+ return;
+
+ TInt actualCount1(0);
+ TInt actualCount2(0);
+
+ // Condition data is always cleared at every new data notification, so
+ // it is unlikely that it ever will build up to more than maximum buffering count,
+ // or have two parts, unless SSY thread somehow manages to call BufferFilled twice
+ // or more times in a row without new data handling on server main thread.
+ // However, it is theoretically possible, so check the available count
+ // and need for multiple parts.
+ // If further optimization of condition checking is required, this possibility can
+ // probably be quite safely ignored and second data part gotten rid of.
+ if (!aTailItem->iConditionDataAvailable)
+ {
+ // No new data available, do nothing
+ BUFFER_TRACE((_L("#### No more condition data available")));
+ }
+ else if (aTailItem->iConditionTailIndex >= iHeadIndex)
+ {
+ // Condition tail after (or at) head, so get up to end of the buffer
+ // and again from the beginning up to the head
+ actualCount1 = iValidEndIndex - aTailItem->iConditionTailIndex;
+ actualCount2 = iHeadIndex;
+ BUFFER_TRACE((_L("#### Two parts of condition data available")));
+ }
+ else
+ {
+ // Condition tail before head, so get up to head
+ actualCount1 = iHeadIndex - aTailItem->iConditionTailIndex;
+ BUFFER_TRACE((_L("#### One part of condition data available")));
+ }
+
+ // Get data parts
+ TUint8* startPtr = const_cast<TUint8*>(iBuffer->Ptr());
+ TUint8* tailPtr = startPtr + aTailItem->iConditionTailIndex*iItemSize;
+
+ aDataParts.iFirstDataPart.Set(tailPtr, actualCount1*iItemSize);
+ aDataParts.iSecondDataPart.Set(startPtr, actualCount2*iItemSize);
+
+ // Reset tail
+ aTailItem->iConditionTailIndex = iHeadIndex;
+ aTailItem->iConditionDataAvailable = 0;
+
+ DEBUG_PRINT_BUFFER;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetConditionData - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Invalidates range of items starting from head index.
+// Adjusts valid and tail indexes accordingly.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::InvalidateRange(TInt aCount)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::InvalidateRange(aCount: %d)" ), aCount ) );
+
+ TInt invalidEnd(iHeadIndex+aCount);
+
+ // Data loss occurs for items between iHeadIndex and invalidIndex,
+ // but only up to iValidEndIndex
+ TInt dataLossIndex(0);
+ if (invalidEnd > iValidEndIndex)
+ {
+ dataLossIndex = iValidEndIndex;
+ }
+ else
+ {
+ dataLossIndex = invalidEnd;
+ }
+
+ // Update tail indexes and data lost for tail indexes in invalidated area
+ for(TInt i = 0; i < iTailIndexArray.Count(); i++)
+ {
+ if ( iTailIndexArray[i]->iDataAvailable
+ && iTailIndexArray[i]->iDataTailIndex >= iHeadIndex
+ && iTailIndexArray[i]->iDataTailIndex < invalidEnd)
+ {
+ // Indicate missed data
+ iTailIndexArray[i]->iDataLostCount += dataLossIndex - iTailIndexArray[i]->iDataTailIndex;
+
+ // Move tail to end of invalid range
+ if (invalidEnd >= iValidEndIndex)
+ {
+ // Roll tail to zero index at end of valid buffer.
+ iTailIndexArray[i]->iDataTailIndex = 0;
+ }
+ else
+ {
+ iTailIndexArray[i]->iDataTailIndex = invalidEnd;
+ }
+
+ // It is necessary to update available amount after invalidation ate some of it.
+ UpdateDataAvailable(*(iTailIndexArray[i]), EFalse);
+ }
+ else
+ {
+ // Do not adjust, as tail is before head, at head (with no unread data),
+ // or beyond invalidation range.
+ // -> It cannot be affected by the invalidation
+ }
+
+ // Update condition tail index. Should very rarely if ever come here.
+ // Only possible if SSY thread is able to make multiple buffer fills
+ // before server gets to handle new data available.
+ if ( iTailIndexArray[i]->iConditionDataAvailable
+ && iTailIndexArray[i]->iConditionTailIndex >= iHeadIndex
+ && iTailIndexArray[i]->iConditionTailIndex < invalidEnd )
+ {
+ if (invalidEnd >= iValidEndIndex)
+ {
+ // Roll tail to zero index at end of valid buffer.
+ iTailIndexArray[i]->iConditionTailIndex = 0;
+ }
+ else
+ {
+ iTailIndexArray[i]->iConditionTailIndex = invalidEnd;
+ }
+
+ // It is necessary to update available amount after invalidation ate some of it.
+ UpdateDataAvailable(*(iTailIndexArray[i]), EFalse);
+ }
+ else
+ {
+ // Do not adjust, as tail is before head, at head (with no unread data),
+ // or beyond invalidation range.
+ // -> It cannot be affected by the invalidation
+ }
+ }
+
+ // Valid data ends at head index, unless it was beyond invalidated range.
+ if (invalidEnd >= iValidEndIndex)
+ {
+ iValidEndIndex = iHeadIndex;
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::InvalidateRange - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Checks how much new data is available for listener.
+//
+// The data available is iHeadIndex - iDataTailIndex if iHeadIndex
+// is larger than iTailIndex, or iBufferLength - iDataTailIndex + iHeadIndex,
+// if iHeadIndex is smaller than iTailIndex.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::UpdateDataAvailable(TSensrvTailIndexItem& aTailItem,
+ TBool aMoreData)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::UpdateDataAvailable(aTailItem.iListener: 0x%x, aMoreData: %d)" ), aTailItem.iListener, aMoreData ) );
+
+ // Update data available
+ if (aTailItem.iDataTailIndex != KSensrvChannelBufferUnusedTail)
+ {
+ if (aTailItem.iDataTailIndex == KSensrvChannelBufferUninitializedTail)
+ {
+ aTailItem.iDataAvailable = 0;
+ aTailItem.iDataTailIndex = iHeadIndex;
+ }
+ else if (aTailItem.iDataTailIndex == iHeadIndex)
+ {
+ if (aMoreData)
+ {
+ // The amount of available data increased with this update;
+ // being at head index means that buffer is full
+ aTailItem.iDataAvailable = iValidEndIndex;
+ }
+ else
+ {
+ // The amount of data potentially decreased with this update;
+ // being at headindex means there is no data available
+ aTailItem.iDataAvailable = 0;
+ }
+ }
+ else if (aTailItem.iDataTailIndex < iHeadIndex)
+ {
+ aTailItem.iDataAvailable = iHeadIndex - aTailItem.iDataTailIndex;
+ }
+ else // aTailItem.iDataTailIndex > iHeadIndex
+ {
+ aTailItem.iDataAvailable = iValidEndIndex - aTailItem.iDataTailIndex + iHeadIndex;
+ }
+ }
+
+ // Update condition data available
+ if (aTailItem.iConditionTailIndex != KSensrvChannelBufferUnusedTail)
+ {
+ if (aTailItem.iConditionTailIndex == KSensrvChannelBufferUninitializedTail)
+ {
+ aTailItem.iConditionDataAvailable = 0;
+ aTailItem.iConditionTailIndex = iHeadIndex;
+ }
+ else if (aTailItem.iConditionTailIndex == iHeadIndex)
+ {
+ if (aMoreData)
+ {
+ // The amount of available data increased with this update;
+ // being at head index means that buffer is full
+ aTailItem.iConditionDataAvailable = iValidEndIndex;
+ }
+ else
+ {
+ // The amount of data potentially decreased with this update;
+ // being at headindex means there is no data available
+ aTailItem.iConditionDataAvailable = 0;
+ }
+ }
+ else if (aTailItem.iConditionTailIndex < iHeadIndex)
+ {
+ aTailItem.iConditionDataAvailable = iHeadIndex - aTailItem.iConditionTailIndex;
+ }
+ else // aTailItem.iConditionTailIndex > iHeadIndex
+ {
+ aTailItem.iConditionDataAvailable = iValidEndIndex - aTailItem.iConditionTailIndex + iHeadIndex;
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::UpdateDataAvailable - return. Data available: %d" ), aTailItem.iDataAvailable ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Returns tail index for listener
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannelBuffer::GetTailIndex(CSensrvChannelListener* aListener)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetTailIndex(aListener: 0x%x)" ), aListener ) );
+
+ TInt index(0);
+
+ for(TInt i = 0; !index && i < iTailIndexArray.Count(); i++)
+ {
+ if (iTailIndexArray[i]->iListener == aListener)
+ {
+ index = i;
+ }
+ }
+
+ if (!index)
+ {
+ index = KErrNotFound;
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetTailIndex - return %d" ), index ) );
+
+ return index;
+ }
+
+#ifdef BUFFER_TRACE_DEBUG
+// ---------------------------------------------------------------------------
+// Prints out buffer details with RDebug
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::DebugPrintBuffer()
+ {
+ BUFFER_TRACE((_L("#### iHeadIndex: %d, iValidEndIndex: %d, iRequestedFreeBlockLength: %d"), iHeadIndex, iValidEndIndex, iRequestedFreeBlockLength));
+ for(TInt i = 0; i < iTailIndexArray.Count(); i++)
+ {
+ BUFFER_TRACE((_L("#### iListener: 0x%x, iDataTailIndex: %d, iConditionTailIndex: %d, iDataLostCount: %d, iDataAvailable: %d, iConditionDataAvailable: %d"),
+ iTailIndexArray[i]->iListener,
+ iTailIndexArray[i]->iDataTailIndex,
+ iTailIndexArray[i]->iConditionTailIndex,
+ iTailIndexArray[i]->iDataLostCount,
+ iTailIndexArray[i]->iDataAvailable,
+ iTailIndexArray[i]->iConditionDataAvailable));
+ }
+ }
+#endif // BUFFER_TRACE_DEBUG
+
+
+// ---------------------------------------------------------------------------
+// Get the initial data for listener to transaction data item
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannelBuffer::GetInitialMessageData( CSensrvChannelListener::TChannelDataMessage& aMessageData )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannelBuffer::GetInitialMessageData iLatestWrittenItemIndex %d" ),
+ iLatestWrittenItemIndex ) );
+
+ aMessageData.iDataItemCount = 0;
+ aMessageData.iDataLostCount = 0;
+
+ if ( iLatestWrittenItemIndex >= 0 )
+ {
+ TUint8* itemPtr = const_cast<TUint8*>( iBuffer->Ptr() ) + iLatestWrittenItemIndex * iItemSize;
+ aMessageData.iFirstDataPart.Set( itemPtr, iItemSize );
+ aMessageData.iSecondDataPart.Set( KNullDesC8 );
+ aMessageData.iDataItemCount = 1;
+ }
+
+ COMPONENT_TRACE( _L( "Sensor Server - CSensrvChannelBuffer::GetInitialMessageData - return" ) );
+ }
+