Поделиться через


Создание согласователей портфеля

Инструмент согласования в Briefcase предоставляет возможность согласовывать различные версии документа.

О сверителях соединений

Согласователь портфеля объединяет различные входные версии документа для создания единой новой выходной версии документа. Возможно, вам потребуется создать приложение для синхронизации, чтобы поддерживать ваш тип документов. В этом обзоре описываются синхронизаторы Briefcase и объясняется, как их создавать.

Рассматриваются следующие разделы:

Примирение

Документ представляет собой коллекцию сведений, которые можно копировать и изменять. Документ имеет разные версии, если содержимое по крайней мере двух копий документа отличается. Согласование создает единую версию документа из двух или более исходных версий. Как правило, примирившаяся версия — это сочетание сведений из начальных версий с самой последней или самой полезной информацией.

Сверка инициируется программой Briefcase, когда определяется, что два или более экземпляров одного документа отличаются. Портфель, который выступает в качестве инициатора в этом контексте, находит и запускает синхронизатор портфеля, связанный с заданным типом документа. Согласователь сравнивает документы и определяет, какие части документов оставить. Некоторым примирителям может потребоваться взаимодействие с пользователем для завершения выверки. Другие могут завершить выверку без взаимодействия с пользователем. Согласователь может содержаться в приложении или быть расширением, реализованным в виде DLL.

Некоторые согласователи портфелей могут создавать остатки. Остатки — это документ, который обычно имеет тот же тип файла, что и исходный документ, содержащий сведения, не сохраненные в объединенной версии. Остаточная информация обычно используется для быстрой проверки, какие сведения из исходного документа отсутствуют в окончательной объединенной версии. Если согласователь поддерживает остатки, он создает один остаток для каждой из исходных версий документа. Остатки не создаются, если инициатор не запрашивает их.

Некоторые договорители, работающие с Briefcase, позволяют пользователю прекратить процесс сверки. Это важная функция для пользователя, который может решить, что выверка не должна продолжаться. Согласователь обычно предоставляет объект завершения, когда для согласования требуется взаимодействие с пользователем, и процесс может занимать много времени. В некоторых средах согласователь может разрешить частичную сверку, что позволяет пользователю временно приостановить сверку и возобновить её позже. В настоящее время Briefcase не поддерживает частичную сверку.

Создание утилиты "Briefcase Reconciler"

Вы создаете модуль для сверки портфеля документов, реализуя интерфейсы сверки. Как минимум, примиритель реализует интерфейс IReconcilableObject и интерфейс IPersistStorage или IPersistFile. В качестве инициатора Briefcase определяет, когда требуется выверка, и вызывает метод IReconcilableObject::Reconcile для начала выверки.

Хотя IReconcilableObject::Reconcile предоставляет широкий набор возможностей по сверке, в большинстве случаев программа для синхронизации данных типа 'портфель' осуществляет только минимальную сверку. В частности, Briefcase не требует от согласователя поддержки создания остатков или поддержки объекта завершения. Кроме того, средство согласования выполняет единую выверку от начала до конца и не должно возвращать значение REC_E_NOTCOMPLETE; то есть оно не должно пытаться произвести частичное согласование.

Портфель предоставляет интерфейс IReconcileInitiator. Примиритель портфеля может использовать метод IReconcileInitiator::SetAbortCallback, чтобы задать объект завершения. Функция "Briefcase" не использует идентификаторы версий и, следовательно, не может предоставить предыдущие версии документа, если посредник запрашивает их с помощью соответствующих методов в IReconcileInitiator.

Портфель передается в IReconcilableObject::Reconcile моникеры файлов, представляющие версии документа, которые необходимо примирить. Согласователь версий получает доступ к версиям с помощью метода IMoniker::BindToObject или IMoniker::BindToStorage. Последний обычно быстрее и рекомендуется. Примиритель должен освободить все объекты или хранилища, к которым он привязан.

Когда при согласовании портфеля используется IMoniker::BindToStorage, он привязывается к хранилищу, которое является неструктурированным хранилищем (потоком) или структурированным хранилищем OLE. Если примиритель ожидает неструктурированное хранилище, он должен использовать IMoniker::BindToStorage для запроса интерфейса IStream. Если примиритель ожидает структурированное хранилище, он должен запросить интерфейс IStorage. В обоих случаях необходимо запрашивать прямой нетрансактированный доступ только для чтения к хранилищу; доступ на чтение и запись может быть недоступен.

Минимальный согласователь портфеля обычно напрямую обращается к хранилищу других версий и обрабатывает встроенные объекты очень примитивным образом, например, путем объединения двух версий объекта, включая обе в выходную версию.

Инициатор находит соответствующий синхронизатор для кейса, используя часть логики, реализованной функцией GetClassFile , чтобы определить тип заданного файла, а затем ищет в реестре класс синхронизатора, связанный с заданным типом файла. Портфел, как и другие компоненты оболочки, определяет тип файла исключительно расширением имени файла. Расширение файла должно иметь зарегистрированный тип файла, чтобы Briefcase мог вызвать инструмент согласования для файла. При установке примирителя необходимо задать запись реестра следующей формы.

CLSID
   {the file CLSID}
      Roles
         Reconciler
            (Default) = {the reconciler-classid}

Класс должен быстро загружаться, должен иметь обозначение _MULTIPLEUSE и, если для интерфейса согласования не предусмотрены маршалеры, должен быть сервером внутрипроцессной обработки (содержащимся в DLL), а не локальным сервером (реализованным в файле .exe).

Взаимодействие с пользователем в сверке

Система согласования портфелей должна стремиться провести согласование без необходимости взаимодействия с пользователем. Чем более автоматизирована сверка, тем лучше восприятие пользователем процесса.

В некоторых случаях вмешательство пользователя может быть ценным. Например, системе документов может потребоваться, чтобы пользователь проверял изменения перед принятием объединенной версии документа или может потребовать комментариев от пользователя, объясняющего внесенные изменения. В таких случаях инициатор, а не примиритель портфеля, отвечает за запрос пользователя и выполнение инструкций пользователя.

В других случаях вмешательство пользователя может потребоваться, например, если две версии были изменены несовместимыми способами. В таких случаях инициатор или примиритель портфеля должен запрашивать у пользователя инструкции по разрешению конфликта. В общем случае инициатор не может полагаться на завершение выверки, не ожидая некоторого взаимодействия с пользователем. С другой стороны, примирители могут взаимодействовать с пользователем, чтобы разрешить конфликты или требовать от инициатора этого.

Согласование внедренных объектов

При согласовании документа сам согласователь может стать инициатором, если он обнаруживает встроенный объект типа, который он не может согласовать. В этом случае посреднику необходимо рекурсивно примирить каждый из внедренных объектов и взять на себя все обязанности инициатора.

Для выполнения рекурсии согласователь портфеля загружает объект и делает запрос на соответствующий интерфейс. Обработчик объекта должен поддерживать интерфейс. Если любой метод интерфейса возвращает значение OLE_E_NOTRUNNING, согласователь должен запустить объект для выполнения операции. Так как код для внедренных объектов не всегда доступен, примиритетель должен предоставить решение для этого условия. Например, примиритетель может включать как старые, так и новые версии внедренного объекта в примиривленную версию. Примиритель не должен пытаться примирить связи.

Инициатор сохраняет объединенные версии документов. Во многих случаях инициатор имеет доступ к хранилищу каждой версии и сохраняет результат выверки с помощью аналогичного хранилища. Однако иногда инициатор может иметь объект в памяти, для которого не доступна постоянная версия. Эта ситуация может возникнуть, когда документ, содержащий открытые внедренные объекты, необходимо согласовать перед сохранением. В таких случаях инициатор сохраняет результат сверки в версии, найденной в памяти.

Инициатор использует интерфейс IPersistStorage для привязки (загрузки) объединенной версии. Инициатор использует метод IPersistStorage::Load, если исходная версия уже создана и использует метод IPersistStorage::InitNew для начальной версии. При загрузке объединенной версии инициатор использует QueryInterface для получения адреса интерфейса IReconcilableObject. Этот интерфейс предоставляет инициатору доступ к хранилищу существующих остатков и позволяет создать хранилище для любых новых остатков. Затем инициатор направляет интерфейс для выполнения выверки. Инициатор фактически запрашивает интерфейс IPersistFile перед IPersistStorage. Если примиритель поддерживает IPersistFile, инициатор управляет репликой с помощью методов IPersistFile, а не методов IPersistStorage. Это позволяет согласование файлов, которые не хранятся в виде составных документов.

По завершении выверки инициатор может сохранить объединенную версию с помощью интерфейса IPersistStorage или IPersistFile. Во время выверки согласователь создает остатки по мере необходимости и записывает их постоянные данные в хранилище. Если объединенная версия представляет собой поток, интерфейс IStorage, передаваемый в IPersistStorage::Load, содержит поток с именем "Contents" и состоянием STATEBITS_FLAT. (Вы можете задать биты состояния с помощью метода IStorage::Stat.) После слияния инициатор сохраняет объединенную версию, записывая данные соответствующим образом. Он должен убедиться, что STATEBITS_FLAT заданы соответствующим образом для хранилища.

Остатки

Инициатор указывает, нужны ли остатки, задавая для параметра pstgNewResidues допустимый адрес при вызове метода IReconcilableObject::Reconcile. Если сверятель не поддерживает создание остатков, он должен немедленно вернуть значение REC_E_NORESIDUES, если только параметр dwFlags не задаёт значение RECONCILEF_NORESIDUESOK.

Примиритель портфеля возвращает остатки инициатору путем создания новых элементов хранилища и копирования их в массив, на который указывает pstgNewResidues. Для структурированных остатков хранилища примиритель копирует интерфейс IStorage, а для плоских остатков хранилища копирует IStream или интерфейс IStorage с установленным флагом STATEBITS_FLAT. Примиритель использует IStorage для создания необходимого хранилища, используя IStorage::CreateStream для создания плоского хранилища для остатка, который является потоком данных, и IStorage::CreateStorage для создания структурированного хранилища.

Инициатор подготавливает pstgNewResidues так, чтобы он не содержал элементов в незарезервированной части пространства имен IStorage. Примиритель портфеля помещает каждый остатк в элемент, имя которого соответствует порядку его начальной версии. Например, первый остатк содержится в "1", второй в "2" и т. д. Если объединенный объект создает остаток, он найден в элементе с именем "0".

Согласователь портфеля закрепляет каждый из вновь созданных элементов по отдельности, гарантируя, что инициатор имеет доступ к информации. Однако согласователь не фиксирует pstgNewResidues сам. Инициатор отвечает за выполнение этого или иную утилизацию.

Справочник по примирителям в кратком регистре

В этом разделе содержатся сведения об интерфейсах выверки. При обработке ошибок метод может возвращать только те значения ошибок, которые явно определены как возможные возвращаемые значения. Кроме того, метод должен установить все переменные, адреса которых передаются в качестве параметров, в значение NULL перед возвратом в случае ошибки.

Интерфейсы и методы для синхронизации данных портфеля