Partager via


Présentation des composants TPS

Tout système de traitement des transactions (TPS) qui utilise le Gestionnaire de transactions du noyau (KTM) et le système de fichiers journaux communs (CLFS) doivent contenir les composants importants suivants :

  • Un gestionnaire de transactions (KTM)

    KTM suit l’état de chaque transaction et coordonne les opérations de récupération après un incident système.

  • Un ou plusieurs gestionnaires de ressources

    Les gestionnaires de ressources que vous fournissez gèrent les données associées à chaque transaction.

  • Un ou plusieurs flux de journaux CLFS

    Le gestionnaire de transactions et les gestionnaires de ressources utilisent des flux de journaux CLFS pour enregistrer des informations qu’ils peuvent utiliser pour valider, restaurer ou récupérer une transaction.

  • Un ou plusieurs clients transactionnels

    En règle générale, chaque client transactionnel de votre TPS peut créer une transaction, effectuer des opérations sur des données dans le contexte de la transaction, puis lancer une opération de validation ou de restauration pour la transaction.

Cet article vous présente un tpS simple avec un gestionnaire de ressources, un TPS plus complexe qui contient plusieurs gestionnaires de ressources et d’autres scénarios TPS.

La section Using KTM fournit des informations détaillées sur l’utilisation de KTM pour créer des composants TPS.

Simple TPS

Un TPS simple peut se composer de KTM, d’un gestionnaire de ressources et de CLFS. Les clients transactionnels peuvent communiquer avec le gestionnaire de ressources via une interface que le gestionnaire de ressources fournit.

Par exemple, supposons que vous souhaitez créer un système de gestion de base de données. Vous souhaitez que les clients de votre système accèdent à la base de données en ouvrant un handle à un objet de base de données, en effectuant des opérations de lecture et d’écriture sur l’objet, puis en fermant le handle d’objet.

Supposons maintenant que vous souhaitez que des ensembles d’opérations de lecture et d’écriture se produisent de manière atomique afin que les autres utilisateurs du système voient uniquement le résultat final. Vous pouvez atteindre cet objectif en concevant un TPS qui permet aux clients de lier des ensembles d’opérations de base de données à une transaction.

Votre système doit inclure un gestionnaire de ressources qui gère les données de la base de données en réponse aux demandes de lecture et d’écriture des clients. Ce gestionnaire de ressources peut exporter une interface de programmation d’application (API) qui permet aux clients d’associer une transaction à un ensemble d’opérations de lecture et d’écriture.

Lorsque vous chargez votre gestionnaire de ressources, il doit s’inscrire auprès de KTM en appelant ZwCreateTransactionManager et ZwCreateResourceManager. Ensuite, le gestionnaire de ressources peut participer aux transactions.

Vous souhaiterez peut-être que votre gestionnaire de ressources prend en charge un ensemble de fonctions qui permettent aux clients de créer des objets de données, de lire et d’écrire des données associées aux objets de données et de fermer les objets de données. Le pseudocode suivant montre un exemple de séquence de code à partir d’un client.

CreateDataObject (IN TransactionID, OUT DataHandle);
ReadData (IN DataHandle, OUT Data);
WriteData (IN DataHandle, IN Data);
WriteData (IN DataHandle, IN Data);
WriteData (IN DataHandle, IN Data);
CloseDataObject (IN DataHandle);

Avant qu’un client puisse appeler la routine CreateDataObject de votre gestionnaire de ressources, le client doit créer un objet transaction en appelant la routine ZwCreateTransaction de KTM et en obtenant l’identificateur de l’objet transaction en appelant ZwQueryInformationTransaction.

Lorsque le client appelle la routine CreateDataObject de votre gestionnaire de ressources, le client transmet l’identificateur de l’objet transaction au gestionnaire de ressources. Le gestionnaire de ressources peut appeler ZwOpenTransaction pour obtenir un handle à l’objet de transaction, puis appeler ZwCreateEnlistment pour inscrire sa participation à la transaction.

À ce stade, le client peut commencer à effectuer des opérations sur l’objet de données. Étant donné que le client a fourni un identificateur de transaction lorsqu’il a créé l’objet de données, le gestionnaire de ressources peut affecter toutes les opérations de lecture et d’écriture à la transaction.

Votre gestionnaire de ressources doit enregistrer tous les résultats des opérations de données spécifiées par le client sans rendre les résultats permanents. En règle générale, le gestionnaire de ressources utilise CLFS pour enregistrer les résultats de l’opération dans un flux de journal des transactions.

Lorsque le client termine l’appel du gestionnaire de ressources pour effectuer des opérations transactionnelles, il appelle la routine ZwCommitTransaction de KTM. À ce stade, KTM informe le gestionnaire de ressources qu’il doit rendre les opérations permanentes . Le gestionnaire de ressources déplace ensuite les résultats de l’opération du flux de journal vers le support de stockage permanent des données. Enfin, le gestionnaire de ressources appelle ZwCommitComplete pour informer KTM que l’opération de validation est terminée.

Que se passe-t-il si votre gestionnaire de ressources signale une erreur pour l’un des appels du client à ReadData ou WriteData ? Le client peut appeler ZwRollbackTransaction pour restaurer la transaction. À la suite de cet appel, KTM informe le gestionnaire de ressources qu’il doit restaurer les données à son état d’origine. Ensuite, le client peut créer une transaction pour les mêmes opérations, ou choisir de ne pas continuer.

Le pseudocode suivant montre un exemple de séquence plus détaillée des opérations transactionnelles d’un client.

    ZwCreateTransaction (&TransactionHandle, ...);
    ZwQueryInformationTransaction (TransactionHandle, ...);
    CreateDataObject (TransactionID, &DataHandle);
    Status = ReadData (DataHandle, &Data1);
    if (Status == Error) goto ErrorRollback;
    Status = WriteData (DataHandle, Data2);
    if (Status == Error) goto ErrorRollback;
    Status = WriteData (DataHandle, Data3);
    if (Status == Error) goto ErrorRollback;
    Status = WriteData (DataHandle, Data4);
    if (Status == Error) goto ErrorRollback;
    ZwCommitTransaction (TransactionHandle, ...);
    goto Leave;
ErrorRollback:
    ZwRollbackTransaction (TransactionHandle, ...);
Leave:
    ZwClose (TransactionHandle);
    return;

Que se passe-t-il si le système se bloque après la création de la transaction, mais avant qu’il ne soit validé ou restauré ? Chaque fois que votre gestionnaire de ressources se charge, il doit appeler ZwRecoverTransactionManager et ZwRecoverResourceManager. L’appel de ZwRecoverTransactionManager permet à KTM d’ouvrir son flux de journal et de lire l’historique des transactions. L’appel de ZwRecoverResourceManager permet à KTM de notifier le gestionnaire de ressources de toutes les transactions inscrites en cours avant le blocage et les transactions que le gestionnaire de ressources doit donc récupérer.

Si un client transactionnel appelé ZwCommitTransaction pour une transaction avant le blocage et a commencé à gérer les opérations de validation pour la transaction, le gestionnaire de ressources doit pouvoir restaurer l’état de la transaction au point juste avant le blocage. Si le client n'était pas prêt à valider la transaction avant le crash, le gestionnaire de ressources peut ignorer les données et annuler la transaction.

Pour plus d’informations sur l’écriture de clients transactionnels, consultez Création d’un client transactionnel.

Pour plus d’informations sur l’écriture de gestionnaires de ressources, consultez Création d’un Gestionnaire de ressources.

Plusieurs gestionnaires de ressources dans un TPS

Supposons maintenant que votre TPS permet aux clients de modifier des informations dans deux bases de données distinctes au sein d’une transaction unique, afin que la transaction réussisse uniquement si les modifications des deux bases de données réussissent.

Dans ce cas, votre TPS peut avoir deux gestionnaires de ressources, un pour chaque base de données. Chaque gestionnaire de ressources peut exporter une API que les clients peuvent utiliser pour accéder à la base de données du gestionnaire de ressources.

Le pseudocode suivant montre comment un client peut créer une transaction unique qui contient des opérations sur deux bases de données que deux gestionnaires de ressources prennent en charge.

Dans cet exemple, le client lit les données de la première base de données et les écrit dans la deuxième base de données. Ensuite, le client lit les données de la deuxième base de données et les écrit dans la première base de données. (Le premier gestionnaire de ressources exporte les fonctions qui commencent par Rm1, et le deuxième gestionnaire de ressources exporte les fonctions qui commencent par Rm2.)

    ZwCreateTransaction (&TransactionHandle, ...);
    ZwQueryInformationTransaction (TransactionHandle, ...);
    Rm1CreateDataObject (TransactionID, &Rm1DataHandle);
    Rm2CreateDataObject (TransactionID, &Rm2DataHandle);
    Status = Rm1ReadData (Rm1DataHandle, &Rm1Data);
    if (Status == Error) goto ErrorRollback;
    Status = Rm2WriteData (Rm2DataHandle, Rm1Data);
    if (Status == Error) goto ErrorRollback;
    Status = Rm2ReadData (Rm2DataHandle, &Rm2Data);
    if (Status == Error) goto ErrorRollback;
    Status = Rm1WriteData (Rm1DataHandle, Rm2Data);
    if (Status == Error) goto ErrorRollback;
    ZwCommitTransaction (TransactionHandle, ...);
    goto Leave;
ErrorRollback:
    ZwRollbackTransaction (TransactionHandle, ...);
Leave:
    ZwClose (TransactionHandle);
    return;

Étant donné que le client transmet le même identificateur de transaction aux deux gestionnaires de ressources, les deux gestionnaires de ressources peuvent appeler ZwOpenTransaction et ZwCreateEnlistment pour s’inscrire dans la transaction. Lorsque le client appelle éventuellement ZwCommitTransaction, KTM informe chaque gestionnaire de ressources que le gestionnaire doit rendre les opérations permanentes , et chaque gestionnaire de ressources appelle ZwCommitComplete lorsqu’il se termine.

Autres scénarios TPS

KTM prend en charge d’autres scénarios TPS. Par exemple, les scénarios suivants décrivent les composants qu’un TPS peut contenir :

  • Un gestionnaire de ressources qui gère plusieurs bases de données.

    L’API du gestionnaire de ressources peut permettre aux clients d’ouvrir et d’accéder à plusieurs bases de données à la fois, et le client peut combiner les accès à plusieurs bases de données dans une seule transaction.

  • Un gestionnaire de ressources avec une API appelée par les clients, et d’autres gestionnaires de ressources avec des API que le premier gestionnaire de ressources appelle.

    Le client communique uniquement avec le premier gestionnaire de ressources. Lorsque ce gestionnaire de ressources traite les demandes d’un client, il peut accéder aux gestionnaires de ressources supplémentaires, le cas échéant, pour traiter les demandes du client. Par exemple, un gestionnaire de ressources gère une base de données accessible au client qui nécessite des opérations de sauvegarde ou de vérification des données à partir d’un deuxième gestionnaire de ressources auquel les clients ne peuvent pas accéder.

  • Un client et un gestionnaire de ressources existants qui n’utilisent pas KTM, intégrés à un ensemble supplémentaire de gestionnaires de ressources qui utilisent KTM.

    Dans ce cas, vous devez généralement modifier le gestionnaire de ressources existant afin qu’il devienne un gestionnaire de transactions supérieur qui communique avec KTM.