廃棄標識の管理
廃棄標識は、レプリカから削除された項目を表します。廃棄標識の主な目的は、削除された項目がレプリカに再挿入されるのを防ぐことです。パフォーマンスやストレージの問題を防ぐため、廃棄標識は定期的にクリーンアップする必要があります。削除された項目が再挿入されるのを防ぐために、クリーンアップは慎重に管理する必要があります。
廃棄標識の表現
レプリカで、削除された項目を追跡するための決まった方法はありません。推奨される方法は、廃棄標識ビットまたは廃棄標識ログを使用することです。
廃棄標識ビット
項目のメタデータを定義するレプリカには、項目ストアからその項目が削除されたかどうかを示すブール値が含まれます。項目が削除されると、対応するメタデータ エントリで、この値が true に設定されます。廃棄標識ビットは、項目ごとに 1 ビット余分に使用するだけで済むため、削除された項目を多数追跡する必要がある場合には、記憶域を効率よく使用できるというメリットがあります。この方法では、メタデータ ストア全体を検索対象にしなければならないため、廃棄標識を列挙したりクリーンアップしたりする際の効率は低くなります。
廃棄標識ログ
項目ストアから削除された一連の項目を記録する、専用のログをレプリカで管理します。項目が削除されると、廃棄標識ログにエントリが追加されます。廃棄標識ログは、削除された項目ごとに ID を保持する必要があるため、削除された項目を多数追跡する必要がある場合の記憶効率はあまり高くありません。一覧には削除された項目しか含まれないため、廃棄標識を列挙したりクリーンアップしたりする際の効率は高くなります。
廃棄標識のクリーンアップ
同期コミュニティ内の各レプリカは、それ自身の状態に関するナレッジを保持しますが、このナレッジは、他のレプリカの状態とは一切関係がありません。そのため、廃棄標識がコミュニティ全体にレプリケートされているかどうかを調べることは不可能です。したがって、特定のレプリカにおいて、廃棄標識をいつどのようにクリーンアップするかは、完全にローカルでの判断ということになります。たとえば、ローカルのタイムスタンプまたはローカルのディスク領域要件に基づいて、廃棄標識をクリーンアップすることも可能です。レプリカに、廃棄標識の占有率がデータ セットの 10% を超えてはならない、というポリシーを設定することもできます。
廃棄標識がクリーンアップされると、レプリカは削除に関する情報を把握できなくなります。それでも、削除された項目が、それ自身のストアや別のレプリカに対して再挿入されてはならない、という点は変わりません。この問題を避けるため、レプリカのメタデータ ストアには、各項目の作成バージョンや、レプリカの忘れられたナレッジが維持されます。レプリカでは、廃棄標識をクリーンアップする場合、忘れられたナレッジに廃棄標識のバージョンを記録する必要があります。
マネージ コードを使用したクリーンアップ済みの廃棄標識の記録
削除された項目のメタデータがレプリカのメタデータ ストアから削除されたことを記録するには、レプリカの ForgottenKnowledge オブジェクトで ForgetTo を呼び出します。このメソッドには、削除された項目のバージョンを指定する必要があります。
アンマネージ コードを使用したクリーンアップ済みの廃棄標識の記録
削除された項目のメタデータがレプリカのメタデータ ストアから削除されたことを記録するには、レプリカの IForgottenKnowledge オブジェクトで IForgottenKnowledge::ForgetToVersion を呼び出します。このメソッドには、削除された項目のバージョンを指定する必要があります。
Sync Framework への忘れられたナレッジの提供
レプリカで忘れられたナレッジを使用してクリーンアップ済みの廃棄標識を追跡する場合、それに関連付けられているプロバイダーで、ChangeBatch (マネージ コードの場合) や IProviderSyncServices::CreateChangeBatch (アンマネージ コードの場合) などの、忘れられたナレッジを必要とする Sync Framework メソッドにこのナレッジを提供する必要があります。また、同期中に StoreKnowledgeForScope メソッド (マネージ コードの場合) や ISynchronousNotifyingChangeApplierTarget::SaveKnowledge メソッド (アンマネージ コードの場合) などで、忘れられたナレッジを更新されたナレッジと共に保存する必要もあります。
レプリカで廃棄標識をクリーンアップせず、忘れられたナレッジを保持しない場合、それに関連付けられているプロバイダーで、忘れられたナレッジのパラメーターがある Sync Framework メソッドに null (マネージ コードの場合) または NULL (アンマネージ コードの場合) を渡す必要があります。
廃棄標識に関連するシナリオ
廃棄標識に関しては、2 つのシナリオを考慮する必要があります。古くなったレプリカが同期を要求するケースと、削除された項目に対してレプリカが更新を送信するケースです。Sync Framework では、そのどちらのケースも検出できます。
古くなったレプリカの検出
これは、同期元レプリカに対して同期先レプリカが古くなった場合のシナリオです。同期元レプリカの廃棄標識はクリーンアップされているため、同期元レプリカには把握されなくなった削除操作が存在します。そのため、同期元プロバイダーは、こうした削除操作に対応する変更を、同期先プロバイダーに送信できません。Sync Framework は、変更を適用する前に、同期元レプリカの忘れられたナレッジと同期先レプリカの現在のナレッジを比較します。同期先ナレッジに忘れられたナレッジが含まれていない場合、Sync Framework は同期先レプリカが古くなっていると判断し、復旧同期を開始します。
アプリケーションのイベント ハンドラーが登録されていた場合、アプリケーションは Sync Framework のイベントを捕捉することにより、完全な列挙処理を続行するか、中止するかを必要に応じて制御できます。マネージ コードの場合、FullEnumerationNeeded イベントが発生します。アンマネージ コードでは、アプリケーションで、ISyncCallback::OnFullEnumerationNeeded コールバックを受け取ることができます。
アプリケーションのイベント ハンドラーが登録されていない場合、完全な列挙処理が自動的に実行されます。完全な列挙処理を実行すると、Sync Framework で同期元プロバイダーからの変更と同期先レプリカの項目を比較して、同期先レプリカから削除する必要がある項目を判断できるようになります。同期元プロバイダーからの対応する変更が含まれていない同期先レプリカの項目は、同期先レプリカから削除されます。
削除された項目に対する更新の検出
これは、同期先レプリカに対して同期元レプリカが古くなった場合のシナリオです。この状況は、前回、同期先レプリカの廃棄標識がクリーンアップされて以来、同期元と同期先のレプリカが同期されていない場合に生じます。同期先レプリカに削除された項目があり、その後同期先レプリカから廃棄標識がクリーンアップされた場合に、同期元レプリカでそれと同じ項目が更新されると問題が発生する可能性があります。この項目は、同期元プロバイダーが同期先プロバイダーに送信する変更バッチに追加されます。同期先プロバイダーが、これを新しい項目として認識した場合、同期先レプリカには、その項目が間違って再挿入されることになります。
同期元レプリカの項目の現在のバージョンを、同期先レプリカの現在のナレッジと比較しても意味はありません。再挿入されようとしている項目の現在のバージョンは、同期先レプリカの現在のナレッジには存在しないためです。その代わりに、同期元レプリカ側の項目の作成バージョンを、同期先レプリカの現在のナレッジと比較することによって、同期先レプリカが以前、その項目を把握していたかどうかを判断できます。項目の削除は、当然、その項目の作成後に起こります。また、同期先レプリカの現在のナレッジには、削除操作が含まれているため、現在のナレッジには、作成操作も存在していることになります。
したがって、Sync Framework は、新しい項目が同期先レプリカに追加される前に、項目の作成バージョンを、同期先レプリカの現在のナレッジと比較します。同期先ナレッジに、項目の作成バージョンが存在した場合、その項目は、以前は把握されていたものの、削除後、クリーンアップによって孤立した項目 (忘れられた項目) であると判断できます。この項目は、更新と削除の競合として扱われます。
参照
リファレンス
ISyncCallback::OnFullEnumerationNeeded
FullEnumerationNeeded