landmarks/locationlandmarks/server/src/EPos_CPosLmLocalAccessSubsession.cpp
changeset 0 667063e416a2
child 8 6fcbaa43369c
equal deleted inserted replaced
-1:000000000000 0:667063e416a2
       
     1 /*
       
     2 * Copyright (c) 2002-2005 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: subsession class for operations related to local access.
       
    15 *
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <e32base.h>
       
    21 #include <s32mem.h>
       
    22 
       
    23 #include <epos_poslmdatabaseutility.h>
       
    24 #include <epos_cposlmdiskutilities.h>
       
    25 #include <epos_cposlmlocaldbaccess.h>
       
    26 
       
    27 #include "epos_lmdebug.h"
       
    28 #include "EPos_CPosLmServer.h"
       
    29 #include "EPos_CPosLmOperationManager.h"
       
    30 #include "EPos_PosLmServerCommon.h"
       
    31 #include "EPos_LmServerGlobal.h"
       
    32 #include "EPos_LandmarksServerPanics.h"
       
    33 #include "EPos_CPosLmEventHandler.h"
       
    34 #include "EPos_PosLmDatabaseManager.h"
       
    35 #include "epos_cposlmindexmanager.h"
       
    36 #include "EPos_CPosLmNameIndex.h"
       
    37 #include "EPos_CPosLmActiveCompacter.h"
       
    38 #include "EPos_CPosLmLocalAccessSubsession.h"
       
    39 
       
    40 // -----------------------------------------------------------------------------
       
    41 // -----------------------------------------------------------------------------
       
    42 //
       
    43 CPosLmLocalAccessSubsession::CPosLmLocalAccessSubsession(
       
    44     CPosLmServer* aLmServer) :
       
    45     CPosLmSubsessionBase(EPosLocalAccessSubsession, aLmServer)
       
    46     {
       
    47     }
       
    48 
       
    49 // -----------------------------------------------------------------------------
       
    50 // -----------------------------------------------------------------------------
       
    51 //
       
    52 void CPosLmLocalAccessSubsession::ConstructL()
       
    53     {
       
    54     }
       
    55 
       
    56 // -----------------------------------------------------------------------------
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 CPosLmLocalAccessSubsession* CPosLmLocalAccessSubsession::NewLC(
       
    60     CPosLmServer* aLmServer)
       
    61     {
       
    62     CPosLmLocalAccessSubsession* self =
       
    63         new (ELeave) CPosLmLocalAccessSubsession(aLmServer);
       
    64     CleanupClosePushL(*self);
       
    65     self->ConstructL();
       
    66     return self;
       
    67     }
       
    68 
       
    69 // -----------------------------------------------------------------------------
       
    70 // -----------------------------------------------------------------------------
       
    71 //
       
    72 CPosLmLocalAccessSubsession::~CPosLmLocalAccessSubsession()
       
    73     {
       
    74     delete iCompacter;
       
    75     delete iDbAccess;
       
    76     delete iEventHandler;
       
    77 
       
    78     // release database
       
    79     iHasWriteLock = EFalse;
       
    80     iNoOfReadLocks = 0;
       
    81     if ( iUsingNameIndex && Server() && iDbUri )
       
    82         {
       
    83         Server()->IndexManager().RemoveIndexUser( *iDbUri );
       
    84         iUsingNameIndex = EFalse;
       
    85         }
       
    86     delete iDbUri;
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 TBool CPosLmLocalAccessSubsession::HasWriteLock( const TDesC& aUri )
       
    93     {
       
    94     if (iHasWriteLock && aUri == *iDbUri)
       
    95         {
       
    96         return ETrue;
       
    97         }
       
    98 
       
    99     return EFalse;
       
   100     }
       
   101 
       
   102 // -----------------------------------------------------------------------------
       
   103 // -----------------------------------------------------------------------------
       
   104 //
       
   105 TBool CPosLmLocalAccessSubsession::HasAnyLock( const TDesC& aUri ) 
       
   106     {
       
   107     if ((iHasWriteLock || iNoOfReadLocks > 0) && aUri == *iDbUri)
       
   108         {
       
   109         return ETrue;
       
   110         }
       
   111 
       
   112     return EFalse;
       
   113     }
       
   114 
       
   115 // -----------------------------------------------------------------------------
       
   116 // -----------------------------------------------------------------------------
       
   117 //
       
   118 void CPosLmLocalAccessSubsession::HandleOperationEventL(
       
   119     TPosLmEvent aEvent,
       
   120     const TDesC& aUri,
       
   121     TBool aCheckUri)
       
   122     {
       
   123     // Check if the event is dedicated to the database, which this subsession is
       
   124     // connected to.
       
   125     if (!aCheckUri && iEventHandler && iDbUri ||
       
   126         iEventHandler && iDbUri && aUri.Compare(*iDbUri) == 0)
       
   127         {
       
   128         iEventHandler->HandleIncomingEventL(aEvent);
       
   129         }
       
   130     }
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 // -----------------------------------------------------------------------------
       
   134 //
       
   135 void CPosLmLocalAccessSubsession::CompleteOutstandingEventRequest(
       
   136     TInt aError)
       
   137     {
       
   138     if (iEventHandler)
       
   139         {
       
   140         iEventHandler->CompleteAnyOutStandingRequest(aError);
       
   141         }
       
   142     }
       
   143 
       
   144 // -----------------------------------------------------------------------------
       
   145 // -----------------------------------------------------------------------------
       
   146 //
       
   147 void CPosLmLocalAccessSubsession::ReleaseCompactLock()
       
   148     {
       
   149     delete iCompacter;
       
   150     iCompacter = NULL;
       
   151     iHasWriteLock = EFalse;
       
   152     }
       
   153 
       
   154 // -----------------------------------------------------------------------------
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 void CPosLmLocalAccessSubsession::ServiceL(
       
   158     const RMessage2& aMessage)
       
   159     {
       
   160 #if 0 // #ifdef _DEBUG
       
   161     RThread client;
       
   162     aMessage.Client( client );
       
   163     LOG3("LocalSession::ServiceL in: function %d (client SID 0x%X, thread 0x%X)",
       
   164         aMessage.Function(), aMessage.SecureId().iId, client.Id() );
       
   165 #endif    
       
   166     
       
   167     switch (aMessage.Function())
       
   168         {
       
   169         case EPosLmServerRegisterSession:
       
   170             if (iDbUri)
       
   171                 {
       
   172                 PanicClient(aMessage, EPosClientHasAlreadyRegistered);
       
   173                 return;
       
   174                 }
       
   175             RegisterUriL(aMessage);
       
   176             break;
       
   177         case EPosLmServerInitializeSync:
       
   178         case EPosLmServerInitializeAsync:
       
   179         case EPosLmServerInitializeCancel:
       
   180         case EPosLmServerLangSwitchSync:
       
   181         case EPosLmServerLangSwitchAsync:
       
   182         case EPosLmServerLangSwitchCancel:
       
   183         case EPosLmServerRecoverSync:
       
   184         case EPosLmServerRecoverAsync:
       
   185         case EPosLmServerRecoverCancel:
       
   186             if (!iDbUri)
       
   187                 {
       
   188                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   189                 return;
       
   190                 }
       
   191             Server()->OperationManagerL(aMessage.Function())->AddRequestL(
       
   192                 aMessage, *iDbUri, this);
       
   193             break;
       
   194         case EPosLmServerDbLock:
       
   195             if (!iDbUri)
       
   196                 {
       
   197                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   198                 return;
       
   199                 }
       
   200             DatabaseLockL(aMessage);
       
   201             break;
       
   202         case EPosLmServerIndexTransaction:
       
   203             if (!iDbUri)
       
   204                 {
       
   205                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   206                 return;
       
   207                 }
       
   208             HandleDataTransactionL(aMessage);
       
   209             break;
       
   210         case EPosLmServerReportLmEvent:
       
   211             if (!iDbUri)
       
   212                 {
       
   213                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   214                 return;
       
   215                 }
       
   216             ForwardEventToAllSessionsL(aMessage);
       
   217             break;
       
   218         case EPosLmServerUpdateNameIndex:
       
   219             if (!iDbUri)
       
   220                 {
       
   221                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   222                 return;
       
   223                 }
       
   224             HandleUpdateLandmarkIndexL( aMessage );
       
   225             break;
       
   226         case EPosLmServerListenForLmEvent:
       
   227             // No check of iDbUri needed here
       
   228             User::LeaveIfError(Server()->StartSettingsListenerIfNeeded());
       
   229             if (!iEventHandler)
       
   230                 {
       
   231                 iEventHandler = CPosLmEventHandler::NewL();
       
   232                 }
       
   233             iEventHandler->HandleRequestForEventL(aMessage);
       
   234             break;
       
   235         case EPosLmServerCancelListenForLmEvent:
       
   236             // No check of iDbUri needed here
       
   237             delete iEventHandler;
       
   238             iEventHandler = NULL;
       
   239             LmServerGlobal::Complete(aMessage, KErrNone);
       
   240             break;
       
   241         case EPosLmServerCreateDefaultDb:
       
   242             // No check of iDbUri needed here
       
   243             CreateDefaultDatabaseL(aMessage);
       
   244             break;
       
   245         case EPosLmServerOpenNameIndex:
       
   246         case EPosLmServerCloseNameIndex:
       
   247             if ( !iDbUri )
       
   248                 {
       
   249                 PanicClient( aMessage, EPosClientHasNotRegistered );
       
   250                 return;
       
   251                 }
       
   252             HandleUseNameIndexL( aMessage );
       
   253             break;
       
   254         case EPosLmServerReadSortedIds:
       
   255             if (!iDbUri)
       
   256                 {
       
   257                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   258                 return;
       
   259                 }
       
   260             HandleReadSortedIdsL( aMessage );
       
   261             break;
       
   262         case EPosLmServerReadNameIndex:
       
   263             if (!iDbUri)
       
   264                 {
       
   265                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   266                 return;
       
   267                 }
       
   268             HandleReadSortedLandmarksL( aMessage );
       
   269             break;
       
   270         case EPosLmServerNameIndexStatus:
       
   271             if (!iDbUri)
       
   272                 {
       
   273                 PanicClient(aMessage, EPosClientHasNotRegistered);
       
   274                 return;
       
   275                 }
       
   276             HandleNameIndexStatusL( aMessage );
       
   277             break;
       
   278         default:
       
   279             User::Leave(KErrNotSupported);
       
   280             break;
       
   281         }
       
   282 #if 0 // #ifdef _DEBUG
       
   283     LOG("LocalSession::ServiceL out");
       
   284 #endif
       
   285     }
       
   286 
       
   287 // -----------------------------------------------------------------------------
       
   288 // -----------------------------------------------------------------------------
       
   289 //
       
   290 void CPosLmLocalAccessSubsession::RegisterUriL(
       
   291     const RMessage2& aMessage)
       
   292     {
       
   293     // Validate length of client message.
       
   294     TInt desLength = aMessage.GetDesLength(KPosLmServerUriArg);
       
   295     if (desLength < 0)
       
   296         {
       
   297         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   298         return;
       
   299         }
       
   300 
       
   301     // Read URI from client message.
       
   302     HBufC* dbUri = HBufC::NewLC(desLength);
       
   303     TPtr uriPtr = dbUri->Des();
       
   304     if (LmServerGlobal::Read(aMessage, KPosLmServerUriArg, uriPtr) != KErrNone)
       
   305         {
       
   306         CleanupStack::PopAndDestroy(dbUri);
       
   307         return;
       
   308         }
       
   309 
       
   310     // Lowercase the URI to be able to match different cases of the same URI.
       
   311     uriPtr.LowerCase();
       
   312 
       
   313     TInt err = PosLmDatabaseUtility::ValidateDatabaseUri(uriPtr);
       
   314     if (err == KErrArgument)
       
   315         {
       
   316         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   317         CleanupStack::PopAndDestroy(dbUri);
       
   318         return;
       
   319         }
       
   320     else
       
   321         {
       
   322         User::LeaveIfError(err);
       
   323         }
       
   324 
       
   325     // iDbUri is set last as it is used to validate if the uri has been
       
   326     // registered properly.
       
   327     CleanupStack::Pop(dbUri);
       
   328     iDbUri = dbUri;
       
   329     
       
   330     LmServerGlobal::Complete(aMessage, KErrNone);
       
   331     }
       
   332 
       
   333 // -----------------------------------------------------------------------------
       
   334 // -----------------------------------------------------------------------------
       
   335 //
       
   336 void CPosLmLocalAccessSubsession::DatabaseLockL(
       
   337     const RMessage2& aMessage)
       
   338     {
       
   339     TBool setLockOn = static_cast<TBool>(aMessage.Int0());
       
   340     TBool writeLock = static_cast<TBool>(aMessage.Int1());
       
   341 
       
   342     if (setLockOn)
       
   343         {
       
   344         if (!Server()->CanAcquireLock(writeLock, *iDbUri))
       
   345             {
       
   346             User::Leave(KErrLocked);
       
   347             }
       
   348 
       
   349         if (writeLock)
       
   350             {
       
   351             iHasWriteLock = ETrue;
       
   352             }
       
   353         else
       
   354             {
       
   355             iNoOfReadLocks++;
       
   356             }
       
   357         }
       
   358     else if (writeLock)
       
   359         {
       
   360         if (!iHasWriteLock)
       
   361             {
       
   362             PanicClient(aMessage, EPosLmDbNotLocked);
       
   363             return;
       
   364             }
       
   365         iHasWriteLock = EFalse;
       
   366         }
       
   367     else
       
   368         {
       
   369         if (iNoOfReadLocks == 0)
       
   370             {
       
   371             PanicClient(aMessage, EPosLmDbNotLocked);
       
   372             return;
       
   373             }
       
   374         iNoOfReadLocks--;
       
   375         }
       
   376 
       
   377     LmServerGlobal::Complete(aMessage, KErrNone);
       
   378 
       
   379     if (!setLockOn && writeLock) // releasing write lock
       
   380         {
       
   381         TRAP_IGNORE( CompactIfNeededL() );
       
   382         }
       
   383     }
       
   384 
       
   385 // -----------------------------------------------------------------------------
       
   386 // -----------------------------------------------------------------------------
       
   387 //
       
   388 void CPosLmLocalAccessSubsession::HandleDataTransactionL( const RMessage2& aMessage )
       
   389     {
       
   390     if ( Server()->IndexManager().Find( *iDbUri ) >= 0 )
       
   391         {
       
   392         CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
       
   393         User::LeaveIfError( index.Status() );
       
   394         switch( aMessage.Int0() )
       
   395             {
       
   396             case EPosLmServerTransactionStart:
       
   397                 index.StartTransaction();
       
   398                 break;
       
   399             case EPosLmServerTransactionCommit:
       
   400                 index.CommitTransaction();
       
   401                 break;
       
   402             case EPosLmServerTransactionRollback:
       
   403                 index.RollbackTransaction();
       
   404                 break;
       
   405             default:
       
   406                 PanicClient( aMessage, EPosUnableToReadOrWriteDataToClient );
       
   407             }
       
   408         }
       
   409 
       
   410     LmServerGlobal::Complete( aMessage, KErrNone );
       
   411     }
       
   412 
       
   413 // -----------------------------------------------------------------------------
       
   414 // -----------------------------------------------------------------------------
       
   415 //
       
   416 void CPosLmLocalAccessSubsession::ForwardEventToAllSessionsL(
       
   417     const RMessage2& aMessage)
       
   418     {
       
   419     TPckgBuf<TPosLmEvent> event;
       
   420 
       
   421     TInt desLength = aMessage.GetDesLength(KPosLmServerEventArg);
       
   422     if (desLength != event.Length())
       
   423         {
       
   424         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   425         return;
       
   426         }
       
   427 
       
   428     if (LmServerGlobal::Read(aMessage, KPosLmServerEventArg, event) != KErrNone)
       
   429         {
       
   430         return;
       
   431         }
       
   432 
       
   433     // Validate that the event type is a valid enum value.
       
   434     TPosLmEventType eventType = event().iEventType;
       
   435     if (!(eventType == EPosLmEventUnknownChanges ||
       
   436         eventType == EPosLmEventNewDefaultDatabaseLocation ||
       
   437         eventType == EPosLmEventMediaRemoved ||
       
   438         (eventType >= EPosLmEventLandmarkUnknownChanges &&
       
   439         eventType <= EPosLmEventLandmarkUpdated) ||
       
   440         (eventType >= EPosLmEventCategoryUnknownChanges &&
       
   441         eventType <= EPosLmEventCategoryUpdated)))
       
   442         {
       
   443         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   444         return;
       
   445         }
       
   446 
       
   447     Server()->ForwardEventToAllSessionsL(event(), *iDbUri, ETrue);
       
   448 
       
   449     LmServerGlobal::Complete(aMessage, KErrNone);
       
   450     }
       
   451 
       
   452 // -----------------------------------------------------------------------------
       
   453 // -----------------------------------------------------------------------------
       
   454 //
       
   455 void CPosLmLocalAccessSubsession::CreateDefaultDatabaseL(
       
   456     const RMessage2& aMessage)
       
   457     {
       
   458     TInt desLength = aMessage.GetDesLength(KPosLmServerUriArg);
       
   459     if (desLength < 0)
       
   460         {
       
   461         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   462         return;
       
   463         }
       
   464 
       
   465     HBufC* msgUri = HBufC::NewLC(desLength);
       
   466     TPtr uriPtr = msgUri->Des();
       
   467 
       
   468     if (LmServerGlobal::Read(aMessage, KPosLmServerUriArg, uriPtr) == KErrNone)
       
   469         {
       
   470         HBufC* uri = PosLmDatabaseUtility::CreateDatabaseUriL(*msgUri);
       
   471         CleanupStack::PushL(uri);
       
   472 
       
   473         // To remove a warning, the event must be default constructed.
       
   474         TPosLmDatabaseEvent event =
       
   475             {
       
   476             EPosLmDbDatabaseRegistered,
       
   477             {0,0,0,0,0,0,0,0}
       
   478             };
       
   479 
       
   480         CheckDiskSizeL(*uri);
       
   481         TPckgBuf<TBool> replaceDb;
       
   482 
       
   483         desLength = aMessage.GetDesLength(KPosLmServerDbReplaceArg);
       
   484         if (desLength != replaceDb.Length())
       
   485             {
       
   486             PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   487             CleanupStack::PopAndDestroy(2, msgUri);
       
   488             return;
       
   489             }
       
   490 
       
   491         if (LmServerGlobal::Read(
       
   492             aMessage, KPosLmServerDbReplaceArg, replaceDb) != KErrNone)
       
   493             {
       
   494             CleanupStack::PopAndDestroy(2, msgUri);
       
   495             return;
       
   496             }
       
   497 
       
   498         PosLmDatabaseManager::CreateDatabaseL(uri->Des(), ETrue, replaceDb());
       
   499 
       
   500         Server()->ForwardEventToAllSessionsL(event, uri->Des());
       
   501         LmServerGlobal::Complete(aMessage, KErrNone);
       
   502         CleanupStack::PopAndDestroy(uri);
       
   503         }
       
   504 
       
   505     CleanupStack::PopAndDestroy(msgUri);
       
   506     }
       
   507 
       
   508 // -----------------------------------------------------------------------------
       
   509 // -----------------------------------------------------------------------------
       
   510 //
       
   511 void CPosLmLocalAccessSubsession::CheckDiskSizeL(
       
   512     const TDesC& aUri)
       
   513     {
       
   514     CPosLmDiskUtilities* diskUtilities = CPosLmDiskUtilities::NewL();
       
   515     CleanupStack::PushL(diskUtilities);
       
   516 
       
   517     diskUtilities->DiskSpaceBelowCriticalLevelL(
       
   518         diskUtilities->EstimatedDiskSizeOfEmptyDatabase(),
       
   519         (aUri)[KPosLocalDbFileProtocol().Length()]);
       
   520 
       
   521     CleanupStack::PopAndDestroy(diskUtilities);
       
   522     }
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // -----------------------------------------------------------------------------
       
   526 //
       
   527 void CPosLmLocalAccessSubsession::CompactIfNeededL()
       
   528     {
       
   529     if (!iDbAccess)
       
   530         {
       
   531         CPosLmLocalDbAccess* dbAccess =
       
   532             CPosLmLocalDbAccess::NewL(CPosLmLocalDbAccess::EServerCompactLevel);
       
   533         CleanupStack::PushL(dbAccess);
       
   534         User::LeaveIfError(dbAccess->OpenDatabaseL(*iDbUri)); // Will be trapped
       
   535         CleanupStack::Pop(dbAccess);
       
   536         iDbAccess = dbAccess;
       
   537         }
       
   538 
       
   539     if (iDbAccess->IsCompactNeededL())
       
   540         {
       
   541         iCompacter = CPosLmActiveCompacter::NewL(*this, *iDbAccess);
       
   542         iHasWriteLock = ETrue;
       
   543         }
       
   544     }
       
   545 
       
   546 // -----------------------------------------------------------------------------
       
   547 // -----------------------------------------------------------------------------
       
   548 //
       
   549 void CPosLmLocalAccessSubsession::HandleReadSortedIdsL( const RMessage2& aMessage )
       
   550     {
       
   551     AssertIndexLoadedL();
       
   552 
       
   553     TPosLmServerReadArrayParam param;
       
   554     TPckg<TPosLmServerReadArrayParam> pack( param );
       
   555     if ( LmServerGlobal::Read( aMessage, KPosLmServerIdArrayParam, pack ) != KErrNone )
       
   556         {
       
   557         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   558         return;
       
   559         }
       
   560     
       
   561     CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
       
   562     User::LeaveIfError( index.Status() );
       
   563 
       
   564     TPosLmItemId* ids = new (ELeave) TPosLmItemId[ param.iCount ];
       
   565     CleanupStack::PushL( ids );
       
   566     TPtrC8 data( (TUint8*) ids, sizeof( TPosLmItemId ) * param.iCount );
       
   567 
       
   568     TInt count = index.GetSortedIds( param.iFirst, param.iCount, ids, param.iRemainder );
       
   569     if ( count >= 0 )
       
   570         {
       
   571         param.iActualCount = count;
       
   572         param.iMinBufferNeeded = 0;
       
   573         User::LeaveIfError( LmServerGlobal::Write( aMessage, KPosLmServerIdArrayParam, pack ) );
       
   574         User::LeaveIfError( LmServerGlobal::Write( aMessage, KPosLmServerIdArray, data ) );
       
   575         }
       
   576     else
       
   577         {
       
   578         User::Leave( count ); // error code
       
   579         }
       
   580     CleanupStack::PopAndDestroy( ids );
       
   581     LmServerGlobal::Complete( aMessage, count );
       
   582     }
       
   583 
       
   584 // -----------------------------------------------------------------------------
       
   585 // -----------------------------------------------------------------------------
       
   586 //
       
   587 void CPosLmLocalAccessSubsession::HandleReadSortedLandmarksL( const RMessage2& aMessage )
       
   588     {
       
   589     AssertIndexLoadedL();
       
   590 
       
   591     TPosLmServerReadArrayParam param;
       
   592     TPckg<TPosLmServerReadArrayParam> pack( param );
       
   593     if ( LmServerGlobal::Read( aMessage, 0, pack ) != KErrNone )
       
   594         {
       
   595         PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
       
   596         return;
       
   597         }
       
   598 
       
   599     param.iMinBufferNeeded = 0;
       
   600     param.iActualCount = 0;
       
   601     param.iRemainder = 0;
       
   602 
       
   603     TInt bufferSize = aMessage.GetDesLengthL( 1 );
       
   604     
       
   605     CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
       
   606     User::LeaveIfError( index.Status() );
       
   607 
       
   608     CBufFlat* buffer = CBufFlat::NewL( bufferSize );
       
   609     CleanupStack::PushL( buffer );
       
   610     
       
   611     RBufWriteStream out;
       
   612     out.Open( *buffer );
       
   613     CleanupClosePushL( out );
       
   614 
       
   615     if ( param.iCount > 0 ) // in ascending order
       
   616         {
       
   617         GetSortedLandmarksL( index, out, param, bufferSize );
       
   618         }
       
   619     else
       
   620         {
       
   621         GetSortedLandmarksReverseL( index, out, param, bufferSize );
       
   622         }
       
   623     
       
   624     out.CommitL();
       
   625     
       
   626     User::LeaveIfError( LmServerGlobal::Write( aMessage, 0, pack ) );
       
   627     User::LeaveIfError( LmServerGlobal::Write( aMessage, 1, buffer->Ptr( 0 ) ) );
       
   628     LmServerGlobal::Complete( aMessage, KErrNone );
       
   629 
       
   630     CleanupStack::PopAndDestroy( &out );
       
   631     CleanupStack::PopAndDestroy( buffer );
       
   632     }
       
   633 
       
   634 // -----------------------------------------------------------------------------
       
   635 // -----------------------------------------------------------------------------
       
   636 //
       
   637 void CPosLmLocalAccessSubsession::GetSortedLandmarksL( 
       
   638     CPosLmNameIndex& aNameIndex,
       
   639     RWriteStream& aOut,
       
   640     TPosLmServerReadArrayParam& aParam,
       
   641     TInt aMaxSize )
       
   642     {
       
   643     TInt start = Max( aParam.iFirst, 0 );
       
   644     TInt last = Min( aParam.iFirst + aParam.iCount, aNameIndex.Count() );
       
   645 
       
   646     TInt leftInBuffer = aMaxSize;
       
   647     TInt i = start;
       
   648     for ( ; i < last ; i++ ) 
       
   649         {
       
   650         const CPosLmNameIndex::CItem& item = aNameIndex.Item( i );
       
   651         if ( !ExportIndexItemL( item, aOut, leftInBuffer, aParam ) )
       
   652             break;
       
   653         }
       
   654 
       
   655     aParam.iRemainder = aNameIndex.Count() - i;
       
   656     }
       
   657 
       
   658 // -----------------------------------------------------------------------------
       
   659 // -----------------------------------------------------------------------------
       
   660 //
       
   661 void CPosLmLocalAccessSubsession::GetSortedLandmarksReverseL( 
       
   662     CPosLmNameIndex& aNameIndex,
       
   663     RWriteStream& aOut,
       
   664     TPosLmServerReadArrayParam& aParam,
       
   665     TInt aMaxSize )
       
   666     {
       
   667     TInt start = Min( aParam.iFirst, aNameIndex.Count() - 1 );
       
   668     TInt last = Max( aParam.iFirst + aParam.iCount, -1 ); // iCount is negative
       
   669 
       
   670     TInt leftInBuffer = aMaxSize;
       
   671     TInt i = start;
       
   672     for ( ; i > last ; i-- ) 
       
   673         {
       
   674         const CPosLmNameIndex::CItem& item = aNameIndex.Item( i );
       
   675         if ( !ExportIndexItemL( item, aOut, leftInBuffer, aParam ) )
       
   676             break;
       
   677         }
       
   678 
       
   679     aParam.iRemainder = i+1;
       
   680     }
       
   681 
       
   682 // -----------------------------------------------------------------------------
       
   683 // -----------------------------------------------------------------------------
       
   684 //
       
   685 TBool CPosLmLocalAccessSubsession::ExportIndexItemL( 
       
   686     const CPosLmNameIndex::CItem& aItem,
       
   687     RWriteStream& aOut,
       
   688     TInt& aLeftInBuffer,
       
   689     TPosLmServerReadArrayParam& aParam )
       
   690     {
       
   691     TInt itemSize = aItem.Size();
       
   692     if ( itemSize <= aLeftInBuffer )
       
   693         {
       
   694         aItem.ExternalizeL( aOut );
       
   695         aLeftInBuffer -= itemSize;
       
   696         aParam.iActualCount++;
       
   697         return ETrue;
       
   698         }
       
   699     else 
       
   700         { 
       
   701         if ( itemSize > aLeftInBuffer )
       
   702             {
       
   703             aParam.iMinBufferNeeded = itemSize;
       
   704             }
       
   705         return EFalse;
       
   706         }
       
   707     }
       
   708 
       
   709 // -----------------------------------------------------------------------------
       
   710 // -----------------------------------------------------------------------------
       
   711 //
       
   712 void CPosLmLocalAccessSubsession::HandleUpdateLandmarkIndexL( const RMessage2& aMessage )
       
   713     {
       
   714     //LOG1("UpdateIndex: function %d", aMessage.Int0() );
       
   715     AssertIndexLoadedL();
       
   716     switch ( aMessage.Int0() )
       
   717         {
       
   718         case EPosLmServerAddLandmarks:
       
   719         case EPosLmServerUpdateLandmarks:
       
   720             HandleLandmarksAddedOrUpdatedL( aMessage );
       
   721             break;
       
   722         case EPosLmServerRemoveLandmarks:
       
   723             HandleLandmarksRemovedL( aMessage );
       
   724             break;
       
   725         default:
       
   726             break;
       
   727         }
       
   728     }
       
   729 
       
   730 // -----------------------------------------------------------------------------
       
   731 // -----------------------------------------------------------------------------
       
   732 //
       
   733 void CPosLmLocalAccessSubsession::HandleLandmarksAddedOrUpdatedL( const RMessage2& aMessage )
       
   734     {
       
   735     CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
       
   736     User::LeaveIfError( index.Status() );
       
   737 
       
   738     HBufC8* buf = LmServerGlobal::CopyClientBuffer8LC( aMessage, 1 );
       
   739     RDesReadStream readStream( *buf );
       
   740 
       
   741     TPosLmItemId id = KPosLmNullItemId;
       
   742 
       
   743     // Update index
       
   744     TInt lmCount = readStream.ReadInt32L();
       
   745     for ( TInt i = 0; i < lmCount; i++ )
       
   746         {
       
   747         id = readStream.ReadInt32L();
       
   748         TInt nameLen = readStream.ReadInt32L();
       
   749         
       
   750         HBufC* lmBuf = HBufC::NewLC( nameLen );
       
   751         
       
   752         TPtr name( lmBuf->Des() );
       
   753         readStream.ReadL( name, nameLen );
       
   754         
       
   755         if ( aMessage.Int0() == EPosLmServerUpdateLandmarks ) 
       
   756             {
       
   757             index.UpdateL( id, lmBuf );
       
   758             }
       
   759         else
       
   760             {
       
   761             index.InsertL( id, lmBuf );
       
   762             }
       
   763         CleanupStack::Pop( lmBuf );
       
   764         }
       
   765     
       
   766     readStream.Close();
       
   767     CleanupStack::PopAndDestroy( buf );
       
   768 
       
   769     LmServerGlobal::Complete( aMessage, KErrNone );
       
   770     }
       
   771 
       
   772 // -----------------------------------------------------------------------------
       
   773 // -----------------------------------------------------------------------------
       
   774 //
       
   775 void CPosLmLocalAccessSubsession::HandleLandmarksRemovedL( const RMessage2& aMessage )
       
   776     {
       
   777     HBufC8* buf = LmServerGlobal::CopyClientBuffer8LC( aMessage, 1 );
       
   778     if ( buf->Size() % ( sizeof( TPosLmItemId ) ) != 0 )
       
   779         {
       
   780         User::Leave( KErrArgument );
       
   781         }
       
   782 
       
   783     TInt lmCount = buf->Size() / ( sizeof( TPosLmItemId ) );
       
   784     const TPosLmItemId* ids = reinterpret_cast<const TPosLmItemId*>( buf->Ptr() );
       
   785 
       
   786     // Update index
       
   787     CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
       
   788     User::LeaveIfError( index.Status() );
       
   789     for ( TInt i = 0; i < lmCount; i++ )
       
   790         {
       
   791         index.Remove( ids[i] );
       
   792         }
       
   793     CleanupStack::PopAndDestroy( buf );
       
   794     
       
   795     LmServerGlobal::Complete( aMessage, KErrNone );
       
   796     }
       
   797 
       
   798 // -----------------------------------------------------------------------------
       
   799 // -----------------------------------------------------------------------------
       
   800 //
       
   801 void CPosLmLocalAccessSubsession::HandleNameIndexStatusL( const RMessage2& aMessage )
       
   802     {
       
   803     AssertIndexLoadedL();
       
   804     CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri );
       
   805     TInt status = index.Status();
       
   806     if ( status < 0 )
       
   807         LmServerGlobal::Complete( aMessage, status );
       
   808     else
       
   809         LmServerGlobal::Complete( aMessage, index.Count() );
       
   810     }
       
   811 
       
   812 // -----------------------------------------------------------------------------
       
   813 // -----------------------------------------------------------------------------
       
   814 //
       
   815 void CPosLmLocalAccessSubsession::HandleUseNameIndexL(
       
   816     const RMessage2& aMessage )
       
   817     {
       
   818     switch ( aMessage.Function() )
       
   819         {
       
   820         case EPosLmServerOpenNameIndex:
       
   821             {
       
   822             if ( iUsingNameIndex )
       
   823                 {
       
   824                 PanicClient( aMessage, EPosClientHasAlreadyRegistered );
       
   825                 return;
       
   826                 }
       
   827             // Register new user of lm index
       
   828             Server()->IndexManager().AddIndexUserL( *iDbUri );
       
   829             iUsingNameIndex = ETrue;
       
   830             break;
       
   831             }
       
   832         case EPosLmServerCloseNameIndex:
       
   833             {
       
   834             if ( !iUsingNameIndex )
       
   835                 {
       
   836                 PanicClient( aMessage, EPosClientHasNotRegistered );
       
   837                 return;
       
   838                 }
       
   839             Server()->IndexManager().RemoveIndexUser( *iDbUri );
       
   840             iUsingNameIndex = EFalse;
       
   841             break;
       
   842             }
       
   843         default:
       
   844             break;
       
   845         }
       
   846     LmServerGlobal::Complete( aMessage, KErrNone );
       
   847     }
       
   848 
       
   849 // -----------------------------------------------------------------------------
       
   850 // -----------------------------------------------------------------------------
       
   851 //
       
   852 void CPosLmLocalAccessSubsession::AssertIndexLoadedL()
       
   853     {
       
   854     if ( Server()->IndexManager().Find( *iDbUri ) < 0 )
       
   855         {
       
   856         User::Leave( KErrNotFound );
       
   857         }
       
   858     }