Создание Resource Manager

Диспетчеры ресурсов поддерживают данные каждой транзакции и регистрируют ее операции. Если в системе обработки транзакций (TPS) есть несколько диспетчеров ресурсов, каждый диспетчер ресурсов может участвовать в операциях фиксации, отката и восстановления каждой транзакции.

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

Как правило, диспетчер ресурсов в режиме ядра должен выполнять следующие задачи в указанном порядке:

  1. Создайте поток журнала.

    Диспетчеры ресурсов могут использовать общую файловую систему журналов (CLFS) или другие возможности ведения журнала для обслуживания своих потоков журналов. Вызов ClfsCreateLogFile создает поток журнала CLFS. Диспетчер ресурсов должен использовать поток журнала для записи любых сведений, необходимых для фиксации, отката или восстановления транзакций. Кроме того, KTM использует поток журналов для записи любых изменений внутреннего состояния, которые могут потребоваться для восстановления транзакций.

  2. Создайте объект диспетчера транзакций.

    Вызов ZwCreateTransactionManager создает объект диспетчера транзакций и подключает диспетчер ресурсов к дополнительному потоку журнала CLFS, заданному диспетчером ресурсов.

  3. Восстановление состояния диспетчера транзакций.

    Вызов ZwRecoverTransactionManager считывает поток журнала объекта диспетчера транзакций (который поддерживает KTM) и определяет, был ли TPS завершен до завершения всех транзакций (например, из-за сбоя системы). KTM восстанавливает свое внутреннее состояние на основе сведений в потоке журнала.

  4. Создайте объект Resource Manager.

    Вызов ZwCreateResourceManager создает объект Resource Manager и связывает его с ранее созданным объектом диспетчера транзакций.

  5. Восстановление состояния диспетчера ресурсов.

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

  6. Получение транзакций от клиентов.

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

  7. Прикручить к каждой транзакции.

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

  8. Включение получения уведомлений о транзакциях.

    Диспетчер ресурсов может вызвать ZwGetNotificationResourceManager для синхронного получения уведомлений или вызвать TmEnableCallbacks , чтобы зарегистрировать подпрограмму обратного вызова ResourceManagerNotification , которая вызывается KTM при появлении уведомления.

  9. Запросы доступа к ресурсам службы от клиентов, но не делают изменения постоянными.

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

    Диспетчер ресурсов должен записывать результаты операций чтения и записи в потоке журналов CLFS или другой возможности ведения журнала, пока не получит уведомление о том, что операции транзакции будут зафиксированы, откаты или восстановлены.

  10. Фиксация или откат клиентских операций.

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

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

  11. Закройте дескриптор объекта зачисления.

    После завершения обработки транзакции диспетчер ресурсов должен вызвать ZwClose , чтобы закрыть дескриптор объекта зачисления.

  12. Закройте дескриптор объекта resource manager и дескриптор объекта диспетчера транзакций.

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

Шаги 1–5 необходимо выполнить в коде инициализации диспетчера ресурсов. Например, если диспетчер ресурсов является драйвером в режиме ядра, код инициализации — это подпрограмма DriverEntry драйвера.

Шаги 6–11 обычно выполняются в коде, который отвечает на запросы от транзакционных клиентов.

Шаг 12 необходимо выполнить в окончательном коде очистки диспетчера ресурсов, например в подпрограмме выгрузки драйвера в режиме ядра.

Создание Read-Only зачисления

Зачисление только для чтения — это зачисление, которое не получает никаких уведомлений от KTM. Диспетчер ресурсов может сделать любое зачисление доступной только для чтения, вызвав ZwReadOnlyEnlistment. Этот вызов приводит к прекращению доставки уведомлений диспетчеру ресурсов KTM.

После того как диспетчер ресурсов вызовет ZwCreateEnlistment, он может вызвать ZwReadOnlyEnlistment в любое время до момента, когда он обычно вызывает ZwPrepareComplete.

Существует две причины, по которым диспетчер ресурсов может вызвать ZwReadOnlyEnlistment.

  • Диспетчер ресурсов участвует в транзакции, и в какой-то момент, прежде чем он получит уведомление TRANSACTION_NOTIFY_COMMIT, диспетчер ресурсов определяет, что он больше не должен участвовать в операции фиксации транзакции.

    Например, когда диспетчер ресурсов получает уведомление TRANSACTION_NOTIFY_PREPARE, он может определить, что ни одна из операций транзакции не изменила базу данных диспетчера ресурсов. Диспетчер ресурсов может вызвать ZwReadOnlyEnlistment вместо ZwPrepareComplete, чтобы удалить себя из транзакции.

  • Диспетчер ресурсов никогда не участвует в операциях фиксации транзакций.

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

После того как диспетчер ресурсов вызовет ZwReadOnlyEnlistment, он может вызвать ZwClose , чтобы закрыть дескриптор зачисления.

Создание диспетчера Volatile-Resource

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

Диспетчер переменных ресурсов должен установить флаг RESOURCE_MANAGER_VOLATILE при вызове ZwCreateResourceManager. Если этот флаг установлен, KTM не регистрирует сведения о диспетчере ресурсов в потоке журнала связанного объекта диспетчера транзакций.

Диспетчер ресурсов также может задать флаг TRANSACTION_MANAGER_VOLATILE при вызове ZwCreateTransactionManager. Если этот флаг установлен, KTM не создает поток журнала для объекта диспетчера транзакций. Кроме того, все дополнительные диспетчеры ресурсов, подключенные к объекту диспетчера транзакций, также должны быть переменными и устанавливать флаг RESOURCE_MANAGER_VOLATILE.

Добавление Resource Manager в существующую TPS

Если вам нужно добавить дополнительный диспетчер ресурсов в существующую TPS, у вас есть два варианта:

  • Новый диспетчер ресурсов вызывает ZwCreateTransactionManager для создания собственного объекта диспетчера транзакций.

    Используйте этот вариант, если диспетчер ресурсов не взаимодействует с другими диспетчерами ресурсов в TPS.

  • Новый диспетчер ресурсов вызывает ZwOpenTransactionManager для подключения к существующему объекту диспетчера транзакций.

    Используйте этот вариант, если диспетчер ресурсов должен взаимодействовать с другими диспетчерами ресурсов в TPS. Диспетчер ресурсов, вызывающий ZwCreateTransactionManager , должен совместно использовать GUID объекта диспетчера транзакций, имя потока журнала или имя объекта, чтобы другие диспетчеры ресурсов могли вызывать ZwOpenTransactionManager. Эти другие диспетчеры ресурсов могут вызывать ZwQueryInformationTransactionManager для получения дополнительных сведений об объекте диспетчера транзакций.

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