cbs/CbsServer/ServerSrc/Ccbsreccollector.cpp
changeset 46 2fa1fa551b0b
parent 42 35488577e233
child 48 78df25012fda
--- a/cbs/CbsServer/ServerSrc/Ccbsreccollector.cpp	Mon Aug 23 15:50:31 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,584 +0,0 @@
-/*
-* Copyright (c) 2003 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:  This module contains the implementation of CCbsRecDecoder class 
-*                member functions.
-*    
-*                This class represents a collector, which stores pages of multipaged 
-*                messages. Complete messages are assembled and returned back to 
-*                the caller of CollectL() method.
-*  
-*                CCbsRecCollector stores message pages in a number of dynamic arrays.
-*                If all but one page of a message are present in collector, and
-*                the remaining page is received, the pages will be assembled and
-*                the corresponding message chain deleted.
-* 
-*                The maximum number of incomplete messages stored in collector at once
-*                is fixed and determined by KMaxCollectorMessages in CCbsRecCollector.cpp.
-* 
-*                CCbsRecCollector implements a circular list to contain message.
-*                Each incomplete message occupies a slot in this list. If the list already
-*                contains KMaxCollectorMessages messages, the next received multipaged
-*                message will delete all received pages of the oldest message in list.
-* 
-*                On receival of a message page, the collector compares network information
-*                (PLMN, LAC, CellId) of both messages to decide whether pages are of
-*                the same message. In short, for pages to be of the same message
-*                their network information have to meet the requirements set by the 
-*                geographical scope of the already collected page.
-*                See ETSI GSM 03.41 for a detailed description. 
-*
-*/
-
-
-// INCLUDE FILES
-#include "CbsServerPanic.h"
-#include "CCbsRecCollector.h"
-#include "CCbsRecMessage.h"
-#include "CCbsMessageFactory.h"
-#include "CCbsMessageCleanUpTimer.h"
-#include "CbsLogger.h"
-
-// CONSTANTS
-
-// Maximum number of pages in a single CB message.
-const TInt KMaxMessagePages = 15;
-
-// Maximum number of partial messages contained in the collector list.
-const TInt KMaxCollectorMessages = 10;
-
-// ================= MEMBER FUNCTIONS =======================
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::CCbsRecCollector
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// -----------------------------------------------------------------------------
-//
-CCbsRecCollector::CCbsRecCollector( CCbsMessageFactory& aFactory )
-    : iRootNodeIterator( 0 ),
-    iFactory( aFactory )
-    {
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::ConstructL
-// Symbian 2nd phase constructor can leave.
-// -----------------------------------------------------------------------------
-//
-void CCbsRecCollector::ConstructL()
-    {
-    CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::ConstructL()");
-
-    // initialize the root node array
-    iRootNodeArray = new ( ELeave ) CArrayPtrFlat< CMessageBuffer >
-        ( KMaxCollectorMessages );
-    iRootNodeArray->SetReserveL( KMaxCollectorMessages );
-    iMessageCleanupTimerArray = new ( ELeave ) CArrayPtrFlat< CCbsMessageCleanupTimer >
-        ( KMaxCollectorMessages );
-
-    for ( TInt i( 0 ); i < KMaxCollectorMessages; i++)
-        {
-        CMessageBuffer* array = new ( ELeave )
-            CMessageBuffer( KMaxMessagePages );
-        CleanupStack::PushL( array );
-        iRootNodeArray->AppendL( array );
-
-		CCbsMessageCleanupTimer* messageCleanUpTimer = CCbsMessageCleanupTimer::NewL( *this, *array );
-		iMessageCleanupTimerArray->AppendL( messageCleanUpTimer );
-        
-        CleanupStack::Pop(); // array
-        }
-    CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::ConstructL()");
-    }
-
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::NewL
-// Two-phased constructor.
-// -----------------------------------------------------------------------------
-//
- CCbsRecCollector* CCbsRecCollector::NewL( CCbsMessageFactory& aFactory )
-    {
-    CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::NewL()");
-
-    CCbsRecCollector* self = new ( ELeave ) CCbsRecCollector( aFactory );
-    CleanupStack::PushL( self );
-    self->ConstructL();
-    CleanupStack::Pop();
-
-    CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::NewL()");
-    return self;
-    }
-    
-// Destructor
-CCbsRecCollector::~CCbsRecCollector()
-    {
-    CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::~CCbsRecCollector()");
-
-    if ( iRootNodeArray )
-        {
-        TInt rootArrayLength( iRootNodeArray->Count() );
-        for ( TInt i( 0 ); i < rootArrayLength; i++ )
-            {
-            iRootNodeArray->At( i )->ResetAndDestroy();
-            }
-        iRootNodeArray->ResetAndDestroy();
-        delete iRootNodeArray;
-        }
-
-    if ( iMessageCleanupTimerArray )
-        {
-        iMessageCleanupTimerArray->ResetAndDestroy();
-        delete iMessageCleanupTimerArray;
-        }
-
-    CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::~CCbsRecCollector()");
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::CollectL
-// Adds a message to the location pointed by iRootNodeIterator.
-//   
-// Checks if all pages of message are present. If all pages
-// are present, sets aCompleted to ECbsMessageComplete,
-// combines message pages into a single message, destroys
-// pages from the list and returns the complete message
-// to caller in aMessage.
-
-// Algorithm:
-//   1.  Check if other pages of this message exist in list.
-//       (serial number and message identifier match)
-//   2.  True: Check if the other messages in chain need
-//       to be deleted. This is based on geographical scope
-//       and network information.
-//       Add this message to the correct message chain.
-//       False: Add this message to the chain pointed
-//       by the iRootNodeIterator.
-//   3.  Seek out the position in the chosed message chain so that
-//       the page number sequence remains ordered (1, 2, .., n)
-//   4.  Add the page to the correct position in chain.
-//   5.  Check if all pages of this message exist (number count).
-//   6.  True: Combine message pages into a single message
-//       and return this page to the caller. Set aCompleted
-//       to ECbsMessageComplete.
-//       False: Set aCompleted to ECbsMessageIncomplete.
-//
-// Note: Ownership of aMessage assumed. aMessage assumed to be
-// on cleanup stack.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//  
-CCbsMessage* CCbsRecCollector::CollectL( 
-    CCbsMessage* aMessage, TInt aMessageType )  
-    {
-	CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::CollectL()");
-
-    // 1.
-    CMessageBuffer* array = FindChainContainingPage( *aMessage );
-    CCbsMessage* mergedMessage = NULL;
-
-    if ( array  ) 
-        {		
-        CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): array != NULL");
-
-        // 2. (True), 3.
-        __ASSERT_DEBUG( array->Count() > 0, 
-            CbsServerPanic( ECbsCollectorArrayEmpty ) );
-
-        // Check geographical scope and network info to decide whether
-        // existing pages in this chain should be deleted.
-        TBool preserveExistingPages( 
-            CheckPageAreaInfoMatch( *aMessage, *array->At( 0 ) ) );
-		
-        CBSLOGSTRING2("CBSSERVER: CCbsRecCollector::CollectL(): preserveExistingPages: %d", preserveExistingPages );
-
-        if ( preserveExistingPages ) 
-            {			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Adding msg to chain...");
-            // aMessage is deleted, if it is a duplicate.
-            AddMessageToChainL( aMessage, *array );			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Adding msg to chain OK.");
-            }
-        else 
-            {			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain...");
-            DeleteChainL( *array );			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain OK.");
-            array->InsertL( 0, aMessage );			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Msg added to array.");
-            }
-        // aMessage, ownership transferred to msg chain or
-        // aMessage has been deleted by AddMessageToChainL
-        CleanupStack::Pop(); 
-
-        // 5. Check if this chain contains all pages of the message.
-        if ( AllPagesPresent( *array ) )
-            {			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): All pages present, merging...");
-
-            // 6. merge creates a new copy of this message
-            // leaves a pointer to msg to cleanup stack
-            mergedMessage = MergePagesLC( *array ); // on CS			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Merging OK.");
-
-			// we stop timer if its livecast message
-			if ( aMessageType == ECbsMessageLivecast )
-				{				
-                CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Msg type == ECbsMessageLivecast, stopping timer.");
-
-				TKeyArrayFix key(0, ECmpTUint16);
-				TInt index;
-				iRootNodeArray->Find( array, key, index);
-				iMessageCleanupTimerArray->At( index )->StopTimer();
-                
-                CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Timer stopped.");
-				}
-
-			CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain...");
-            DeleteChainL( *array );
-			CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain OK.");
-
-            CleanupStack::Pop(); // mergedMessage
-            }
-        }
-    else
-        {		
-        CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): array == NULL");
-
-		// if message pagenumber does not start from 1, its not inserted to chain.
-		if ( aMessage->ThisPage () == 1 ) 
-			{			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): aMessage->ThisPage () == 1");
-
-			// 2. (False)
-			// add this page as the first node in chain pointed by 
-			// iRootNodeIterator. Delete any pages contained in the chain
-			// occuping this location first.
-			array = iRootNodeArray->At( iRootNodeIterator );
-			DeleteChainL( *array );
-			array->InsertL( 0, aMessage );
-			CleanupStack::Pop(); // aMessage, ownership transferred to msg chain.
-			iRootNodeIterator++;
-			// Return to the first message, if passed the
-			// maximum messages.
-			iRootNodeIterator %= KMaxCollectorMessages;
-
-			if ( aMessageType == ECbsMessageLivecast )
-				{				
-                CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): aMessageType == ECbsMessageLivecast");
-
-				// start timeout timer for livecast message
-				TKeyArrayFix key(0, ECmpTUint16);
-				TInt index;
-				iRootNodeArray->Find( array, key, index);
-				iMessageCleanupTimerArray->At( index )->StartTimer();
-				
-                CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Timer started.");
-				}
-			}
-		else
-			{			
-            CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): CleanupStack::Pop()");
-			CleanupStack::Pop();
-			}
-        }
-    // mergedMessage == NULL if msg not completed,
-    // otherwise return the complete message
-	CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::CollectL(), returning mergedMessage.");
-
-    return mergedMessage;
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::DeleteChainL
-// Deletes all message pages contained in aArray.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//  
-void CCbsRecCollector::DeleteChainL( 
-    CMessageBuffer& aArray ) const
-    {
-    aArray.ResetAndDestroy();
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::AllPagesPresent
-// Returns ETrue if all pages of the message of aArray are present.
-// Counts pages in message chain aArray and compares the result
-// against the total number of pages in the message.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-// 
-TBool CCbsRecCollector::AllPagesPresent( 
-    const CMessageBuffer& aArray ) const
-    {
-    TBool result( ETrue );
-    if ( TUint( aArray.Count() ) < aArray.At( 0 )->TotalPages() )
-        {
-        result = EFalse;        
-        }
-    
-    return result;
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::MergePagesLC
-// Returns a complete message in aMessage.
-// Merges all pages in message chain aArray and returns
-// a pointer to the resulting assembled message. The pointer
-// is also left on the cleanup stack.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CCbsMessage* CCbsRecCollector::MergePagesLC( 
-    CMessageBuffer& aArray ) const
-    {
-    if ( aArray.Count() <= 0 )
-        {
-        User::Leave( KErrNotFound );
-        }
-    // Create a new message based on first message page in the chain.
-    CCbsMessage* message = iFactory.CreateMessageL( *aArray.At( 0 ) );
-
-    CleanupStack::PushL( message ); // left on cleanup stack
-
-    // Traverse through the chain and merge contents.
-    TInt length( 0 );
-    TInt count( aArray.Count() );
-
-    // If this is a Livecast message, use the 8-bit representation
-    // (message not decoded).
-    if ( message->IsLivecastMessage() )
-        {
-        for ( TInt j( 0 ); j < count; j++ )
-            {
-            length += aArray.At( j )->Contents8().Length();
-            }
-        
-        __ASSERT_DEBUG( length >= 0, CbsServerPanic( ECbsCollectorMergeFailed ) );
-
-        message->ReserveContentSize8L( length );
-        count = aArray.Count();
-        
-        for ( TInt i( 1 ); i < count; i++ ) 
-            {
-            message->AppendContent8( aArray.At( i )->Contents8() );
-            }
-        }
-    // Else use the 16-bit representation (message already decoded)
-    else
-        {
-        for ( TInt j( 0 ); j < count; j++ )
-            {
-            length += aArray.At( j )->Contents().Length();
-            }
-    
-	    __ASSERT_DEBUG( length >= 0, CbsServerPanic( ECbsCollectorMergeFailed ) );
-
-	    message->ReserveContentSizeL( length );
-	    count = aArray.Count();
-
-    // Append the rest of the pages (first page handled earlier)
-	    for ( TInt i( 1 ); i < count; i++ ) 
-	        {
-	        message->AppendContent( aArray.At( i )->Contents() );
-	        }
-        }
-    return message;
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::FindChainContainingPage
-// Returns the buffer containing pages of same message.
-// Finds and returns a message chain which already contains pages
-// of aMessage's message. If none is found, NULL is returned.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CMessageBuffer* CCbsRecCollector::FindChainContainingPage( 
-    const CCbsMessage& aMessage ) const
-    {
-    TBool quitSeek( EFalse );
-    TInt seekIterator( 0 );
-    TCbsDbMessageKey key( aMessage.Key() );
-    TCbsDbTopicNumber topicNumber( aMessage.TopicNumber() );
-    CMessageBuffer* array = NULL;
-    
-    // find out if the root array contains pages of this message
-    while ( ( seekIterator < KMaxCollectorMessages ) && !quitSeek  )
-        {
-        array = iRootNodeArray->At( seekIterator );
-        if ( array->Count() > 0 ) 
-            {
-            CCbsMessage* msg = array->At( 0 );
-            if ( key == msg->Key() && topicNumber == msg->TopicNumber() )
-                {
-                quitSeek = ETrue;
-                }
-            }
-        seekIterator++;
-        }
-
-    if ( !quitSeek )
-        {
-        array = NULL;
-        }
-    
-    return array;
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::AddMessageToChainL
-// Adds message page aMessage to the correct position in message chain aArray
-//        
-// Message chains are ordered in ascending page number order.
-// Duplicate pages are not accepted.
-//
-// Ownership of aMessage is transferred to aArray, if the given page
-// hasn't been already collected. The given page will be deleted,
-// if it already exists in the chain.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsRecCollector::AddMessageToChainL( 
-    CCbsMessage* aMessage, 
-    CMessageBuffer& aArray ) const
-    {
-    // Find out a position for this page in the chain.
-    TInt chainLength( aArray.Count() );    
-    TInt insertPosition( -1 );
-    TBool duplicate( EFalse );
-
-    for ( TInt i( 0 ); ( i < chainLength ) && !duplicate; i++ )
-        {
-        CCbsMessage* msg = aArray.At( i );
-        if ( insertPosition == -1 && msg->ThisPage() > aMessage->ThisPage() )
-            {
-            insertPosition = i;
-            }
-        else if ( msg->ThisPage() == aMessage->ThisPage() )
-            {
-            duplicate = ETrue; // This page has been already collected
-            delete aMessage;
-            }
-        }
-
-    // If this message was not a duplicate, add it to the chain
-    if ( !duplicate )
-        {
-        if ( insertPosition == -1 )
-            {
-            aArray.AppendL( aMessage );
-            }
-        else
-            {
-            aArray.InsertL( insertPosition, aMessage );
-            }
-        }    
-    }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::CheckPageAreaInfoMatch
-// Checks if these pages can be merged. Returns ETrue, if merging is acceptable.
-//   
-// Decision is based network information and geographical scope of 
-// pages. Network information consists of cell id, location area code
-// and operator id.
-// 
-// Assumption: aPage1 and aPage have identical message
-// identifiers and serial numbers. 
-// Returns ETrue if the pages are of same message.
-// On EFalse previous pages should be deleted.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TBool CCbsRecCollector::CheckPageAreaInfoMatch( 
-    const CCbsMessage& aPage1, 
-    const CCbsMessage& aPage2 ) const
-    {   
-    RMobilePhone::TMobilePhoneNetworkInfoV1 info1;
-    RMobilePhone::TMobilePhoneNetworkInfoV1 info2;
-
-    aPage1.GetPLMN( info1 );
-    aPage2.GetPLMN( info2 );
-
-    TBool result( EFalse );
-
-    if ( info1.iCountryCode == KRecMessageNoNetworkInfo || 
-        info2.iCountryCode == KRecMessageNoNetworkInfo )
-        {
-        // Network info is unavailable; we must assume that the aPage1
-        // is of the same page area as aPage2, so we return ETrue
-        // unconditionally.
-        result = ETrue;
-        }
-
-    if ( info1.iCountryCode == info2.iCountryCode && 
-        info1.iNetworkId == info2.iNetworkId )
-        // PLMN match
-        {
-        if ( aPage1.LAC() == aPage2.LAC() )
-            // LAC match
-            {
-            if ( aPage1.CellId() == aPage2.CellId() )
-                // Cell match
-                {
-                // Full network information match
-                result = ETrue;
-                }
-            else
-                {
-                // Cell mismatch
-                if ( aPage1.GeographicalScope() == 
-                    ECbsRecGeographicalScopeCell )
-                    // Cell id mismatch and scoped cell wide.
-                    {
-                    result = EFalse;
-                    }
-                else
-                    // Cell id mismatch, not scoped cell wide.
-                    {
-                    result = ETrue;
-                    }
-                }
-            }            
-        else
-            // LAC mismatch
-            {
-            if ( aPage1.GeographicalScope() == 
-                ECbsRecGeographicalScopePLMN )
-                {
-                // LAC mismatch but scoped operator-wide
-                result = ETrue;
-                }
-            else
-                {
-                // LAC mismatch and not scoped operator-wide
-                result = EFalse;
-                }
-            }
-        }
-    else
-        // PLMN mismatch
-        {
-        result = EFalse; // operator mismatch
-        }
-
-    return result;    
-    }
-
-
-// ================= OTHER EXPORTED FUNCTIONS ==============
-
-//  End of File