競合のログ記録と管理
同期時に、競合をすぐに解決できないので競合ログに保存する必要がある、という内容のメッセージが表示されることがあります。競合ログを使用することによって、競合を同期処理とは別に解決することができます。その結果、同期をできるだけ効率的に完了することができます。
ログ記録による競合の解決
アプリケーションは、同時実行の競合を保存することを示す場合、競合解決アクションとして SaveConflict (マネージ コードの場合) または SRA_TRANSFER_AND_DEFER (アンマネージ コードの場合) を設定します。アプリケーションは、制約の競合を保存することを示す場合、競合解決アクションとして SaveConflict (マネージ コードの場合) または SCRA_TRANSFER_AND_DEFER (アンマネージ コードの場合) を設定します。
競合のログ記録
変更適用元は、同時実行の競合をログ記録する場合、SaveConflict (マネージ コードの場合) または ISynchronousNotifyingChangeApplierTarget::SaveConflict (アンマネージ コードの場合) を呼び出します。このメソッドで、プロバイダーは、競合する変更のメタデータ、競合する変更のデータ、および指定された競合ナレッジを保存します。
変更適用元は、制約の競合をログ記録する場合、SaveConstraintConflict (マネージ コードの場合) または ISynchronousNotifyingChangeApplierTarget2::SaveConstraintConflict (アンマネージ コードの場合) を呼び出します。このメソッドで、プロバイダーは、競合する変更のメタデータ、競合する変更のデータ、同期先レプリカの競合する項目の ID、競合する理由、および指定された競合ナレッジを保存します。
競合を競合ログに記録する前に、プロバイダーは、この競合に代わる新しい別の変更が競合ログに既に記録されていないことを確認する必要があります。これを行う 1 つの方法は、Combine (マネージ コードの場合) または ISyncKnowledge::Union (アンマネージ コードの場合) を使用して、ログに記録されたすべての競合の競合ナレッジを組み合わせて、ログ ナレッジを作成することです。新しい競合がログ ナレッジに含まれる場合、その競合は古いものなので、ログに追加するのは適切ではありません。このログ ナレッジは、必要時に作成することも、競合ログと共に保管することもできます。保管したログ ナレッジは、競合が追加されたら Combine (マネージ コードの場合) または Union (アンマネージ コードの場合) を使用して、更新する必要があります。同様に、競合が削除されたら Complement (マネージ コードの場合) または ISyncKnowledge2::Complement (アンマネージ コードの場合) を使用して、ログ ナレッジを更新する必要があります。
期限切れの競合の削除
競合ログが肥大化するのを防ぐため、期限切れの競合を競合ログから削除する必要があります。
期限切れの競合の検出と削除を最も簡単に実行するには、Sync Framework の変更適用元を使用します。競合ログを変更適用元に関連付けるために、プロバイダーまたは競合ログには IConflictLogAccess および IConflictLogWriter インターフェイス (マネージ コードの場合) または IConflictLogAccess および IConflictLogWriter インターフェイス (アンマネージ コードの場合) が実装されています。競合ログは、
ApplyChanges メソッド (マネージ コードの場合) または ISynchronousNotifyingChangeApplier2::ApplyChanges メソッド (アンマネージ コードの場合) を使用して、変更適用元に渡されます。競合ログが変更適用元に渡されると、変更適用元は、ログに記録されている期限切れの競合を検出して、各変更バッチの最後に削除します。
変更適用元に接続しない競合ログの場合、競合ログが単独で期限切れの競合を管理する必要があります。競合は、競合ログに既に記録されているものに代わる新しい競合が競合ログに追加された場合に、期限切れになります。このようなケースを検出する 1 つの方法は、ログに記録された各競合の変更バージョンを新しい競合の競合ナレッジに照らし合わせて検査することです。競合の変更バージョンが、新しい競合の競合ナレッジに含まれる場合、その既存の競合は期限切れであり、ログから削除する必要があります。また、競合は、競合ログに既に記録されている競合に代わる変更がレプリカに適用されると、その時点で期限切れになります。このようなケースを検出する 1 つの方法は、ログに記録された各競合の変更バージョンを各変更バッチの適用後にレプリカのナレッジに照らし合わせて検査することです。期限切れの競合の検出と解決は、同期セッションの一環として実行することも別の機会に実行することもできます。
ログに記録された競合の解決
競合ログに記録された競合は、同期セッションの一環として解決することも別の機会に解決することもできます。ただし、競合ログに記録された競合を変更適用時に解決しないでください。予期しない結果が生じる可能性があります。
競合ログに記録された競合をレプリカに適用する場合は、ローカルな変更として処理する必要があります。競合ログに記録された競合を解決するために、アプリケーションまたはプロバイダーは次の手順を実行します。
レプリカのティック数を増やします。
ティック数が更新されたローカル レプリカによって変更が行われることを反映して、項目または変更単位の変更バージョンを更新します。
Combine (マネージ コードの場合) または Union (アンマネージ コードの場合) を使用してレプリカのナレッジを競合のナレッジと組み合わせます。この組み合わされたナレッジをレプリカの新しいナレッジとして保存します。
変更データをレプリカに適用します。
競合を競合ログから削除します。
メモリ内競合ログ
プロバイダーが制約の競合を報告する場合、競合ログが必要になります。競合ログがないレプリカのために制約の競合を報告するプロバイダーを支援するために、Sync Framework は、競合ログ インターフェイスを実装します。この実装は、メモリ内で動作して、制約の競合を処理する結果として生じる可能性がある一時的な競合を格納するために使用されます。具体的な実装としては、MemoryConflictLog クラス (マネージ コードの場合) と、IProviderSyncServices2::CreateMemoryConflictLog の呼び出しで取得できる IMemoryConflictLog インターフェイス (アンマネージ コードの場合) が該当します。
このメモリ内競合ログ実装は、永続的な競合ログと組み合わせて使用することもできます。メモリ内競合ログ実装を使用して、パフォーマンスを向上させることができます。具体的には、メモリ内競合ログ実装が完全な競合ログのメモリ内キャッシュとなって、一時的な競合を処理します。永続的な競合ログが、メモリ内競合ログに連結されている場合、Persist (マネージ コードの場合) または IMemoryConflictLog::Persist (アンマネージ コードの場合) を呼び出して、同期完了後に競合を永続的な競合ログに保存することができます。