convergedcallengine/spsettings/src/spsbufferedpublisher.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:45:17 +0300
branchRCL_3
changeset 19 7d48bed6ce0c
parent 0 ff3b6d0fd310
child 20 987c9837762f
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c)  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: Logic for bufferred publish and subcribe notifier
*
*/

#include <e32property.h>
#include "spdefaultvalues.h"

#include "spsbufferedpublisher.h"

const TUint32 KRealGlobalIndex = 0;
_LIT( KSemaphore, "CSpsBufferedPublisher" );

// ======== LOCAL FUNCTIONS ========

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
CSpsBufferedPublisher* CSpsBufferedPublisher::NewL( TUid aCategory, TUint aKey )
    {
    CSpsBufferedPublisher* self = new (ELeave) CSpsBufferedPublisher( aCategory, aKey );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
CSpsBufferedPublisher::CSpsBufferedPublisher( TUid aCategory, TUint aKey ):
    iCategory( aCategory ),
    iKey( aKey ),
    iIndex( KErrNotReady )
    {

    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
CSpsBufferedPublisher::~CSpsBufferedPublisher()
    {

    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
void CSpsBufferedPublisher::ConstructL()
    {
    static _LIT_SECURITY_POLICY_PASS( KAllowAllPolicy );

    TInt err = RProperty::Define( 
            iCategory, iKey, 
            RProperty::EByteArray,
            KAllowAllPolicy, KAllowAllPolicy, 
            RProperty::KMaxPropertySize );
    
    if( !err )
        {
        TBuf8<RProperty::KMaxPropertySize> data;
        data.FillZ( data.MaxLength() );
        User::LeaveIfError( RProperty::Set( iCategory, iKey, data ) );
        }
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
void CSpsBufferedPublisher::SetL( TUid aCategory, TUint aKey, TUint32 aData )
    {
    RSemaphore wait;
    TInt err = wait.OpenGlobal( KSemaphore );
     
    if ( err )
        {
        User::LeaveIfError( wait.CreateGlobal( KSemaphore, 1 ) );
        }
    
    wait.Wait();
    TCleanupItem cleanup( CSpsBufferedPublisher::SignalAndCloseSemaphore, &wait );
    CleanupStack::PushL( cleanup );
    
    TBuf8<RProperty::KMaxPropertySize> data;
    User::LeaveIfError(
        RProperty::Get( aCategory, aKey, data ) );

    // Increment index
    GlobalIndex( data )++;

    if( Base( data, GlobalIndex( data ) ) == GlobalIndex( data ) )
        {
        // Skip index if real index is same as KRealGlobalIndex
        GlobalIndex( data )++;
        }
        
    // Write data to index
    At( data, GlobalIndex( data ) ) = aData;
    
    User::LeaveIfError(
        RProperty::Set( aCategory, aKey, data ) );
    
    CleanupStack::PopAndDestroy(); // wait
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
void CSpsBufferedPublisher::GetL( RArray<TUint32>& aData )
    {
    User::LeaveIfError( iIndex );
    
    TBuf8<RProperty::KMaxPropertySize> data;
    User::LeaveIfError(
            RProperty::Get( iCategory, iKey, data ) );
    
    const TUint32 lastModified = GlobalIndex( data );
    const TUint32 indexDifference = lastModified - iIndex;
    if( Max( data ) < indexDifference )
        {
        // If some of data is missed
        iIndex = lastModified - Max( data );
        }
    
    // Start reading
    while( lastModified != iIndex ) 
        {
        iIndex++;
        
        if( Base( data, iIndex ) == iIndex )
            {
            // Skip index if real index is same as KRealGlobalIndex
            iIndex++;
            }
        aData.AppendL( At(data, iIndex) );
        }

    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
void CSpsBufferedPublisher::Start()
    {
    if( KErrNone > iIndex )
        {
        TBuf8<RProperty::KMaxPropertySize> data;
        RProperty::Get( iCategory, iKey, data );
        if( data.Length() )
            {
            // When no error occurs
            iIndex = GlobalIndex( data );
            }
        else
            {
            iIndex = 0;
            }
        }

    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
void CSpsBufferedPublisher::Stop()
    {
    iIndex = KErrNotReady;
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
void CSpsBufferedPublisher::SignalAndCloseSemaphore( TAny* aPtr )
    {
    RSemaphore* wait = (RSemaphore*)aPtr;
    wait->Signal();
    wait->Close();
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
TUint32& CSpsBufferedPublisher::At( TDes8& aData, TInt aIndex )
    {
    const TUint32 baseIndex = Base( aData, aIndex );
    TUint32 realIndex = aIndex - baseIndex;
    ASSERT( KRealGlobalIndex != realIndex ); // Check if global index is not used
    return (TUint32&)aData[ realIndex * sizeof(TUint32) ];
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
TUint CSpsBufferedPublisher::Max( TDesC8& aData )
    {
    return ( aData.Length() / sizeof(TUint32) );
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
TInt32 CSpsBufferedPublisher::Base( TDesC8& aData, TInt aIndex )
    {
    const TInt max = Max( aData );
    return ( max * (TUint32)( aIndex / max ) );
    }

// ---------------------------------------------------------------------------
// ?description
// ---------------------------------------------------------------------------
//
TUint32& CSpsBufferedPublisher::GlobalIndex( TDes8& aData )
    {
    return (TUint32&)aData[ KRealGlobalIndex ];
    }