landmarks/locationlandmarks/server/src/EPos_CPosLmLocalAccessSubsession.cpp
changeset 0 667063e416a2
child 8 6fcbaa43369c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/landmarks/locationlandmarks/server/src/EPos_CPosLmLocalAccessSubsession.cpp	Tue Feb 02 01:06:48 2010 +0200
@@ -0,0 +1,858 @@
+/*
+* 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: subsession class for operations related to local access.
+*
+*
+*/
+
+
+#include <e32base.h>
+#include <s32mem.h>
+
+#include <epos_poslmdatabaseutility.h>
+#include <epos_cposlmdiskutilities.h>
+#include <epos_cposlmlocaldbaccess.h>
+
+#include "epos_lmdebug.h"
+#include "EPos_CPosLmServer.h"
+#include "EPos_CPosLmOperationManager.h"
+#include "EPos_PosLmServerCommon.h"
+#include "EPos_LmServerGlobal.h"
+#include "EPos_LandmarksServerPanics.h"
+#include "EPos_CPosLmEventHandler.h"
+#include "EPos_PosLmDatabaseManager.h"
+#include "epos_cposlmindexmanager.h"
+#include "EPos_CPosLmNameIndex.h"
+#include "EPos_CPosLmActiveCompacter.h"
+#include "EPos_CPosLmLocalAccessSubsession.h"
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+CPosLmLocalAccessSubsession::CPosLmLocalAccessSubsession(
+    CPosLmServer* aLmServer) :
+    CPosLmSubsessionBase(EPosLocalAccessSubsession, aLmServer)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+CPosLmLocalAccessSubsession* CPosLmLocalAccessSubsession::NewLC(
+    CPosLmServer* aLmServer)
+    {
+    CPosLmLocalAccessSubsession* self =
+        new (ELeave) CPosLmLocalAccessSubsession(aLmServer);
+    CleanupClosePushL(*self);
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+CPosLmLocalAccessSubsession::~CPosLmLocalAccessSubsession()
+    {
+    delete iCompacter;
+    delete iDbAccess;
+    delete iEventHandler;
+
+    // release database
+    iHasWriteLock = EFalse;
+    iNoOfReadLocks = 0;
+    if ( iUsingNameIndex && Server() && iDbUri )
+        {
+        Server()->IndexManager().RemoveIndexUser( *iDbUri );
+        iUsingNameIndex = EFalse;
+        }
+    delete iDbUri;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CPosLmLocalAccessSubsession::HasWriteLock( const TDesC& aUri )
+    {
+    if (iHasWriteLock && aUri == *iDbUri)
+        {
+        return ETrue;
+        }
+
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CPosLmLocalAccessSubsession::HasAnyLock( const TDesC& aUri ) 
+    {
+    if ((iHasWriteLock || iNoOfReadLocks > 0) && aUri == *iDbUri)
+        {
+        return ETrue;
+        }
+
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleOperationEventL(
+    TPosLmEvent aEvent,
+    const TDesC& aUri,
+    TBool aCheckUri)
+    {
+    // Check if the event is dedicated to the database, which this subsession is
+    // connected to.
+    if (!aCheckUri && iEventHandler && iDbUri ||
+        iEventHandler && iDbUri && aUri.Compare(*iDbUri) == 0)
+        {
+        iEventHandler->HandleIncomingEventL(aEvent);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::CompleteOutstandingEventRequest(
+    TInt aError)
+    {
+    if (iEventHandler)
+        {
+        iEventHandler->CompleteAnyOutStandingRequest(aError);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::ReleaseCompactLock()
+    {
+    delete iCompacter;
+    iCompacter = NULL;
+    iHasWriteLock = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::ServiceL(
+    const RMessage2& aMessage)
+    {
+#if 0 // #ifdef _DEBUG
+    RThread client;
+    aMessage.Client( client );
+    LOG3("LocalSession::ServiceL in: function %d (client SID 0x%X, thread 0x%X)",
+        aMessage.Function(), aMessage.SecureId().iId, client.Id() );
+#endif    
+    
+    switch (aMessage.Function())
+        {
+        case EPosLmServerRegisterSession:
+            if (iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasAlreadyRegistered);
+                return;
+                }
+            RegisterUriL(aMessage);
+            break;
+        case EPosLmServerInitializeSync:
+        case EPosLmServerInitializeAsync:
+        case EPosLmServerInitializeCancel:
+        case EPosLmServerLangSwitchSync:
+        case EPosLmServerLangSwitchAsync:
+        case EPosLmServerLangSwitchCancel:
+        case EPosLmServerRecoverSync:
+        case EPosLmServerRecoverAsync:
+        case EPosLmServerRecoverCancel:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            Server()->OperationManagerL(aMessage.Function())->AddRequestL(
+                aMessage, *iDbUri, this);
+            break;
+        case EPosLmServerDbLock:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            DatabaseLockL(aMessage);
+            break;
+        case EPosLmServerIndexTransaction:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            HandleDataTransactionL(aMessage);
+            break;
+        case EPosLmServerReportLmEvent:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            ForwardEventToAllSessionsL(aMessage);
+            break;
+        case EPosLmServerUpdateNameIndex:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            HandleUpdateLandmarkIndexL( aMessage );
+            break;
+        case EPosLmServerListenForLmEvent:
+            // No check of iDbUri needed here
+            User::LeaveIfError(Server()->StartSettingsListenerIfNeeded());
+            if (!iEventHandler)
+                {
+                iEventHandler = CPosLmEventHandler::NewL();
+                }
+            iEventHandler->HandleRequestForEventL(aMessage);
+            break;
+        case EPosLmServerCancelListenForLmEvent:
+            // No check of iDbUri needed here
+            delete iEventHandler;
+            iEventHandler = NULL;
+            LmServerGlobal::Complete(aMessage, KErrNone);
+            break;
+        case EPosLmServerCreateDefaultDb:
+            // No check of iDbUri needed here
+            CreateDefaultDatabaseL(aMessage);
+            break;
+        case EPosLmServerOpenNameIndex:
+        case EPosLmServerCloseNameIndex:
+            if ( !iDbUri )
+                {
+                PanicClient( aMessage, EPosClientHasNotRegistered );
+                return;
+                }
+            HandleUseNameIndexL( aMessage );
+            break;
+        case EPosLmServerReadSortedIds:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            HandleReadSortedIdsL( aMessage );
+            break;
+        case EPosLmServerReadNameIndex:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            HandleReadSortedLandmarksL( aMessage );
+            break;
+        case EPosLmServerNameIndexStatus:
+            if (!iDbUri)
+                {
+                PanicClient(aMessage, EPosClientHasNotRegistered);
+                return;
+                }
+            HandleNameIndexStatusL( aMessage );
+            break;
+        default:
+            User::Leave(KErrNotSupported);
+            break;
+        }
+#if 0 // #ifdef _DEBUG
+    LOG("LocalSession::ServiceL out");
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::RegisterUriL(
+    const RMessage2& aMessage)
+    {
+    // Validate length of client message.
+    TInt desLength = aMessage.GetDesLength(KPosLmServerUriArg);
+    if (desLength < 0)
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        return;
+        }
+
+    // Read URI from client message.
+    HBufC* dbUri = HBufC::NewLC(desLength);
+    TPtr uriPtr = dbUri->Des();
+    if (LmServerGlobal::Read(aMessage, KPosLmServerUriArg, uriPtr) != KErrNone)
+        {
+        CleanupStack::PopAndDestroy(dbUri);
+        return;
+        }
+
+    // Lowercase the URI to be able to match different cases of the same URI.
+    uriPtr.LowerCase();
+
+    TInt err = PosLmDatabaseUtility::ValidateDatabaseUri(uriPtr);
+    if (err == KErrArgument)
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        CleanupStack::PopAndDestroy(dbUri);
+        return;
+        }
+    else
+        {
+        User::LeaveIfError(err);
+        }
+
+    // iDbUri is set last as it is used to validate if the uri has been
+    // registered properly.
+    CleanupStack::Pop(dbUri);
+    iDbUri = dbUri;
+    
+    LmServerGlobal::Complete(aMessage, KErrNone);
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::DatabaseLockL(
+    const RMessage2& aMessage)
+    {
+    TBool setLockOn = static_cast<TBool>(aMessage.Int0());
+    TBool writeLock = static_cast<TBool>(aMessage.Int1());
+
+    if (setLockOn)
+        {
+        if (!Server()->CanAcquireLock(writeLock, *iDbUri))
+            {
+            User::Leave(KErrLocked);
+            }
+
+        if (writeLock)
+            {
+            iHasWriteLock = ETrue;
+            }
+        else
+            {
+            iNoOfReadLocks++;
+            }
+        }
+    else if (writeLock)
+        {
+        if (!iHasWriteLock)
+            {
+            PanicClient(aMessage, EPosLmDbNotLocked);
+            return;
+            }
+        iHasWriteLock = EFalse;
+        }
+    else
+        {
+        if (iNoOfReadLocks == 0)
+            {
+            PanicClient(aMessage, EPosLmDbNotLocked);
+            return;
+            }
+        iNoOfReadLocks--;
+        }
+
+    LmServerGlobal::Complete(aMessage, KErrNone);
+
+    if (!setLockOn && writeLock) // releasing write lock
+        {
+        TRAP_IGNORE( CompactIfNeededL() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleDataTransactionL( const RMessage2& aMessage )
+    {
+    if ( Server()->IndexManager().Find( *iDbUri ) >= 0 )
+        {
+        CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
+        User::LeaveIfError( index.Status() );
+        switch( aMessage.Int0() )
+            {
+            case EPosLmServerTransactionStart:
+                index.StartTransaction();
+                break;
+            case EPosLmServerTransactionCommit:
+                index.CommitTransaction();
+                break;
+            case EPosLmServerTransactionRollback:
+                index.RollbackTransaction();
+                break;
+            default:
+                PanicClient( aMessage, EPosUnableToReadOrWriteDataToClient );
+            }
+        }
+
+    LmServerGlobal::Complete( aMessage, KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::ForwardEventToAllSessionsL(
+    const RMessage2& aMessage)
+    {
+    TPckgBuf<TPosLmEvent> event;
+
+    TInt desLength = aMessage.GetDesLength(KPosLmServerEventArg);
+    if (desLength != event.Length())
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        return;
+        }
+
+    if (LmServerGlobal::Read(aMessage, KPosLmServerEventArg, event) != KErrNone)
+        {
+        return;
+        }
+
+    // Validate that the event type is a valid enum value.
+    TPosLmEventType eventType = event().iEventType;
+    if (!(eventType == EPosLmEventUnknownChanges ||
+        eventType == EPosLmEventNewDefaultDatabaseLocation ||
+        eventType == EPosLmEventMediaRemoved ||
+        (eventType >= EPosLmEventLandmarkUnknownChanges &&
+        eventType <= EPosLmEventLandmarkUpdated) ||
+        (eventType >= EPosLmEventCategoryUnknownChanges &&
+        eventType <= EPosLmEventCategoryUpdated)))
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        return;
+        }
+
+    Server()->ForwardEventToAllSessionsL(event(), *iDbUri, ETrue);
+
+    LmServerGlobal::Complete(aMessage, KErrNone);
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::CreateDefaultDatabaseL(
+    const RMessage2& aMessage)
+    {
+    TInt desLength = aMessage.GetDesLength(KPosLmServerUriArg);
+    if (desLength < 0)
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        return;
+        }
+
+    HBufC* msgUri = HBufC::NewLC(desLength);
+    TPtr uriPtr = msgUri->Des();
+
+    if (LmServerGlobal::Read(aMessage, KPosLmServerUriArg, uriPtr) == KErrNone)
+        {
+        HBufC* uri = PosLmDatabaseUtility::CreateDatabaseUriL(*msgUri);
+        CleanupStack::PushL(uri);
+
+        // To remove a warning, the event must be default constructed.
+        TPosLmDatabaseEvent event =
+            {
+            EPosLmDbDatabaseRegistered,
+            {0,0,0,0,0,0,0,0}
+            };
+
+        CheckDiskSizeL(*uri);
+        TPckgBuf<TBool> replaceDb;
+
+        desLength = aMessage.GetDesLength(KPosLmServerDbReplaceArg);
+        if (desLength != replaceDb.Length())
+            {
+            PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+            CleanupStack::PopAndDestroy(2, msgUri);
+            return;
+            }
+
+        if (LmServerGlobal::Read(
+            aMessage, KPosLmServerDbReplaceArg, replaceDb) != KErrNone)
+            {
+            CleanupStack::PopAndDestroy(2, msgUri);
+            return;
+            }
+
+        PosLmDatabaseManager::CreateDatabaseL(uri->Des(), ETrue, replaceDb());
+
+        Server()->ForwardEventToAllSessionsL(event, uri->Des());
+        LmServerGlobal::Complete(aMessage, KErrNone);
+        CleanupStack::PopAndDestroy(uri);
+        }
+
+    CleanupStack::PopAndDestroy(msgUri);
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::CheckDiskSizeL(
+    const TDesC& aUri)
+    {
+    CPosLmDiskUtilities* diskUtilities = CPosLmDiskUtilities::NewL();
+    CleanupStack::PushL(diskUtilities);
+
+    diskUtilities->DiskSpaceBelowCriticalLevelL(
+        diskUtilities->EstimatedDiskSizeOfEmptyDatabase(),
+        (aUri)[KPosLocalDbFileProtocol().Length()]);
+
+    CleanupStack::PopAndDestroy(diskUtilities);
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::CompactIfNeededL()
+    {
+    if (!iDbAccess)
+        {
+        CPosLmLocalDbAccess* dbAccess =
+            CPosLmLocalDbAccess::NewL(CPosLmLocalDbAccess::EServerCompactLevel);
+        CleanupStack::PushL(dbAccess);
+        User::LeaveIfError(dbAccess->OpenDatabaseL(*iDbUri)); // Will be trapped
+        CleanupStack::Pop(dbAccess);
+        iDbAccess = dbAccess;
+        }
+
+    if (iDbAccess->IsCompactNeededL())
+        {
+        iCompacter = CPosLmActiveCompacter::NewL(*this, *iDbAccess);
+        iHasWriteLock = ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleReadSortedIdsL( const RMessage2& aMessage )
+    {
+    AssertIndexLoadedL();
+
+    TPosLmServerReadArrayParam param;
+    TPckg<TPosLmServerReadArrayParam> pack( param );
+    if ( LmServerGlobal::Read( aMessage, KPosLmServerIdArrayParam, pack ) != KErrNone )
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        return;
+        }
+    
+    CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
+    User::LeaveIfError( index.Status() );
+
+    TPosLmItemId* ids = new (ELeave) TPosLmItemId[ param.iCount ];
+    CleanupStack::PushL( ids );
+    TPtrC8 data( (TUint8*) ids, sizeof( TPosLmItemId ) * param.iCount );
+
+    TInt count = index.GetSortedIds( param.iFirst, param.iCount, ids, param.iRemainder );
+    if ( count >= 0 )
+        {
+        param.iActualCount = count;
+        param.iMinBufferNeeded = 0;
+        User::LeaveIfError( LmServerGlobal::Write( aMessage, KPosLmServerIdArrayParam, pack ) );
+        User::LeaveIfError( LmServerGlobal::Write( aMessage, KPosLmServerIdArray, data ) );
+        }
+    else
+        {
+        User::Leave( count ); // error code
+        }
+    CleanupStack::PopAndDestroy( ids );
+    LmServerGlobal::Complete( aMessage, count );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleReadSortedLandmarksL( const RMessage2& aMessage )
+    {
+    AssertIndexLoadedL();
+
+    TPosLmServerReadArrayParam param;
+    TPckg<TPosLmServerReadArrayParam> pack( param );
+    if ( LmServerGlobal::Read( aMessage, 0, pack ) != KErrNone )
+        {
+        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
+        return;
+        }
+
+    param.iMinBufferNeeded = 0;
+    param.iActualCount = 0;
+    param.iRemainder = 0;
+
+    TInt bufferSize = aMessage.GetDesLengthL( 1 );
+    
+    CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
+    User::LeaveIfError( index.Status() );
+
+    CBufFlat* buffer = CBufFlat::NewL( bufferSize );
+    CleanupStack::PushL( buffer );
+    
+    RBufWriteStream out;
+    out.Open( *buffer );
+    CleanupClosePushL( out );
+
+    if ( param.iCount > 0 ) // in ascending order
+        {
+        GetSortedLandmarksL( index, out, param, bufferSize );
+        }
+    else
+        {
+        GetSortedLandmarksReverseL( index, out, param, bufferSize );
+        }
+    
+    out.CommitL();
+    
+    User::LeaveIfError( LmServerGlobal::Write( aMessage, 0, pack ) );
+    User::LeaveIfError( LmServerGlobal::Write( aMessage, 1, buffer->Ptr( 0 ) ) );
+    LmServerGlobal::Complete( aMessage, KErrNone );
+
+    CleanupStack::PopAndDestroy( &out );
+    CleanupStack::PopAndDestroy( buffer );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::GetSortedLandmarksL( 
+    CPosLmNameIndex& aNameIndex,
+    RWriteStream& aOut,
+    TPosLmServerReadArrayParam& aParam,
+    TInt aMaxSize )
+    {
+    TInt start = Max( aParam.iFirst, 0 );
+    TInt last = Min( aParam.iFirst + aParam.iCount, aNameIndex.Count() );
+
+    TInt leftInBuffer = aMaxSize;
+    TInt i = start;
+    for ( ; i < last ; i++ ) 
+        {
+        const CPosLmNameIndex::CItem& item = aNameIndex.Item( i );
+        if ( !ExportIndexItemL( item, aOut, leftInBuffer, aParam ) )
+            break;
+        }
+
+    aParam.iRemainder = aNameIndex.Count() - i;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::GetSortedLandmarksReverseL( 
+    CPosLmNameIndex& aNameIndex,
+    RWriteStream& aOut,
+    TPosLmServerReadArrayParam& aParam,
+    TInt aMaxSize )
+    {
+    TInt start = Min( aParam.iFirst, aNameIndex.Count() - 1 );
+    TInt last = Max( aParam.iFirst + aParam.iCount, -1 ); // iCount is negative
+
+    TInt leftInBuffer = aMaxSize;
+    TInt i = start;
+    for ( ; i > last ; i-- ) 
+        {
+        const CPosLmNameIndex::CItem& item = aNameIndex.Item( i );
+        if ( !ExportIndexItemL( item, aOut, leftInBuffer, aParam ) )
+            break;
+        }
+
+    aParam.iRemainder = i+1;
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+TBool CPosLmLocalAccessSubsession::ExportIndexItemL( 
+    const CPosLmNameIndex::CItem& aItem,
+    RWriteStream& aOut,
+    TInt& aLeftInBuffer,
+    TPosLmServerReadArrayParam& aParam )
+    {
+    TInt itemSize = aItem.Size();
+    if ( itemSize <= aLeftInBuffer )
+        {
+        aItem.ExternalizeL( aOut );
+        aLeftInBuffer -= itemSize;
+        aParam.iActualCount++;
+        return ETrue;
+        }
+    else 
+        { 
+        if ( itemSize > aLeftInBuffer )
+            {
+            aParam.iMinBufferNeeded = itemSize;
+            }
+        return EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleUpdateLandmarkIndexL( const RMessage2& aMessage )
+    {
+    //LOG1("UpdateIndex: function %d", aMessage.Int0() );
+    AssertIndexLoadedL();
+    switch ( aMessage.Int0() )
+        {
+        case EPosLmServerAddLandmarks:
+        case EPosLmServerUpdateLandmarks:
+            HandleLandmarksAddedOrUpdatedL( aMessage );
+            break;
+        case EPosLmServerRemoveLandmarks:
+            HandleLandmarksRemovedL( aMessage );
+            break;
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleLandmarksAddedOrUpdatedL( const RMessage2& aMessage )
+    {
+    CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
+    User::LeaveIfError( index.Status() );
+
+    HBufC8* buf = LmServerGlobal::CopyClientBuffer8LC( aMessage, 1 );
+    RDesReadStream readStream( *buf );
+
+    TPosLmItemId id = KPosLmNullItemId;
+
+    // Update index
+    TInt lmCount = readStream.ReadInt32L();
+    for ( TInt i = 0; i < lmCount; i++ )
+        {
+        id = readStream.ReadInt32L();
+        TInt nameLen = readStream.ReadInt32L();
+        
+        HBufC* lmBuf = HBufC::NewLC( nameLen );
+        
+        TPtr name( lmBuf->Des() );
+        readStream.ReadL( name, nameLen );
+        
+        if ( aMessage.Int0() == EPosLmServerUpdateLandmarks ) 
+            {
+            index.UpdateL( id, lmBuf );
+            }
+        else
+            {
+            index.InsertL( id, lmBuf );
+            }
+        CleanupStack::Pop( lmBuf );
+        }
+    
+    readStream.Close();
+    CleanupStack::PopAndDestroy( buf );
+
+    LmServerGlobal::Complete( aMessage, KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleLandmarksRemovedL( const RMessage2& aMessage )
+    {
+    HBufC8* buf = LmServerGlobal::CopyClientBuffer8LC( aMessage, 1 );
+    if ( buf->Size() % ( sizeof( TPosLmItemId ) ) != 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TInt lmCount = buf->Size() / ( sizeof( TPosLmItemId ) );
+    const TPosLmItemId* ids = reinterpret_cast<const TPosLmItemId*>( buf->Ptr() );
+
+    // Update index
+    CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
+    User::LeaveIfError( index.Status() );
+    for ( TInt i = 0; i < lmCount; i++ )
+        {
+        index.Remove( ids[i] );
+        }
+    CleanupStack::PopAndDestroy( buf );
+    
+    LmServerGlobal::Complete( aMessage, KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleNameIndexStatusL( const RMessage2& aMessage )
+    {
+    AssertIndexLoadedL();
+    CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
+    TInt status = index.Status();
+    if ( status < 0 )
+        LmServerGlobal::Complete( aMessage, status );
+    else
+        LmServerGlobal::Complete( aMessage, index.Count() );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::HandleUseNameIndexL(
+    const RMessage2& aMessage )
+    {
+    switch ( aMessage.Function() )
+        {
+        case EPosLmServerOpenNameIndex:
+            {
+            if ( iUsingNameIndex )
+                {
+                PanicClient( aMessage, EPosClientHasAlreadyRegistered );
+                return;
+                }
+            // Register new user of lm index
+            Server()->IndexManager().AddIndexUserL( *iDbUri );
+            iUsingNameIndex = ETrue;
+            break;
+            }
+        case EPosLmServerCloseNameIndex:
+            {
+            if ( !iUsingNameIndex )
+                {
+                PanicClient( aMessage, EPosClientHasNotRegistered );
+                return;
+                }
+            Server()->IndexManager().RemoveIndexUser( *iDbUri );
+            iUsingNameIndex = EFalse;
+            break;
+            }
+        default:
+            break;
+        }
+    LmServerGlobal::Complete( aMessage, KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+//
+void CPosLmLocalAccessSubsession::AssertIndexLoadedL()
+    {
+    if ( Server()->IndexManager().Find( *iDbUri ) < 0 )
+        {
+        User::Leave( KErrNotFound );
+        }
+    }