omads/omadsextensions/adapters/mediads/src/changefinder.cpp
changeset 36 9ba7f05d28a5
equal deleted inserted replaced
35:0ca79e3612d9 36:9ba7f05d28a5
       
     1 /*
       
     2 * Copyright (c) 2009 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:  Part of SyncML Data Synchronization Plug In Adapter
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "changefinder.h"
       
    20 #include "logger.h"
       
    21 
       
    22 const TUint KSnapshotFormatVersion ( 0xf0000001 ); // format version
       
    23 
       
    24 // -----------------------------------------------------------------------------
       
    25 // CChangeFinder::NewL
       
    26 // Static function to create CChangeFider object(s)
       
    27 // -----------------------------------------------------------------------------
       
    28 CChangeFinder* CChangeFinder::NewL( MSmlSyncRelationship& aSyncRelationship, TKeyArrayFix aKey,
       
    29         TBool& aHasHistory, TInt aStreamUid )
       
    30     {
       
    31     CChangeFinder* self = new (ELeave) CChangeFinder( aSyncRelationship, aKey, aStreamUid );
       
    32     CleanupStack::PushL( self );
       
    33     self->ConstructL( aHasHistory );
       
    34     CleanupStack::Pop( self );
       
    35     return self;
       
    36     }
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CChangeFinder::CChangeFinder
       
    40 // Constructor for the class
       
    41 // -----------------------------------------------------------------------------
       
    42 CChangeFinder::CChangeFinder( MSmlSyncRelationship& aSyncRelationship, TKeyArrayFix aKey, TInt aStreamUid ) :
       
    43 iSyncRelationship( aSyncRelationship ),
       
    44 iKey(aKey),
       
    45 iStreamUid( aStreamUid ),
       
    46 iDataStoreUid( KErrNotFound )
       
    47     {
       
    48         
       
    49     }
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // CChangeFinder::~CChangeFinder
       
    53 // Destructor for the class, closes the ChangeFinder and writes snapshot to stream
       
    54 // -----------------------------------------------------------------------------
       
    55 CChangeFinder::~CChangeFinder()
       
    56     {
       
    57     TRACE_FUNC_ENTRY;
       
    58     TInt error;
       
    59     TRAP( error, CloseL() );
       
    60     if ( error != KErrNone )
       
    61         {
       
    62         LOGGER_WRITE( "CChangeFinder::~CChangeFinder, CloseL failed." );
       
    63         }
       
    64     
       
    65     delete iCurrentSnapshot;
       
    66     iCurrentSnapshot = NULL;
       
    67     delete iOldSnapshot;
       
    68     iOldSnapshot = NULL;
       
    69     
       
    70     TRACE_FUNC_EXIT;
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CChangeFinder::ConstructL
       
    75 // 2nd phase constructor for the class, reads snapshot from stream
       
    76 // -----------------------------------------------------------------------------
       
    77 void CChangeFinder::ConstructL( TBool& aHasHistory )
       
    78     {
       
    79     TRACE_FUNC_ENTRY;
       
    80     
       
    81     TUid streamId;
       
    82     streamId.iUid = iStreamUid;
       
    83     
       
    84     aHasHistory = iSyncRelationship.IsStreamPresentL(streamId);
       
    85     
       
    86     if ( aHasHistory )
       
    87         {
       
    88         LOGGER_WRITE("CChangeFinder::ConstructL, history exists.");
       
    89         RReadStream readStream;
       
    90         iSyncRelationship.OpenReadStreamLC(readStream, streamId);
       
    91         
       
    92         // Read the index, first create snapshot array
       
    93         iOldSnapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
    94         
       
    95         // Read used format version
       
    96         TUint formatVer = readStream.ReadUint32L();
       
    97         if ( formatVer != KSnapshotFormatVersion )
       
    98             {
       
    99             // Wrong version, do not try to import data
       
   100             LOGGER_WRITE("CChangeFinder::ConstructL, Wrong format version -> no history");
       
   101             aHasHistory = EFalse;
       
   102             CleanupStack::PopAndDestroy( &readStream );
       
   103             TRACE_FUNC_EXIT;
       
   104             return;
       
   105             }
       
   106         
       
   107         // Read item count
       
   108         TInt count = readStream.ReadUint32L();
       
   109         // Read items
       
   110         for ( TInt i=0; i<count; i++ )
       
   111             {
       
   112             TSnapshotItem item;
       
   113             item.InternalizeL( readStream );
       
   114             iOldSnapshot->InsertIsqL( item, iKey );
       
   115             }
       
   116 
       
   117         CleanupStack::PopAndDestroy( &readStream );
       
   118         }
       
   119     else
       
   120         {
       
   121         LOGGER_WRITE("CChangeFinder::ConstructL, no sync history.");
       
   122         }
       
   123     
       
   124     TRACE_FUNC_EXIT;
       
   125     }
       
   126 
       
   127 // -----------------------------------------------------------------------------
       
   128 // CChangeFinder::CloseL
       
   129 // Closes ChangeFinder object and writes snapshot to stream
       
   130 // -----------------------------------------------------------------------------
       
   131 void CChangeFinder::CloseL()
       
   132     {
       
   133     TRACE_FUNC_ENTRY;
       
   134     
       
   135     // Write to stream
       
   136     RWriteStream writeStream;
       
   137     
       
   138     TUid streamId;
       
   139     streamId.iUid = iStreamUid; 
       
   140 
       
   141     // Open write stream
       
   142     iSyncRelationship.OpenWriteStreamLC( writeStream, streamId );
       
   143     
       
   144     // Write used format version
       
   145     writeStream.WriteUint32L( KSnapshotFormatVersion );
       
   146 
       
   147     // Write item count
       
   148     TInt count(0);
       
   149     if ( iOldSnapshot )
       
   150         {
       
   151         count = iOldSnapshot->Count();
       
   152         }
       
   153     writeStream.WriteUint32L(count);
       
   154     
       
   155     // Write items
       
   156     for (TInt i=0; i<count; i++)
       
   157         {
       
   158         const TSnapshotItem& item = iOldSnapshot->At( i );
       
   159         item.ExternalizeL( writeStream );
       
   160         }
       
   161 
       
   162     writeStream.CommitL();
       
   163     CleanupStack::PopAndDestroy( &writeStream );
       
   164     
       
   165     TRACE_FUNC_EXIT;
       
   166     }
       
   167 
       
   168 // -----------------------------------------------------------------------------
       
   169 // CChangeFinder::ResetL
       
   170 // Resets synchronization history, all contetn is considered new after this call
       
   171 // -----------------------------------------------------------------------------
       
   172 void CChangeFinder::ResetL()
       
   173     {
       
   174     TRACE_FUNC_ENTRY;
       
   175     
       
   176     // Delete old change information
       
   177     if ( iOldSnapshot )
       
   178         {
       
   179         LOGGER_WRITE("iOldSnapshot->Reset()");
       
   180         iOldSnapshot->Reset();
       
   181         }
       
   182     
       
   183     // Write 'null' data to file, 
       
   184     // this removes change history from the file
       
   185     CloseL();
       
   186     
       
   187     TRACE_FUNC_EXIT;
       
   188     }
       
   189 
       
   190 // -----------------------------------------------------------------------------
       
   191 // CChangeFinder::FindChangedItemsL
       
   192 // Compares snapshots, finds changed items
       
   193 // -----------------------------------------------------------------------------
       
   194 void CChangeFinder::FindChangedItemsL( CNSmlDataItemUidSet& aChangedUids )
       
   195     {   
       
   196     TRACE_FUNC_ENTRY;
       
   197     
       
   198     if ( !iCurrentSnapshot )
       
   199         {
       
   200         LOGGER_WRITE( "CChangeFinder::FindChangedItemsL leaved, no current snapshot." );
       
   201         User::Leave( KErrNotFound );
       
   202         }
       
   203 
       
   204     if ( !iOldSnapshot )
       
   205         {
       
   206         LOGGER_WRITE( "CChangeFinder::FindChangedItemsL leaved, no old snapshot." );
       
   207         User::Leave( KErrNotFound );
       
   208         }
       
   209         
       
   210     TInt index;
       
   211     TInt count = iCurrentSnapshot->Count();
       
   212     LOGGER_WRITE_1( "CChangeFinder::FindChangedItemsL count: %d", count );
       
   213     for ( TInt i=0; i < count; i++ )
       
   214         {
       
   215         const TSnapshotItem& currentItem = iCurrentSnapshot->At( i );
       
   216         // Find this entry from the old snapshot
       
   217         if ( iOldSnapshot->FindIsq( currentItem, iKey, index ) == KErrNone)
       
   218             {
       
   219             // This is the old item
       
   220             TSnapshotItem& oldItem = iOldSnapshot->At( index );
       
   221             // Compare hash to see whether this was changed
       
   222             if ( oldItem.Hash().Compare( currentItem.Hash() ) != 0
       
   223                     || oldItem.ParentId() != currentItem.ParentId() )
       
   224                 {
       
   225                 aChangedUids.AddItem( currentItem.ItemId() );
       
   226                 //LOGGER_WRITE_1( "Item %d was changed.", currentItem.ItemId() );  
       
   227                 }
       
   228             }
       
   229         }
       
   230     
       
   231     TRACE_FUNC_EXIT;
       
   232     }
       
   233 
       
   234 // -----------------------------------------------------------------------------
       
   235 // CChangeFinder::FindDeletedItemsL
       
   236 // Compares snapshots, finds deleted items
       
   237 // -----------------------------------------------------------------------------
       
   238 void CChangeFinder::FindDeletedItemsL( CNSmlDataItemUidSet& aDeletedUids )
       
   239     {
       
   240     TRACE_FUNC_ENTRY;
       
   241     
       
   242     if ( !iOldSnapshot )
       
   243         {
       
   244         LOGGER_WRITE( "CChangeFinder::FindDeletedItemsL leaved, no old snapshot." );
       
   245         User::Leave( KErrNotFound );
       
   246         }
       
   247     
       
   248     TInt index;
       
   249     TInt count = iOldSnapshot->Count();
       
   250     for ( TInt i=0; i < count; i++ )
       
   251         {
       
   252         const TSnapshotItem& currentItem = iOldSnapshot->At( i );
       
   253         
       
   254         // If there's no current snapshot, this definately is deleted item
       
   255         if ( !iCurrentSnapshot )
       
   256             {
       
   257             aDeletedUids.AddItem( currentItem.ItemId() );
       
   258             //LOGGER_WRITE_1( "Item %d was deleted.", currentItem.ItemId() );
       
   259             }
       
   260         // It is also new if it doesn't exist int the current snapshot.
       
   261         else if ( iCurrentSnapshot->FindIsq( currentItem, iKey, index ) != KErrNone )
       
   262             {
       
   263             aDeletedUids.AddItem( currentItem.ItemId() );
       
   264             //LOGGER_WRITE_1( "Item %d was deleted.", currentItem.ItemId() );
       
   265             }       
       
   266         }
       
   267         
       
   268     TRACE_FUNC_EXIT;
       
   269     }
       
   270 
       
   271 // -----------------------------------------------------------------------------
       
   272 // CChangeFinder::FindNewItemsL
       
   273 // Compares snapshots, finds new items
       
   274 // -----------------------------------------------------------------------------
       
   275 void CChangeFinder::FindNewItemsL( CNSmlDataItemUidSet& aNewUids )
       
   276     {
       
   277     TRACE_FUNC_ENTRY;
       
   278     
       
   279     if ( !iCurrentSnapshot )
       
   280         {
       
   281         LOGGER_WRITE( "CChangeFinder::FindNewItemsL leaved, no current snapshot." );
       
   282         User::Leave( KErrNotFound );
       
   283         }
       
   284 
       
   285     TInt index;
       
   286     TInt count = iCurrentSnapshot->Count();
       
   287     for ( TInt i=0; i < count; i++ )
       
   288         {
       
   289         const TSnapshotItem& currentItem = iCurrentSnapshot->At( i );
       
   290         
       
   291         // If there's no old snapshot, all items are new
       
   292         if ( !iOldSnapshot )
       
   293             {
       
   294             aNewUids.AddItem( currentItem.ItemId() );
       
   295             //LOGGER_WRITE_1( "Item %d was new.", currentItem.ItemId() );
       
   296             }
       
   297         // It is also new if it doesn't exist int the old snapshot.
       
   298         else if ( iOldSnapshot->FindIsq( currentItem, iKey, index ) != KErrNone )
       
   299             {
       
   300             aNewUids.AddItem( currentItem.ItemId() );
       
   301             //LOGGER_WRITE_1( "Item %d was new.", currentItem.ItemId() );
       
   302             }       
       
   303         }
       
   304         
       
   305     TRACE_FUNC_EXIT;
       
   306     }
       
   307 
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // CChangeFinder::ItemAddedL
       
   311 // Adds item to snapshot, this item is no longer considered new
       
   312 // -----------------------------------------------------------------------------
       
   313 void CChangeFinder::ItemAddedL( const TSnapshotItem& aItem )
       
   314     {
       
   315     TRACE_FUNC_ENTRY;
       
   316     
       
   317     // Add this to old snapshot, if there's no old snapshot it must be created
       
   318     if ( !iOldSnapshot )
       
   319         {
       
   320         iOldSnapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
   321         }
       
   322         
       
   323     LOGGER_WRITE_1( "Adding item %d.", aItem.ItemId() );
       
   324     
       
   325     TRAPD( error, iOldSnapshot->InsertIsqL( aItem, iKey ) );
       
   326     if ( error == KErrAlreadyExists )
       
   327         {
       
   328         // It was already committed, no actions required
       
   329         LOGGER_WRITE( "iOldSnapshot->InsertIsqL leaved with KErrAlreadyExists" );
       
   330         }
       
   331     else if ( error != KErrNone )
       
   332         {
       
   333         LOGGER_WRITE_1( "iOldSnapshot->InsertIsqL leaved with %d.", error );
       
   334         User::Leave( error );
       
   335         }
       
   336     iOldSnapshot->Compress();
       
   337     
       
   338     TRACE_FUNC_EXIT;
       
   339     }
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // CChangeFinder::ItemDeletedL
       
   343 // Removes item to snapshot, this item is no longer considered deleted
       
   344 // -----------------------------------------------------------------------------
       
   345 void CChangeFinder::ItemDeletedL( const TSnapshotItem& aItem )
       
   346     {
       
   347     TRACE_FUNC_ENTRY;
       
   348     
       
   349     LOGGER_WRITE_1( "deleting item %d.", aItem.ItemId() );
       
   350     
       
   351     if ( !iOldSnapshot )
       
   352         {
       
   353         LOGGER_WRITE( "CChangeFinder::ItemDeleted leaved, no old snapshot." );
       
   354         User::Leave( KErrNotFound );
       
   355         }
       
   356 
       
   357     // Delete item from the old snapshot
       
   358     TInt index;
       
   359     if ( iOldSnapshot->FindIsq( aItem, iKey, index ) == KErrNone )
       
   360         {
       
   361         iOldSnapshot->Delete( index );
       
   362         }
       
   363     else // Skip, there wasn't such entry
       
   364         {
       
   365         LOGGER_WRITE( "iOldSnapshot->FindIsq, item was not found." );
       
   366         }
       
   367     iOldSnapshot->Compress();
       
   368     
       
   369     TRACE_FUNC_EXIT;
       
   370     }
       
   371 
       
   372 // -----------------------------------------------------------------------------
       
   373 // CChangeFinder::ItemUpdatedL
       
   374 // Updates item to snapshot, this item is no longer considered changed
       
   375 // -----------------------------------------------------------------------------
       
   376 void CChangeFinder::ItemUpdatedL( const TSnapshotItem& aItem )
       
   377     {
       
   378     TRACE_FUNC_ENTRY;
       
   379 
       
   380     LOGGER_WRITE_1( "Updating item %d.", aItem.ItemId() );
       
   381     
       
   382     // There must be such entry in the snapshot after this
       
   383     // If there isn't old snapshot, we'll create it and add the item
       
   384     if ( !iOldSnapshot )
       
   385         {
       
   386         iOldSnapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
   387         ItemAddedL( aItem );
       
   388         }
       
   389     else
       
   390         {
       
   391         // Update item in the old snapshot
       
   392         TInt index;
       
   393         if ( iOldSnapshot->FindIsq( aItem, iKey, index ) == KErrNone )
       
   394             {
       
   395             TSnapshotItem& oldItem = iOldSnapshot->At( index );
       
   396             oldItem = aItem;
       
   397             }
       
   398         else 
       
   399             {
       
   400             // There was old snapshot but no such item. Let's add it
       
   401             ItemAddedL( aItem );
       
   402             }
       
   403         
       
   404         }
       
   405     iOldSnapshot->Compress();
       
   406     TRACE_FUNC_EXIT;
       
   407     }
       
   408 
       
   409 
       
   410 // -----------------------------------------------------------------------------
       
   411 // CChangeFinder::CommitChangesL
       
   412 // Commits current changes to snapshot
       
   413 // -----------------------------------------------------------------------------
       
   414 void CChangeFinder::CommitChangesL()
       
   415     {
       
   416     TRACE_FUNC_ENTRY;
       
   417     
       
   418     if ( !iCurrentSnapshot )
       
   419         {
       
   420         LOGGER_WRITE( "CChangeFinder::CommitChangesL leaved, current snapshot missing." );
       
   421         User::Leave( KErrNotFound );
       
   422         }
       
   423         
       
   424     if ( !iOldSnapshot )
       
   425         {
       
   426         iOldSnapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
   427         }
       
   428         
       
   429     // Delete everything from the old snapshot
       
   430     iOldSnapshot->Reset();
       
   431     
       
   432     // Loop through all the items in current snapshot
       
   433     TInt count = iCurrentSnapshot->Count();
       
   434     
       
   435     // Copy everything from current to old snapshot
       
   436     for ( TInt i = 0; i < count; i++ )
       
   437         {
       
   438         // Commit it to the old array.
       
   439         iOldSnapshot->InsertIsqL( iCurrentSnapshot->At( i ), iKey );
       
   440         }
       
   441     TRACE_FUNC_EXIT;
       
   442     }
       
   443 
       
   444 
       
   445 // -----------------------------------------------------------------------------
       
   446 // CChangeFinder::CommitChangesL
       
   447 // Commits current changes to snapshot, affects only a specified group of items
       
   448 // -----------------------------------------------------------------------------
       
   449 void CChangeFinder::CommitChangesL( const MSmlDataItemUidSet& aUids )
       
   450     {
       
   451     TRACE_FUNC_ENTRY;
       
   452     
       
   453     
       
   454     // This function commits changes from current snapshot to old snapshot
       
   455     // But commits only the entries in the parameter array
       
   456     if ( !iCurrentSnapshot )
       
   457         {
       
   458         LOGGER_WRITE( "CChangeFinder::CommitChangesL leaved, current snapshot missing." );
       
   459         User::Leave( KErrNotFound );
       
   460         }
       
   461         
       
   462     if ( !iOldSnapshot )
       
   463         {
       
   464         iOldSnapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
   465         }
       
   466     
       
   467     for ( TInt i = 0; i < aUids.ItemCount(); i++ )
       
   468         {
       
   469         TSmlDbItemUid itemId = aUids.ItemAt( i );
       
   470         TSnapshotItem temp( itemId );
       
   471         TInt indexOld( -1 );
       
   472         TInt indexNew( -1 );
       
   473         TInt err = iOldSnapshot->FindIsq( temp, iKey, indexOld);
       
   474         if ( !err )
       
   475             {
       
   476             // founded from old snapshot
       
   477             if ( !iCurrentSnapshot->FindIsq(temp, iKey, indexNew) )
       
   478                 {
       
   479                 // Replace
       
   480                 iOldSnapshot->At( indexOld ) = iCurrentSnapshot->At( indexNew );
       
   481                 }
       
   482             else
       
   483                 {
       
   484                 // not found from current snapshot, delete from old also.
       
   485                 iOldSnapshot->Delete( indexOld );
       
   486                 }
       
   487             }
       
   488         else
       
   489             {
       
   490             // not found from old snapshot, add it.
       
   491             if ( !iCurrentSnapshot->FindIsq( temp, iKey, indexNew ) )
       
   492                 {
       
   493                 iOldSnapshot->InsertIsqL( iCurrentSnapshot->At( indexNew ), iKey );
       
   494                 }
       
   495             }
       
   496         }
       
   497     TRACE_FUNC_EXIT;
       
   498     }
       
   499 
       
   500 // -----------------------------------------------------------------------------
       
   501 // CChangeFinder::SetNewSnapshot
       
   502 // Sets new snapshot (to be compared against), ChangeFinder takes ownership
       
   503 // -----------------------------------------------------------------------------
       
   504 void CChangeFinder::SetNewSnapshot( CSnapshotArray* aNewSnapshot )
       
   505     {
       
   506     TRACE_FUNC_ENTRY;
       
   507     
       
   508     // Delete existing snapshot
       
   509     delete iCurrentSnapshot;
       
   510     
       
   511     // Set submitted snapshot as active
       
   512     iCurrentSnapshot = aNewSnapshot;
       
   513     iCurrentSnapshot->Compress();
       
   514     
       
   515     TRACE_FUNC_EXIT;
       
   516     }
       
   517 
       
   518 // -----------------------------------------------------------------------------
       
   519 // CChangeFinder::DataStoreUid
       
   520 // returns stored data store id number
       
   521 // -----------------------------------------------------------------------------
       
   522 TInt64 CChangeFinder::DataStoreUid() const
       
   523     {
       
   524     TRACE_FUNC;
       
   525     return iDataStoreUid;
       
   526     }
       
   527 
       
   528 // -----------------------------------------------------------------------------
       
   529 // CChangeFinder::SetDataStoreUid
       
   530 // Sets data store id number
       
   531 // -----------------------------------------------------------------------------
       
   532 void CChangeFinder::SetDataStoreUid( TInt64 aUid )
       
   533     {
       
   534     TRACE_FUNC;
       
   535     iDataStoreUid = aUid;
       
   536     }
       
   537