sensorservices/sensorserver/src/server/sensrvchannelbuffer.cpp
changeset 0 4e1aa6a622a0
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     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