IKnowledgeSyncProvider::ProcessChangeBatch
Обрабатывает набор изменений, обнаруживая конфликты и применяя изменения к хранилищу элементов.
HRESULT ProcessChangeBatch(
CONFLICT_RESOLUTION_POLICY resolutionPolicy,
ISyncChangeBatch * pSourceChangeBatch,
IUnknown * pUnkDataRetriever,
ISyncCallback * pCallback,
SYNC_SESSION_STATISTICS * pSyncSessionStatistics);
Параметры
- resolutionPolicy
[in] Политика разрешения конфликтов, осуществляемая во время применения изменений этим методом.
- pSourceChangeBatch
[in] Пакет изменений от поставщика источника для локального применения.
- pUnkDataRetriever
[in] Объект, который может использоваться для получения информации об изменениях. Это может быть объект ISynchronousDataRetriever или другой объект, зависящий от поставщика.
- pCallback
[in] Объект, который получает уведомления о событиях в ходе применения изменений.
- pSyncSessionStatistics
[in, out] Отслеживает статистику изменений. Для поставщика, использующего нестандартное применение изменений, этот объект необходимо обновить с учетом результатов применения изменений.
Возвращаемое значение
S_OK
Коды ошибок, определяемые поставщиком
Замечания
Если изменение источника содержит изменения базовых единиц, то поставщик назначения должен определить, какие именно версии базовых единиц (если они есть) следует включить в пакет версий назначения, отправляемый в объект применения изменений. Это решение зависит от типа изменений на поставщике источника, а также от того, помечен ли элемент как удаленный в реплике назначения. Дополнительные сведения см. в разделе Синхронизация базовых единиц.
Примеры
В приведенных ниже примерах показана реализация метода ProcessChangeBatch. В первом примере создается объект ISynchronousNotifyingChangeApplier и вызывается метод ISynchronousNotifyingChangeApplier::ApplyChanges для применения изменений в реплике назначения. Во втором примере реализован метод m_pMetadataMgr->GetItemBatchVersions
, используемый в первом примере. В этом методе выполняется перечисление изменений в пакете изменений источника и создается соответствующий список версий назначения с помощью объекта IDestinationChangeVersionsBuilder.
STDMETHODIMP CXMLProvider::ProcessChangeBatch(
CONFLICT_RESOLUTION_POLICY resolutionPolicy,
ISyncChangeBatch * pSourceChangeBatch,
IUnknown * pUnkDataRetriever,
ISyncCallback * pCallback,
SYNC_SESSION_STATISTICS * pSyncSessionStatistics)
{
HRESULT hr = E_UNEXPECTED;
if (NULL == pSourceChangeBatch || NULL == pUnkDataRetriever || NULL == pSyncSessionStatistics)
{
hr = E_POINTER;
}
else
{
IEnumSyncChanges* pDestinationChangeEnum = NULL;
_ASSERT(NULL != m_pMetadataMgr);
// Obtain the local (destination) versions for the items in the source change batch.
hr = m_pMetadataMgr->GetItemBatchVersions(pSourceChangeBatch, &pDestinationChangeEnum);
if (SUCCEEDED(hr))
{
IProviderSyncServices* pProviderSvc = NULL;
hr = GetProviderSyncServices(&c_idParams, &pProviderSvc);
if (SUCCEEDED(hr))
{
// Create a standard change applier from Sync Framework.
ISynchronousNotifyingChangeApplier* pChangeApplier = NULL;
hr = pProviderSvc->CreateChangeApplier(IID_ISynchronousNotifyingChangeApplier,
(void**)&pChangeApplier);
if (SUCCEEDED(hr))
{
ISyncKnowledge* pDestinationKnowledge = NULL;
hr = m_pMetadataMgr->GetKnowledge(&pDestinationKnowledge);
if (SUCCEEDED(hr))
{
// Have the change applier process the change batch and apply changes.
// This method will call the change applier target methods to save
// changes and conflicts. It will also pass the data retriever
// interface to the change applier target so it can retrieve item data.
hr = pChangeApplier->ApplyChanges(resolutionPolicy, pSourceChangeBatch,
pUnkDataRetriever, pDestinationChangeEnum, pDestinationKnowledge,
NULL, this, m_pSessionState, pCallback);
pDestinationKnowledge->Release();
}
pChangeApplier->Release();
}
pProviderSvc->Release();
}
pDestinationChangeEnum->Release();
}
}
return hr;
}
STDMETHODIMP CMetadataMgr::GetItemBatchVersions(
ISyncChangeBatch * pRemoteSyncChangeBatch,
IEnumSyncChanges ** ppLocalVersionsEnum)
{
HRESULT hr = E_UNEXPECTED;
if (NULL == pRemoteSyncChangeBatch || NULL == ppLocalVersionsEnum)
{
hr = E_POINTER;
}
else
{
IProviderSyncServices* pProvSvc;
hr = GetProviderSyncServices(&c_idParams, &pProvSvc);
if (SUCCEEDED(hr))
{
IDestinationChangeVersionsBuilder* pDestChangeBuilder = NULL;
hr = pProvSvc->CreateDestinationChangeVersionsBuilder(&pDestChangeBuilder);
if (SUCCEEDED(hr))
{
IEnumSyncChanges* pRemoteEnum = NULL;
hr = pRemoteSyncChangeBatch->GetChangeEnumerator(&pRemoteEnum);
if (SUCCEEDED(hr))
{
ULONG cFetched;
ISyncChange* pChange;
SYNC_GID gidItem;
DWORD cbID = sizeof(gidItem);
DWORD dwFlags;
SYNC_VERSION verCurrent;
SYNC_VERSION verCreation;
HRESULT hrEnum = S_OK;
while (S_OK == hrEnum && SUCCEEDED(hr))
{
pChange = NULL;
hrEnum = pRemoteEnum->Next(1, &pChange, &cFetched);
if (S_OK == hrEnum)
{
hr = pChange->GetRootItemId((BYTE*)&gidItem, &cbID);
if (SUCCEEDED(hr))
{
// Try to find the item in the local (destination) metadata.
IItemMetadata* pItem = NULL;
hr = FindItemMetadataByGlobalId((BYTE*)&gidItem, &pItem);
if (S_OK == hr)
{
// S_OK means the item exists in our local store.
// Extract its version and tombstone information.
dwFlags = 0;
BOOL fTombstone = FALSE;
hr = pItem->GetIsDeleted(&fTombstone);
if (SUCCEEDED(hr))
{
if (fTombstone)
{
dwFlags = SYNC_CHANGE_FLAG_DELETED;
}
}
if (SUCCEEDED(hr))
{
hr = pItem->GetChangeVersion(&verCurrent);
if (SUCCEEDED(hr))
{
hr = pItem->GetCreationVersion(&verCreation);
}
}
pItem->Release();
}
else if (S_FALSE == hr)
{
// S_FALSE means this item does not exist in our local store.
// Set versions to 0 and flag it as a new item.
verCurrent.dwLastUpdatingReplicaKey = 0;
verCurrent.ullTickCount = 0;
verCreation.dwLastUpdatingReplicaKey = 0;
verCreation.ullTickCount = 0;
dwFlags = SYNC_CHANGE_FLAG_DOES_NOT_EXIST;
}
if (SUCCEEDED(hr))
{
// Add the item to the batch of destination versions.
GUID guidReplicaID = GUID_NULL;
ULONG cbID = sizeof(guidReplicaID);
hr = GetReplicaId((BYTE*)&guidReplicaID, &cbID);
if (SUCCEEDED(hr))
{
hr = pDestChangeBuilder->AddItemMetadata((BYTE*)&guidReplicaID,
(BYTE*)&gidItem, &verCurrent, &verCreation, dwFlags, NULL);
}
}
}
pChange->Release();
}
}
if (FAILED(hrEnum))
{
hr = hrEnum;
}
pRemoteEnum->Release();
}
if (SUCCEEDED(hr))
{
hr = pDestChangeBuilder->GetChangeEnumerator(ppLocalVersionsEnum);
}
pDestChangeBuilder->Release();
}
pProvSvc->Release();
}
}
return hr;
}
См. также
Справочник
Интерфейс IKnowledgeSyncProvider
Перечисление CONFLICT_RESOLUTION_POLICY