landmarks/locationlandmarks/server/src/EPos_CPosLmServerOperation.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:06:48 +0200
changeset 0 667063e416a2
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2002-2005 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: provides functionality common to all server operations
*
*
*/


#include <EPos_Landmarks.h>
#include "EPos_CPosLmServerOperation.h"
#include "EPos_LandmarksServerPanics.h"
#include "EPos_MPosLmServerOperationObserver.h"
#include "EPos_PosLmServerCommon.h"
#include "EPos_LmServerGlobal.h"

const TInt KDrivePosition = 7;

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmServerOperation::CPosLmServerOperation(
    CPosLmServer& aServer,
    MPosLmServerOperationObserver* aObserver ) :
    CActive(EPriorityIdle),
    iServer( aServer ),
    iObserver(aObserver),
    iProgress(0),
    iStatusFlag(KPosLmOperationNotComplete)
    {
    CActiveScheduler::Add(this);
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::BaseConstructL(
    const TDesC& aUri)
    {
    iDb = CPosLmLocalDbAccess::NewL();
    User::LeaveIfError(iDb->OpenDatabaseL(aUri));

    iDiskUtilities = CPosLmDiskUtilities::NewL();

    iDbDrive = aUri[KDrivePosition];
    iDbUri = aUri.AllocL();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmServerOperation::~CPosLmServerOperation()
    {
    Cancel();
    if (iStatusFlag == KErrNone)
        {
        iStatusFlag = KErrServerTerminated;
        }
    CompleteAndRemoveMessagesFromSyncWaitList();
    CompleteAndRemoveMessagesFromAsyncWaitList();
    iSyncWaitList.Close();
    iAsyncWaitList.Close();
    delete iDiskUtilities;
    delete iDb;
    iClientSessions.Close();
    delete iDbUri;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TInt CPosLmServerOperation::RunError( TInt aError )
    {
    iStatusFlag = aError;
    CompleteAndRemoveMessagesFromSyncWaitList();
    CompleteAndRemoveMessagesFromAsyncWaitList();
    iObserver->HandleOperationStatus(this, iStatusFlag);

    return KErrNone;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::DoCancel()
    {
    iStatusFlag = KErrCancel;
    CompleteAndRemoveMessagesFromSyncWaitList();
    CompleteAndRemoveMessagesFromAsyncWaitList();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::AddToSyncWaitListL(
    const RMessage2& aMessage,
    TAny* aSession)
    {
    User::LeaveIfError(iSyncWaitList.Append(Message(aMessage, aSession)));
    if (iClientSessions.Find(static_cast<TUint*>(aSession)) == KErrNotFound)
        {
        User::LeaveIfError(iClientSessions.Append(
                    static_cast<TUint*>(aSession)));
        }

    if ( iStatusFlag != KPosLmOperationNotComplete )
        {
        NotifyClients();
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::AddToAsyncWaitListL(
    const RMessage2& aMessage,
    TAny* aSession )
    {
    TPckgBuf<TReal32> progress;
    TInt desMaxLength = aMessage.GetDesMaxLength(KPosLmServerProgressArg);
    if (desMaxLength != progress.Length())
        {
        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
        return;
        }
    User::LeaveIfError(iAsyncWaitList.Append(Message(aMessage, aSession)));
    if (iClientSessions.Find(static_cast<TUint*>(aSession)) == KErrNotFound)
        {
        User::LeaveIfError(iClientSessions.Append(
            static_cast<TUint*>(aSession)));
        }
    
    if ( iStatusFlag != KPosLmOperationNotComplete )
        {
        // this client should only be informed about operation
        // status (because it has not been yet) and removed from
        // operation's clients
        NotifyClients();
        RemoveSessionMessages( aSession );
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::RemoveFromAsyncWaitList(
    const RMessage2& aMessage,
    TAny* aSession)
    {
    RemoveFromWaitList(iAsyncWaitList, aSession);
    LmServerGlobal::Complete(aMessage, KErrNone);

    TInt position = iClientSessions.Find(static_cast<TUint*>(aSession));
    if (position != KErrNotFound)
        {
        iClientSessions.Remove(position);
        }
    iObserver->HandleOperationStatus( this, iStatusFlag );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::RemoveSessionMessages(
    TAny* aSession)
    {
    RemoveFromWaitList(iAsyncWaitList, aSession);
    RemoveFromWaitList(iSyncWaitList, aSession);

    TInt position = iClientSessions.Find(static_cast<TUint*>(aSession));
    if (position != KErrNotFound)
        {
        iClientSessions.Remove(position);
        }
    iObserver->HandleOperationStatus( this, iStatusFlag );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::CompleteAndRemoveMessagesFromAsyncWaitList()
    {
    for (TInt i = 0; i < iAsyncWaitList.Count(); i++)
        {
        Write(iAsyncWaitList[i].iMsg);
        LmServerGlobal::Complete(iAsyncWaitList[i].iMsg, iStatusFlag);
        }

    iAsyncWaitList.Reset();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::CompleteAndRemoveMessagesFromSyncWaitList()
    {
    for (TInt i = 0; i < iSyncWaitList.Count(); i++)
        {
        LmServerGlobal::Complete(iSyncWaitList[i].iMsg, iStatusFlag);
        }

    iSyncWaitList.Reset();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::Write(
    const RMessage2& aMessage)
    {
    // It is not necessary to return the error code, because the client will be
    // panicked if the write fails. Hence, the client won't receive the error
    // anyway.
    TPckgBuf<TInt> statusFlag(iStatusFlag);
    TInt err = LmServerGlobal::Write(aMessage, KPosLmServerStatusArg,
        statusFlag);

    if (err == KErrNone)
        {
        TPckgBuf<TReal32> progress(iProgress);
        err = LmServerGlobal::Write(aMessage, KPosLmServerProgressArg,
            progress);

        if (err == KErrNone && iStatusFlag == KErrNone)
            {
            // Reset init flag on client side
            TPckgBuf<TUint> initFlag(ENoInit);
            LmServerGlobal::Write(aMessage, KPosLmServerInitFlagArg, initFlag);
            }
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::NotifyClients()
    {
    // Check if there are any clients left listening for status
    if (iClientSessions.Count() == 0)
        {
        Cancel();
        iObserver->HandleOperationStatus(this, iStatusFlag);
        return;
        }

    CompleteAndRemoveMessagesFromAsyncWaitList();

    if ( iStatusFlag == KErrNone )
        {
        CompleteAndRemoveMessagesFromSyncWaitList();
        iObserver->HandleOperationStatus(this, iStatusFlag);
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::CompleteSelf()
    {
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status, KErrNone);
    SetActive();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmServerOperation::RemoveFromWaitList(
    RArray<TPosMessage>& aWaitList,
    TAny* aSession)
    {
    for (TInt i = 0; i < aWaitList.Count(); i++)
        {
        if (aSession == aWaitList[i].iSession)
            {
            LmServerGlobal::Complete(aWaitList[i].iMsg, KErrCancel);
            aWaitList.Remove(i--);
            }
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmServerOperation::TPosMessage CPosLmServerOperation::Message(
    const RMessage2& aMessage,
    TAny* aSession)
    {
    TPosMessage msg;
    msg.iSession = aSession;
    msg.iMsg = aMessage;

    return msg;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TInt CPosLmServerOperation::Status() const
    {
    return iStatusFlag;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmServerOperation::IsRegistered( TAny* aSession ) const
    {
    return iClientSessions.Find( static_cast<TUint*>( aSession ) ) != KErrNotFound;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmServerOperation::HasRequests( TAny* aSession ) const
    {
    for ( TInt i = 0; i < iAsyncWaitList.Count(); i++ )
        {
        if ( iAsyncWaitList[i].iSession == aSession )
            return ETrue;
        }
    for ( TInt i = 0; i < iSyncWaitList.Count(); i++ )
        {
        if ( iSyncWaitList[i].iSession == aSession )
            return ETrue;
        }
    return EFalse;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmServerOperation::HasClients() const
    {
    return iClientSessions.Count() > 0;;
    }