diff -r 000000000000 -r 4e1aa6a622a0 sensorservices/sensorserver/src/server/sensrvchannelbuffer.cpp --- /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(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, , 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(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(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( iBuffer->Ptr() ) + iLatestWrittenItemIndex * iItemSize; + aMessageData.iFirstDataPart.Set( itemPtr, iItemSize ); + aMessageData.iSecondDataPart.Set( KNullDesC8 ); + aMessageData.iDataItemCount = 1; + } + + COMPONENT_TRACE( _L( "Sensor Server - CSensrvChannelBuffer::GetInitialMessageData - return" ) ); + } +