landmarks/locationlandmarks/server/src/EPos_CPosLmNameIndex.cpp
changeset 0 667063e416a2
child 8 6fcbaa43369c
equal deleted inserted replaced
-1:000000000000 0:667063e416a2
       
     1 /*
       
     2 * Copyright (c) 2007 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: Implementation of CPosLmNameIndex class
       
    15 *
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <e32base.h>
       
    21 #include <d32dbms.h>
       
    22 #include <EPos_Landmarks.h>
       
    23 #include <EPos_CPosLandmark.h>
       
    24 #include <epos_cposlmlocaldbaccess.h>
       
    25 #include <epos_landmarkdatabasestructure.h>
       
    26 #include <epos_poslmlandmarkhandler.h>
       
    27 #include <epos_cposlmdiskutilities.h>
       
    28 #include <epos_poslmserverutility.h>
       
    29 #include <epos_poslmlongtextcolhandler.h>
       
    30 
       
    31 #include "EPos_PosLmDatabaseManager.h"
       
    32 #include "epos_lmdebug.h"
       
    33 #include "EPos_CPosLmNameIndex.h"
       
    34 
       
    35 // ============================ LOCAL FUNCTIONS ===============================
       
    36 
       
    37 // ============================ MEMBER FUNCTIONS ===============================
       
    38 
       
    39 //--------------------------------------------------------------------
       
    40 // CLmNameIndex::CIndexItem
       
    41 //--------------------------------------------------------------------
       
    42 //
       
    43 CPosLmNameIndex::CIndexItem::CIndexItem()
       
    44 : iId ( KPosLmNullItemId )
       
    45     {
       
    46     }
       
    47 
       
    48 CPosLmNameIndex::CIndexItem::CIndexItem( TPosLmItemId aId )
       
    49 : iId ( aId )
       
    50     {
       
    51     }
       
    52 
       
    53 CPosLmNameIndex::CIndexItem::CIndexItem( TPosLmItemId aId, HBufC* aName )
       
    54 : iId ( aId ), iName( aName )
       
    55     {
       
    56     }
       
    57 
       
    58 CPosLmNameIndex::CIndexItem::~CIndexItem()
       
    59     {
       
    60     delete iName;
       
    61     }
       
    62 
       
    63 CPosLmNameIndex::CIndexItem* CPosLmNameIndex::CIndexItem::NewLC( TPosLmItemId aId, const TDesC& aName )
       
    64     {
       
    65     CIndexItem* self = new (ELeave) CIndexItem( aId );
       
    66     CleanupStack::PushL( self );
       
    67     self->iName = aName.AllocL();
       
    68     return self;
       
    69     }
       
    70 
       
    71 CPosLmNameIndex::CIndexItem* CPosLmNameIndex::CIndexItem::NewLC( RReadStream& aIn )
       
    72     {
       
    73     TPosLmItemId id = aIn.ReadUint32L();
       
    74     TInt len = aIn.ReadUint32L();
       
    75     if ( id < 1 || len < 0 ) User::Leave( KErrCorrupt );
       
    76     
       
    77     HBufC* name = HBufC::NewLC( len );
       
    78     TPtr ptr = name->Des();
       
    79     aIn.ReadL( ptr, len );
       
    80     
       
    81     CIndexItem* self = new (ELeave) CIndexItem( id, name );
       
    82     CleanupStack::Pop( name );
       
    83     
       
    84     CleanupStack::PushL( self );
       
    85     return self;
       
    86     }
       
    87 
       
    88 TPtrC CPosLmNameIndex::CIndexItem::Name() const
       
    89     {
       
    90     if ( iName )
       
    91         return *iName;
       
    92     else
       
    93         return KNullDesC();
       
    94     }
       
    95 
       
    96 void CPosLmNameIndex::CIndexItem::ExternalizeL( RWriteStream& aOut ) const
       
    97     {
       
    98     aOut.WriteUint32L( iId );
       
    99     aOut.WriteUint32L( Name().Length() );
       
   100     aOut.WriteL( Name() );
       
   101     // state is not stored, it is used only for index verification
       
   102     }
       
   103 
       
   104 TInt CPosLmNameIndex::CIndexItem::Size() const
       
   105     {
       
   106     return 
       
   107         sizeof( TUint32 )       // id size
       
   108         + sizeof( TUint32 )     // string length size
       
   109         + Name().Size();        // string size
       
   110     }
       
   111 
       
   112 TInt CPosLmNameIndex::CIndexItem::CompareById( const CIndexItem& aLeft, const CIndexItem& aRight )
       
   113     {
       
   114     return aLeft.Id() - aRight.Id();
       
   115     }
       
   116 
       
   117 //--------------------------------------------------------------------
       
   118 // CPosLmNameIndex::TLmIndexNameKey
       
   119 //--------------------------------------------------------------------
       
   120 //
       
   121 CPosLmNameIndex::TLmIndexNameKey::TLmIndexNameKey() :
       
   122     TKeyArrayFix( 0, ECmpCollated )
       
   123     {
       
   124     // the second parameter - comparison type - is used
       
   125     // by TKeyArrayFix::Compare()
       
   126     // the first parameter - offset of the key - is not used: 
       
   127     // overridden At() returns pointer to key not using offsets
       
   128     }
       
   129 
       
   130 TAny* CPosLmNameIndex::TLmIndexNameKey::At( TInt anIndex ) const
       
   131     {
       
   132     TAny* any = TKeyArrayFix::At( anIndex );
       
   133     CIndexItem** ptr = static_cast<CIndexItem**>( any );
       
   134     return (*ptr)->NamePtr();
       
   135     }
       
   136 
       
   137 //--------------------------------------------------------------------
       
   138 // CPosLmNameIndex::TLmIndexIdKey
       
   139 //--------------------------------------------------------------------
       
   140 //
       
   141 CPosLmNameIndex::TLmIndexIdKey::TLmIndexIdKey() :
       
   142     TKeyArrayFix( 0, ECmpTUint32 )
       
   143     {
       
   144     }
       
   145 
       
   146 TAny* CPosLmNameIndex::TLmIndexIdKey::At( TInt anIndex ) const
       
   147     {
       
   148     TAny* any = TKeyArrayFix::At( anIndex );
       
   149     CIndexItem** ptr = static_cast<CIndexItem**>( any );
       
   150     return (*ptr)->IdPtr();
       
   151     }
       
   152 
       
   153 //--------------------------------------------------------------------
       
   154 // CPosLmNameIndex
       
   155 //--------------------------------------------------------------------
       
   156 //
       
   157 
       
   158 //--------------------------------------------------------------------
       
   159 //--------------------------------------------------------------------
       
   160 //
       
   161 CPosLmNameIndex::CPosLmNameIndex( CPosLmLocalDbAccess& aDbAccess )
       
   162 :   iDbAccess( aDbAccess ), iStatus( KErrNotReady )
       
   163     {
       
   164     }
       
   165 
       
   166 //--------------------------------------------------------------------
       
   167 //--------------------------------------------------------------------
       
   168 //
       
   169 CPosLmNameIndex::~CPosLmNameIndex()
       
   170     {
       
   171     Reset();
       
   172     delete iArray;
       
   173     delete iKeyItem;
       
   174     }
       
   175 
       
   176 //--------------------------------------------------------------------
       
   177 //--------------------------------------------------------------------
       
   178 //
       
   179 void CPosLmNameIndex::Reset()
       
   180     {
       
   181     StopEvaluation();
       
   182     iArray->ResetAndDestroy();
       
   183     iDataSize = 0;
       
   184     iStatus = KErrNotReady;
       
   185     }
       
   186 
       
   187 //--------------------------------------------------------------------
       
   188 //--------------------------------------------------------------------
       
   189 //
       
   190 CPosLmNameIndex* CPosLmNameIndex::NewL( CPosLmLocalDbAccess& aDbAccess )
       
   191     {
       
   192     CPosLmNameIndex* self = NewLC( aDbAccess );
       
   193     CleanupStack::Pop( self );
       
   194     return self;
       
   195     }
       
   196 
       
   197 //--------------------------------------------------------------------
       
   198 //--------------------------------------------------------------------
       
   199 //
       
   200 CPosLmNameIndex* CPosLmNameIndex::NewLC( CPosLmLocalDbAccess& aDbAccess )
       
   201     {   
       
   202     CPosLmNameIndex* self = new (ELeave) CPosLmNameIndex( aDbAccess );
       
   203     CleanupStack::PushL( self );
       
   204     self->ConstructL();
       
   205     return self;
       
   206     }
       
   207 
       
   208 //--------------------------------------------------------------------
       
   209 //--------------------------------------------------------------------
       
   210 //
       
   211 void CPosLmNameIndex::ConstructL()
       
   212     {
       
   213     const TInt KGranularity = 100;
       
   214     iArray = new (ELeave) CArrayPtrSeg<CIndexItem>( KGranularity );
       
   215     iKeyItem = new (ELeave) CIndexItem;
       
   216     
       
   217     iDbAccess.GetDatabase( iDatabase );
       
   218 
       
   219     iTimeStamp.UniversalTime();
       
   220     TRAPD( err, LoadL() );
       
   221     if ( err )
       
   222         {
       
   223         // need to re-generate index
       
   224         iStatus = KErrNotReady;
       
   225         }
       
   226     else
       
   227     	{
       
   228     	//if no need to re-generate then set all the landmarks to valid state
       
   229     	for(int i =0; i < iArray->Count(); i++)
       
   230     	{
       
   231     		CIndexItem *item = iArray->At(i);
       
   232     		item->SetValid();
       
   233     	}
       
   234     	iStatus = KErrNone;
       
   235     	}
       
   236     }
       
   237 
       
   238 //--------------------------------------------------------------------
       
   239 //--------------------------------------------------------------------
       
   240 //
       
   241 TReal32 CPosLmNameIndex::Evaluate()
       
   242     {
       
   243     TReal32 progress = 1.0;
       
   244     if ( iStatus )
       
   245         {
       
   246         TRAPD( err, DoEvaluateL( progress ) );
       
   247         if ( err )
       
   248             {
       
   249             StopEvaluation();
       
   250             iStatus = err;
       
   251             }
       
   252         else if ( progress == 1.0 ) // evaluation completed
       
   253             {
       
   254             StopEvaluation();
       
   255             iStatus = KErrNone;
       
   256             }
       
   257         }
       
   258     return progress;
       
   259     }
       
   260 
       
   261 //--------------------------------------------------------------------
       
   262 //--------------------------------------------------------------------
       
   263 //
       
   264 void CPosLmNameIndex::StopEvaluation()
       
   265 	{
       
   266 	if ( iIsTableOpen )
       
   267 		{
       
   268 	    iTable.Close();
       
   269 	    iIsTableOpen = EFalse;
       
   270 		}
       
   271     iIdSortedArray.Reset();
       
   272     RemoveInvalidItems();
       
   273 	}
       
   274 
       
   275 //--------------------------------------------------------------------
       
   276 //--------------------------------------------------------------------
       
   277 //
       
   278 void CPosLmNameIndex::DoEvaluateL( TReal32& aProgress )
       
   279     {
       
   280     const TInt KRowsPerStep( 100 );
       
   281 
       
   282     if ( !iIsTableOpen )
       
   283     	{
       
   284         TInt err = iTable.Open( iDatabase, KPosLmLandmarkTable, RDbRowSet::EReadOnly );
       
   285         User::LeaveIfError( err );
       
   286         iIsTableOpen = ETrue;
       
   287 
       
   288         if ( iTable.FirstL() )
       
   289             {
       
   290             //   Reset(); 
       
   291             // Don't reset what's loaded - try to check the index with
       
   292             // contents of the database and update accordingly. 
       
   293             // Reason: if changes are small (most probable case) this job 
       
   294             // is faster than rebuilding new index from scratch
       
   295             CreateByIdSortingL();
       
   296             iTablePosition = 0;
       
   297             iStatus = KErrNotReady;
       
   298             }
       
   299         else
       
   300             {
       
   301             // no records in the table
       
   302     	    iTable.Close();
       
   303     	    iIsTableOpen = EFalse;
       
   304             aProgress = 1.0;
       
   305             return;
       
   306             }
       
   307     	}
       
   308     
       
   309     TInt numRows = KRowsPerStep;
       
   310     while( !iTable.AtEnd() && numRows-- > 0 )
       
   311         {
       
   312         iTable.GetL();
       
   313 
       
   314         TPosLmItemId id = iTable.ColUint32( EPosLmLcLandmarkIdCol );
       
   315 
       
   316         HBufC* name = PosLmServerUtility::ReadFromLongTextColumnLC( 
       
   317         	iTable, EPosLmLcNameCol );
       
   318 
       
   319         // If the item already exists in the index, mark it as verified
       
   320         // otherwise - add to index
       
   321         CIndexItem* item = ItemById( id );
       
   322         // when comparing contents of the index with database
       
   323         // it is ok to use binary comparison 
       
   324         if ( !item || item->Name().Compare( *name ) != 0 ) 
       
   325             {
       
   326             // the ID has been removed or changed in database
       
   327             if ( item )
       
   328                 {
       
   329                 // the original item has been changed
       
   330                 item->SetInvalid();
       
   331                 }
       
   332             // add new item for this ID
       
   333             // here comparison must be done using collation
       
   334             CIndexItem* newItem = DoInsertL( id, name ); // takes onwership of name
       
   335             newItem->SetValid();
       
   336             
       
   337             TLinearOrder<CIndexItem> order( CIndexItem::CompareById );
       
   338             iIdSortedArray.InsertInOrder( newItem, order );
       
   339             CleanupStack::Pop( name );
       
   340             }
       
   341         else
       
   342             {
       
   343             // this item already exists in the index
       
   344             item->SetValid();
       
   345             CleanupStack::PopAndDestroy( name );
       
   346             }
       
   347 
       
   348         iTable.NextL();
       
   349         iTablePosition++;
       
   350         }
       
   351     
       
   352     // return progress;
       
   353     TInt count = iTable.CountL();
       
   354     if ( count > 0 )
       
   355         {
       
   356         aProgress = TReal32( iTablePosition ) / TReal32( count );
       
   357         }
       
   358     else
       
   359         {
       
   360         aProgress = 1.0;
       
   361         }
       
   362     }
       
   363 
       
   364 //--------------------------------------------------------------------
       
   365 //--------------------------------------------------------------------
       
   366 //
       
   367 CArrayFixSeg<TPosLmItemId>* CPosLmNameIndex::GetSortedIdsLC() const
       
   368     {
       
   369     return GetSortedIdsLC( 0, Count() );
       
   370     }
       
   371 
       
   372 //--------------------------------------------------------------------
       
   373 //--------------------------------------------------------------------
       
   374 //
       
   375 CArrayFixSeg<TPosLmItemId>* CPosLmNameIndex::GetSortedIdsLC( TInt aFirst, TInt aCount ) const
       
   376     {
       
   377     if ( iStatus == KErrNone )
       
   378         {
       
   379         const TInt KGranularity( 512 );
       
   380         CArrayFixSeg<TPosLmItemId>* array = new (ELeave) CArrayFixSeg<TPosLmItemId>( KGranularity );
       
   381         CleanupStack::PushL( array );
       
   382         TInt first = Max( 0, aFirst );
       
   383         TInt last = Min( first + aCount, iArray->Count() );
       
   384         for ( TInt i = first; i < last; i++ )
       
   385             {
       
   386             CIndexItem* item = iArray->At(i);
       
   387             array->AppendL( item->Id() );
       
   388             }
       
   389         return array;
       
   390         }
       
   391     else
       
   392         {
       
   393         User::Leave( iStatus );
       
   394         return NULL;
       
   395         }
       
   396     }
       
   397 
       
   398 //--------------------------------------------------------------------
       
   399 //--------------------------------------------------------------------
       
   400 //
       
   401 TInt CPosLmNameIndex::GetSortedIds( 
       
   402     TInt aFirst, TInt aCount, 
       
   403     TPosLmItemId* aTarget, TInt& aReminder ) const
       
   404     {
       
   405     if ( aFirst < 0 || aCount < 0 || aTarget == NULL )
       
   406         return KErrArgument;
       
   407     
       
   408     if ( iStatus == KErrNone )
       
   409         {
       
   410         TInt first = Min( Max( aFirst, 0 ), iArray->Count() );
       
   411         TInt last = Max( 0, Min( aFirst + aCount, iArray->Count() ) );
       
   412         for ( TInt i = first; i < last; i++ )
       
   413             {
       
   414             CIndexItem* item = iArray->At( i );
       
   415             *(aTarget + i-first ) = item->Id();
       
   416             }
       
   417         aReminder = Count() - last;
       
   418         return last - first;
       
   419         }
       
   420     else
       
   421         {
       
   422         return iStatus;
       
   423         }
       
   424     }
       
   425 
       
   426 //--------------------------------------------------------------------
       
   427 //--------------------------------------------------------------------
       
   428 //
       
   429 void CPosLmNameIndex::InsertL( const CPosLandmark& aLandmark )
       
   430     {
       
   431     TPtrC name;
       
   432     aLandmark.GetLandmarkName( name );
       
   433     InsertL( aLandmark.LandmarkId(), name );
       
   434     }
       
   435 
       
   436 //--------------------------------------------------------------------
       
   437 //--------------------------------------------------------------------
       
   438 //
       
   439 void CPosLmNameIndex::InsertL( TPosLmItemId aLmid, const TDesC& aName )
       
   440     {
       
   441     HBufC* name = aName.AllocLC();
       
   442     InsertL( aLmid, name );
       
   443     CleanupStack::Pop( name );
       
   444     }
       
   445 
       
   446 //--------------------------------------------------------------------
       
   447 //--------------------------------------------------------------------
       
   448 //
       
   449 void CPosLmNameIndex::InsertL( TPosLmItemId aLmid, HBufC* aName )
       
   450     {
       
   451     DoInsertL( aLmid, aName );
       
   452     }
       
   453 
       
   454 //--------------------------------------------------------------------
       
   455 //--------------------------------------------------------------------
       
   456 //
       
   457 CPosLmNameIndex::CIndexItem* CPosLmNameIndex::DoInsertL( TPosLmItemId aLmid, HBufC* aName )
       
   458     {
       
   459     if ( Find( aLmid ) >= 0 ) // finds valid item
       
   460         {
       
   461         User::Leave( KErrAlreadyExists ); // duplicate ID found
       
   462         }
       
   463     
       
   464     CIndexItem* landmark = new (ELeave) CIndexItem( aLmid, aName ); // takes ownership of aName
       
   465     CleanupStack::PushL( landmark );
       
   466     
       
   467     TLmIndexNameKey key;
       
   468     iArray->InsertIsqAllowDuplicatesL( landmark, key );
       
   469 
       
   470     CleanupStack::Pop( landmark );
       
   471     iDataSize += landmark->Size();
       
   472     
       
   473     if ( !iInTransaction )
       
   474         {
       
   475         landmark->SetValid();
       
   476         }
       
   477     // otherwise item remains in Temp state
       
   478     
       
   479     return landmark;
       
   480     }
       
   481 
       
   482 //--------------------------------------------------------------------
       
   483 //--------------------------------------------------------------------
       
   484 //
       
   485 void CPosLmNameIndex::AppendL( TPosLmItemId aLmid, HBufC* aName )
       
   486     {
       
   487     CIndexItem* landmark = new (ELeave) CIndexItem( aLmid, aName );
       
   488     CleanupStack::PushL( landmark );
       
   489     AppendL( landmark );
       
   490     CleanupStack::Pop( landmark );
       
   491     }
       
   492 
       
   493 //--------------------------------------------------------------------
       
   494 //--------------------------------------------------------------------
       
   495 //
       
   496 void CPosLmNameIndex::AppendL( CIndexItem* aLandmark )
       
   497     {
       
   498     ASSERT( aLandmark );
       
   499     iArray->AppendL( aLandmark );
       
   500     iDataSize += aLandmark->Size();
       
   501     }
       
   502 
       
   503 //--------------------------------------------------------------------
       
   504 //--------------------------------------------------------------------
       
   505 //
       
   506 void CPosLmNameIndex::Remove( TPosLmItemId aLmid )
       
   507     {
       
   508     TInt index = Find( aLmid );
       
   509     if ( index >= 0 )
       
   510         {
       
   511         DoRemove( index );
       
   512         }
       
   513     }
       
   514 
       
   515 //--------------------------------------------------------------------
       
   516 //--------------------------------------------------------------------
       
   517 //
       
   518 void CPosLmNameIndex::DoRemove( TInt aIndex )
       
   519     {
       
   520     ASSERT( aIndex >= 0 && aIndex < iArray->Count() );
       
   521 
       
   522     CIndexItem* entry = iArray->At( aIndex );
       
   523     if ( !iInTransaction )
       
   524         {
       
   525         iDataSize -= entry->Size();
       
   526         ASSERT( iDataSize >= 0 );
       
   527         delete entry;
       
   528         iArray->Delete( aIndex );
       
   529         }
       
   530     else
       
   531         {
       
   532         entry->SetInvalid();
       
   533         }
       
   534     }
       
   535 
       
   536 //--------------------------------------------------------------------
       
   537 //--------------------------------------------------------------------
       
   538 //
       
   539 void CPosLmNameIndex::UpdateL( TPosLmItemId aId, const TDesC& aName )
       
   540     {
       
   541     HBufC* name = aName.AllocLC();
       
   542     UpdateL( aId, name );
       
   543     CleanupStack::Pop( name );
       
   544     }
       
   545 
       
   546 //--------------------------------------------------------------------
       
   547 //--------------------------------------------------------------------
       
   548 //
       
   549 void CPosLmNameIndex::UpdateL( TPosLmItemId aLmid, HBufC* aName )
       
   550     {
       
   551     TInt index = Find( aLmid );
       
   552     if ( index >= 0 )
       
   553         {
       
   554         CIndexItem* entry = iArray->At( index );
       
   555         // if name is exactly same, no need to change anything
       
   556         if ( entry->Name().Compare( *aName ) != 0 )
       
   557             {
       
   558             DoRemove( index );
       
   559             InsertL( aLmid, aName );
       
   560             }
       
   561         else
       
   562             {
       
   563             delete aName;
       
   564             }
       
   565         }
       
   566     else
       
   567         {
       
   568         delete aName;
       
   569         }
       
   570     }
       
   571 
       
   572 //--------------------------------------------------------------------
       
   573 //--------------------------------------------------------------------
       
   574 //
       
   575 TInt CPosLmNameIndex::Find( TPosLmItemId aLmid ) const
       
   576     {
       
   577     for ( TInt i = 0; i < iArray->Count(); i++ )
       
   578         {
       
   579         CIndexItem* entry = iArray->At(i);
       
   580         if ( entry->Id() == aLmid && entry->IsValid() )
       
   581             {
       
   582             return i;
       
   583             }
       
   584         }
       
   585     return KErrNotFound;
       
   586     }
       
   587 
       
   588 //--------------------------------------------------------------------
       
   589 //--------------------------------------------------------------------
       
   590 //
       
   591 TInt CPosLmNameIndex::Count() const
       
   592     {
       
   593     return iArray->Count();
       
   594     }
       
   595 
       
   596 //--------------------------------------------------------------------
       
   597 //--------------------------------------------------------------------
       
   598 //
       
   599 TInt CPosLmNameIndex::DataSize() const
       
   600     {
       
   601     return 
       
   602         sizeof( TUint32 )       // total amount of items
       
   603         + iDataSize;
       
   604     }
       
   605 
       
   606 //--------------------------------------------------------------------
       
   607 //--------------------------------------------------------------------
       
   608 //
       
   609 const CPosLmNameIndex::CItem& CPosLmNameIndex::Item( TInt aIndex ) const
       
   610     {
       
   611     return *( iArray->At( aIndex ) );
       
   612     }
       
   613 
       
   614 //--------------------------------------------------------------------
       
   615 //--------------------------------------------------------------------
       
   616 //
       
   617 void CPosLmNameIndex::ExternalizeL( RWriteStream& aOut ) const
       
   618     {
       
   619     aOut.WriteInt32L( iArray->Count() );
       
   620     for ( TInt i = 0; i < iArray->Count(); i++ ) 
       
   621         {
       
   622         CIndexItem* item = iArray->At( i );
       
   623         item->ExternalizeL( aOut );
       
   624         }
       
   625     }
       
   626 
       
   627 //--------------------------------------------------------------------
       
   628 //--------------------------------------------------------------------
       
   629 //
       
   630 void CPosLmNameIndex::InternalizeL( RReadStream& aIn )
       
   631     {
       
   632     Reset();
       
   633     TInt32 count = aIn.ReadInt32L();
       
   634     if ( count < 0 ) User::Leave( KErrCorrupt );
       
   635     for ( TInt i = 0; i < count; i++ ) 
       
   636         {
       
   637         CIndexItem* item = CIndexItem::NewLC( aIn );
       
   638         AppendL( item ); // array takes ownership
       
   639         CleanupStack::Pop( item );
       
   640         }
       
   641     iStatus = KErrNone;
       
   642     }
       
   643 
       
   644 //--------------------------------------------------------------------
       
   645 //--------------------------------------------------------------------
       
   646 //
       
   647 void CPosLmNameIndex::LoadL()
       
   648     {
       
   649     // Skip index loading for empty databases
       
   650     TInt numLandmarks = PosLmServerUtility::TotalLandmarkCountL( iDbAccess );
       
   651     if ( numLandmarks == 0 )
       
   652         {
       
   653         iTimeStamp.UniversalTime();
       
   654         iStatus = KErrNone;
       
   655         return;
       
   656         }
       
   657     
       
   658     RDbTable table;
       
   659     TInt err = table.Open( iDatabase, KPosLmIndexTable, RDbRowSet::EReadOnly );
       
   660     if ( err )
       
   661         {
       
   662         LOG("NameIndex::LoadL: index table not found"); 
       
   663         User::Leave( err );
       
   664         }
       
   665     CleanupClosePushL( table );
       
   666 
       
   667     table.FirstL();
       
   668     if ( table.AtEnd() )
       
   669         {
       
   670         LOG("NameIndex::LoadL: index not found"); 
       
   671         User::Leave( KErrNotFound  );
       
   672         }
       
   673 
       
   674     table.GetL();
       
   675 
       
   676     // verify that index is valid for current language
       
   677     if ( !table.IsColNull( EPosLmIncLanguageCol ) )
       
   678         {
       
   679         TLanguage lang = (TLanguage) table.ColInt32( EPosLmIncLanguageCol );
       
   680         if ( User::Language() != lang ) 
       
   681             {
       
   682             LOG2("NameIndex::LoadL: index not valid, lang %d, current lang %d", 
       
   683                 lang, User::Language() );
       
   684             User::Leave( KErrCorrupt );
       
   685             }
       
   686         }
       
   687     else
       
   688         {
       
   689         LOG("NameIndex::LoadL: index lang not found"); 
       
   690         User::Leave( KErrCorrupt );
       
   691         }
       
   692 
       
   693     // read the index
       
   694     if ( !table.IsColNull( EPosLmIncIndexDataCol ) )
       
   695         {
       
   696         RDbColReadStream readStream;
       
   697         readStream.OpenL( table, EPosLmIncIndexDataCol );
       
   698         CleanupClosePushL( readStream );
       
   699         InternalizeL( readStream );
       
   700         CleanupStack::PopAndDestroy( &readStream );
       
   701 
       
   702         // basic check for the index
       
   703         if ( Count() != numLandmarks )
       
   704             {
       
   705             LOG2("NameIndex::LoadL: index not valid, count %d, landmarks in db %d", 
       
   706                 Count(), numLandmarks );
       
   707             User::Leave( KErrCorrupt );
       
   708             }
       
   709         }
       
   710     else
       
   711         {
       
   712         LOG("NameIndex::LoadL: index data not found"); 
       
   713         User::Leave( KErrCorrupt );
       
   714         }
       
   715 
       
   716     // read the time stamp
       
   717     iTimeStamp.UniversalTime();
       
   718     if ( !table.IsColNull( EPosLmIncTimestampCol ) )
       
   719         {
       
   720         iTimeStamp = table.ColTime( EPosLmIncTimestampCol );
       
   721         }
       
   722     else
       
   723         {
       
   724         LOG("NameIndex::LoadL: index timestamp not found"); 
       
   725         User::Leave( KErrCorrupt );
       
   726         }
       
   727 
       
   728     CleanupStack::PopAndDestroy ( &table );
       
   729 
       
   730     // index is valid
       
   731     iStatus = KErrNone;
       
   732     }
       
   733 
       
   734 //--------------------------------------------------------------------
       
   735 //--------------------------------------------------------------------
       
   736 //
       
   737 void CPosLmNameIndex::SaveL( TChar aDrive )
       
   738     {
       
   739     RDbTable table;
       
   740     TInt err = table.Open( iDatabase, KPosLmIndexTable, RDbRowSet::EUpdatable );
       
   741     if ( err == KErrNotFound )
       
   742         {
       
   743         PosLmDatabaseManager::CreateIndexTableL( iDatabase );
       
   744         err = table.Open( iDatabase, KPosLmIndexTable, RDbRowSet::EUpdatable );
       
   745         }
       
   746     User::LeaveIfError( err );
       
   747     CleanupClosePushL( table );
       
   748 
       
   749     TInt currentSize = 0;
       
   750     table.FirstL();
       
   751     if ( table.AtEnd() )
       
   752         {
       
   753         table.InsertL();
       
   754         }
       
   755     else
       
   756         {
       
   757         table.GetL();
       
   758         currentSize = table.ColSize( EPosLmIncIndexDataCol ); 
       
   759         table.UpdateL();
       
   760         }
       
   761     
       
   762     if ( currentSize < DataSize() )
       
   763         {
       
   764         // check disk size
       
   765         CPosLmDiskUtilities* diskUtilities = CPosLmDiskUtilities::NewL();
       
   766         CleanupStack::PushL( diskUtilities );
       
   767     
       
   768         TInt bytesToWrite = DataSize() - currentSize;
       
   769         diskUtilities->DiskSpaceBelowCriticalLevelL( bytesToWrite, aDrive );
       
   770     
       
   771         CleanupStack::PopAndDestroy( diskUtilities );
       
   772         }
       
   773     
       
   774     // current language
       
   775     table.SetColL( EPosLmIncLanguageCol, User::Language() );
       
   776     
       
   777     // index data
       
   778     RDbColWriteStream writeStream;
       
   779     writeStream.OpenL( table, EPosLmIncIndexDataCol );
       
   780     CleanupClosePushL( writeStream );
       
   781     ExternalizeL( writeStream );
       
   782     CleanupStack::PopAndDestroy( &writeStream );
       
   783     
       
   784     // index timestamp
       
   785     TTime now;
       
   786     now.UniversalTime();
       
   787     table.SetColL( EPosLmIncTimestampCol, now );
       
   788 
       
   789 #ifdef _DEBUG  
       
   790     TBuf<64> mtime;
       
   791     now.FormatL( mtime, KPosLmTimeFormat );
       
   792     LOG1( "NameIndex: Saving index timestamp %S", &mtime); 
       
   793 #endif    
       
   794 
       
   795     table.PutL();
       
   796     CleanupStack::PopAndDestroy ( &table );
       
   797     
       
   798     iTimeStamp = now;
       
   799     }
       
   800 
       
   801 //--------------------------------------------------------------------
       
   802 //--------------------------------------------------------------------
       
   803 //
       
   804 CPosLmNameIndex::CIndexItem* CPosLmNameIndex::ItemById( TPosLmItemId aId ) const
       
   805     {
       
   806     iKeyItem->SetId( aId );
       
   807 
       
   808     TLinearOrder<CIndexItem> order( CIndexItem::CompareById );
       
   809     TInt index = iIdSortedArray.FindInOrder( iKeyItem, order );
       
   810     if ( index >=0 )
       
   811         return iIdSortedArray[index];
       
   812     else
       
   813         return NULL;
       
   814     }
       
   815 
       
   816 //--------------------------------------------------------------------
       
   817 //--------------------------------------------------------------------
       
   818 //
       
   819 void CPosLmNameIndex::CreateByIdSortingL()
       
   820     {
       
   821     iIdSortedArray.Reset();
       
   822     iIdSortedArray.ReserveL( iArray->Count() );
       
   823     
       
   824     for ( TInt i = 0; i < iArray->Count(); i++ ) 
       
   825         {
       
   826         CIndexItem* item = iArray->At( i );
       
   827         TLinearOrder<CIndexItem> order( CIndexItem::CompareById );
       
   828         iIdSortedArray.InsertInOrder( item, order );
       
   829         }
       
   830     }
       
   831 
       
   832 //--------------------------------------------------------------------
       
   833 //--------------------------------------------------------------------
       
   834 //
       
   835 void CPosLmNameIndex::RemoveInvalidItems()
       
   836     {
       
   837     for ( TInt i = iArray->Count() - 1; i >= 0 ; i-- ) 
       
   838         {
       
   839         CIndexItem* item = iArray->At( i );
       
   840         if ( !item->IsValid() )
       
   841             {
       
   842             delete item;
       
   843             iArray->Delete( i );
       
   844             }
       
   845         }
       
   846     }
       
   847 
       
   848 //--------------------------------------------------------------------
       
   849 //--------------------------------------------------------------------
       
   850 //
       
   851 void CPosLmNameIndex::StartTransaction()
       
   852     {
       
   853     ASSERT( !iInTransaction );
       
   854     ASSERT( iStatus == KErrNone );
       
   855     iInTransaction = ETrue;
       
   856     }
       
   857 
       
   858 //--------------------------------------------------------------------
       
   859 //--------------------------------------------------------------------
       
   860 //
       
   861 void CPosLmNameIndex::CommitTransaction()
       
   862     {
       
   863     ASSERT( iInTransaction );
       
   864     ASSERT( iStatus == KErrNone );
       
   865     // delete items marked as deleted
       
   866     // and validate items marked as temporary
       
   867     for ( TInt i = iArray->Count() - 1; i >= 0 ; i-- ) 
       
   868         {
       
   869         CIndexItem* item = iArray->At( i );
       
   870         if ( item->IsTemp() )
       
   871             {
       
   872             item->SetValid();
       
   873             }
       
   874         else if ( !item->IsValid() )
       
   875             {
       
   876             delete item;
       
   877             iArray->Delete( i );
       
   878             }
       
   879         }
       
   880     iInTransaction = EFalse;
       
   881     }
       
   882 
       
   883 //--------------------------------------------------------------------
       
   884 //--------------------------------------------------------------------
       
   885 //
       
   886 void CPosLmNameIndex::RollbackTransaction()
       
   887     {
       
   888     ASSERT( iInTransaction );
       
   889     ASSERT( iStatus == KErrNone );
       
   890     // delete temp items
       
   891     // and validate items marked as invalid
       
   892     for ( TInt i = iArray->Count() - 1; i >= 0 ; i-- ) 
       
   893         {
       
   894         CIndexItem* item = iArray->At( i );
       
   895         if ( item->IsTemp() )
       
   896             {
       
   897             delete item;
       
   898             iArray->Delete( i );
       
   899             }
       
   900         else if ( !item->IsValid() )
       
   901             {
       
   902             item->SetValid();
       
   903             }
       
   904         }
       
   905     iInTransaction = EFalse;
       
   906     }