none
SqlReplicaMetadata.GetChangeBatch throws ArgumentException: Value does not fall within the expected range RRS feed

  • Question

  • I have a custom provider that syncs with another provider instance of the same type. I am trying to implement move logic for ItemMetadata that has a unique indexed field in the metadata called Path. This path identifies the location of the item. The move logic deletes the original ItemMetadata with a merge tombstone for the new location.

    When I call for a sync, the SqlReplicaMetadata.GetChangeBatch method throws an ArgumentException: Value does not fall within the expected range. This is down in the COM object so I've got no ideas on what is wrong.

    Here are the failure details:

    Test method Neovolve.Jabiru.Server.Synchronization.IntegrationTests.StoreSyncProviderTests.StoreSyncProviderCanMoveItemToNewLocationTest threw exception:  System.ArgumentException: Value does not fall within the expected range..

    Microsoft.Synchronization.MetadataStorage.IReplicaMetadata2.GetChangeBatch(UInt32 dwBatchSize, ISyncKnowledge pSyncKnowledge, ISyncChangeBatch& ppSyncChangeBatch)
    Microsoft.Synchronization.MetadataStorage.SqlReplicaMetadata.GetChangeBatch(UInt32 batchSize, SyncKnowledge destinationKnowledge)
    Neovolve.Jabiru.Server.MetadataStorage.MetadataManager.GetChangeBatch(UInt32 batchSize, SyncKnowledge destinationKnowledge) in G:\Codeplex\Jabiru\Neovolve.Jabiru.Server\Neovolve.Jabiru.Server.MetadataStorage\MetadataManager.cs: line 147
    Neovolve.Jabiru.Server.Synchronization.StoreSyncProvider.GetChangeBatch(UInt32 batchSize, SyncKnowledge destinationKnowledge, Object& changeDataRetriever) in G:\Codeplex\Jabiru\Neovolve.Jabiru.Server\Neovolve.Jabiru.Server.Synchronization\StoreSyncProvider.cs: line 147
    Microsoft.Synchronization.KnowledgeProviderProxy.GetChangeBatch(UInt32 dwBatchSize, ISyncKnowledge pSyncKnowledge, ISyncChangeBatch& ppChangeBatch, Object& ppUnkDataRetriever)
    Microsoft.Synchronization.CoreInterop.ISyncSession.Start(CONFLICT_RESOLUTION_POLICY resolutionPolicy, _SYNC_SESSION_STATISTICS& pSyncSessionStatistics)
    Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWaySyncHelper(SyncIdFormatGroup sourceIdFormats, SyncIdFormatGroup destinationIdFormats, KnowledgeSyncProviderConfiguration destinationConfiguration, SyncCallbacks DestinationCallbacks, ISyncProvider sourceProxy, ISyncProvider destinationProxy, ChangeDataAdapter callbackChangeDataAdapter, SyncDataConverter conflictDataConverter, Int32& changesApplied, Int32& changesFailed)
    Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWayKnowledgeSync(SyncDataConverter sourceConverter, SyncDataConverter destinationConverter, SyncProvider sourceProvider, SyncProvider destinationProvider, Int32& changesApplied, Int32& changesFailed)
    Microsoft.Synchronization.KnowledgeSyncOrchestrator.Synchronize()
    Microsoft.Synchronization.SyncOrchestrator.Synchronize()
    Neovolve.Jabiru.Server.Synchronization.IntegrationTests.TestHelper.RunSync(SyncProvider localProvider, KnowledgeSyncProvider remoteProvider) in G:\Codeplex\Jabiru\Neovolve.Jabiru.Server\Neovolve.Jabiru.Server.Synchronization.IntegrationTests\TestHelper.cs: line 384
    Neovolve.Jabiru.Server.Synchronization.IntegrationTests.StoreSyncProviderTests.StoreSyncProviderCanMoveItemToNewLocationTest() in G:\Codeplex\Jabiru\Neovolve.Jabiru.Server\Neovolve.Jabiru.Server.Synchronization.IntegrationTests\StoreSyncProviderTests.cs: line 481

    The latest codebase is at http://jabiru.codeplex.com/SourceControl/changeset/view/39326 and this is the only test that currently fails for the Neovolve.Jabiru.Server solution.

    My only guess is that I am not creating the new ItemMetadata or  perhaps the merge tombstone correctly. Maybe I'm not using the SyncVersion values correctly.

    Any ideas would be appreciated.
    Friday, February 12, 2010 12:00 AM

Answers

  • If you have already fixed the problem then it is a great news.

    Let me explain a little about Merge Tombstone if you do not mind.  Assume you have one email contact item on a PC and its metadata item id is 0x10.  And later on, instead of sync this contact item to another PC, you created another email contact with the same user name but with a different metadata item id say 0x20 on the 2nd PC.  In general, these are 2 different metadata item in the sync community.  Now you are doing a sync between these 2 PC and they are conflicting, a constraint conflict is raised.  Syntactically, you have 2 different contact items because you have 2 different metadata items in the sync community.  But semantically, they should be one because they are of the same contact name.  In this scenario, one metadata item is MERGE tombstoned to another one.

    Now back to your scenario, #1.  How could a user data moved from path A to path B when B does not exist?  In real use, we should update metadata at the same time or even after the update of user data.  Is this the case here?

    Thanks.
    Leo Zhou ------ This posting is provided "AS IS" with no warranties, and confers no rights.
    Tuesday, February 16, 2010 5:05 AM
    Answerer

All replies

  • What is your business scenario here?  What does the actual "move" action do?

    "Deleting ItemMetadata" might not be a proper action, or you are just deleting user data not metadata (ItemMetadata)?

    Thanks.


    Leo Zhou ------ This posting is provided "AS IS" with no warranties, and confers no rights.
    Friday, February 12, 2010 8:14 PM
    Answerer
  • Hi -

    Why create a merge tombstone? You have succesfully indentified a move ( which is always the harder part) - why not just update the "Path" field in the metadata?

    Thanks
    Deepa
    Deepa ( Microsoft Sync Framework)
    Monday, February 15, 2010 11:57 PM
    Answerer
  • Hi Leo,

    There are probably three scenarios that I have.

    1. An item is moved from path A to path B when path B does not yet exist.
    2. An item is moved form path A to path B when path B is a pre-existing item
    3. Local and remote providers both know about path A but have its metadata stored with different SyncId values.


    Deepa,

    Your suggestion may work for scenario #3 above, but I can't make assumptions about that state of other replicas in the sync community. The local provider might not have path B, but path B may exist in a different replica such that simply updating the path would cause problems with the metadata.

    Using a merge tombstone seems to take care of all three scenarios and keep the metadata of multiple replicas intact.



    I have actually found the problem I was having with this code. My original merge logic was the following.
    MetadataManager.MergeSyncId(context.ConflictingItemId, change.ItemId, change.ChangeVersion);
    The sync id values here were incorrect and I was merging the same id values. This has been updated to the following.
    MetadataManager.MergeSyncId(context.WinnerChange.ItemId, context.ConflictingItemId, change.ChangeVersion);
    The MergeSyncId method has the following signature.
    void MergeSyncId(SyncId winningId, SyncId losingId, SyncVersion losingVersion);
    Tuesday, February 16, 2010 4:06 AM
  • If you have already fixed the problem then it is a great news.

    Let me explain a little about Merge Tombstone if you do not mind.  Assume you have one email contact item on a PC and its metadata item id is 0x10.  And later on, instead of sync this contact item to another PC, you created another email contact with the same user name but with a different metadata item id say 0x20 on the 2nd PC.  In general, these are 2 different metadata item in the sync community.  Now you are doing a sync between these 2 PC and they are conflicting, a constraint conflict is raised.  Syntactically, you have 2 different contact items because you have 2 different metadata items in the sync community.  But semantically, they should be one because they are of the same contact name.  In this scenario, one metadata item is MERGE tombstoned to another one.

    Now back to your scenario, #1.  How could a user data moved from path A to path B when B does not exist?  In real use, we should update metadata at the same time or even after the update of user data.  Is this the case here?

    Thanks.
    Leo Zhou ------ This posting is provided "AS IS" with no warranties, and confers no rights.
    Tuesday, February 16, 2010 5:05 AM
    Answerer
  • Yes, I think you are correct. I can refactor my code to do an update to the path for the existing metadata item id in the scenario where path B does not already exist. What you have suggested does seem to be the most appropriate action in this case.

    The only issue I see with this is where path A is updated to path B for the local replica, but path B already happens to exist in the remote replica before the sync session. This would be a very unlikely scenario, but I guess in this case a merge conflict on the local path B and remote path B will be the expected outcome anyway.

    So to sum up, scenario #1 will cause an update to the path for the existing metadata item when the destination path does not exist. If the destination does exist (and may be a tombstone from a previous sync session), then a merge tombstone will be required. The third scenario will always be a merge tombstone as the two metadata items already exist for the same path (this now works with the above fix).

    With regard to my fix, it has fixed the problem for scenario #3, but I am finding the same problem still occurs with my move logic. I'll refactor as suggested and see what happens.
    Tuesday, February 16, 2010 9:20 AM