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 CLFS (Common Log File System ) doit 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 plantage du 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 qui peuvent être utilisées 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 les données dans le contexte de la transaction, puis lancer une opération de validation ou de restauration pour la transaction.
Cette rubrique 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 Utilisation de 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 à l’aide d’une interface que le gestionnaire de ressources fournit.
Par exemple, supposons que vous souhaitiez 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 sur 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 atomiquement 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’applications (API) qui permet aux clients d’associer une transaction à un ensemble d’opérations de lecture et d’écriture.
Lorsque votre gestionnaire de ressources est chargé, il doit s’inscrire auprès de KTM en appelant ZwCreateTransactionManager et ZwCreateResourceManager. Ensuite, le gestionnaire de ressources peut participer à des 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 pseudo-code 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, il doit créer un objet transaction en appelant la routine ZwCreateTransaction de KTM et obtenir 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 pour l’objet transaction, puis il peut 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 lors de la création de 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 que le client spécifie 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 a terminé d’appeler le gestionnaire de ressources pour effectuer des opérations transactionnelles, il appelle la routine ZwCommitTransaction de KTM. À ce stade, KTM avertit le responsable des 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 journaux 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 annuler la transaction. À la suite de cet appel, KTM informe le gestionnaire de ressources qu’il doit restaurer les données à leur état d’origine. Ensuite, le client peut soit créer une transaction pour les mêmes opérations, soit choisir de ne pas continuer.
Le pseudocode suivant montre un exemple d’une 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’elle soit validée ou restaurée ? 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 d’informer le gestionnaire de ressources de toutes les transactions inscrites qui étaient en cours avant l’incident et des transactions que le gestionnaire de ressources doit donc récupérer.
Si un client transactionnel appelé ZwCommitTransaction pour une transaction avant l’incident et a commencé à gérer les opérations de validation pour la transaction, le gestionnaire de ressources doit être en mesure de restaurer l’état de la transaction au point juste avant l’incident. Si le client n’était pas prêt à valider la transaction avant l’incident, le gestionnaire de ressources peut ignorer les données et restaurer 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 des gestionnaires de ressources, consultez Création d’un Resource Manager.
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 même transaction, 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 pseudo-code suivant montre comment un client peut créer une transaction unique qui contient des opérations sur deux bases de données prises en charge par deux gestionnaires de ressources.
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 avertit chaque gestionnaire de ressources que le responsable doit rendre les opérations permanentes, et chaque gestionnaire de ressources appelle ZwCommitComplete quand il a terminé.
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 en une seule transaction.
Un gestionnaire de ressources avec une API que les clients appellent, 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, si nécessaire, pour traiter les demandes du client. Par exemple, un gestionnaire de ressources gère une base de données accessible par le client qui nécessite des opérations de sauvegarde ou de vérification des données à partir d’un deuxième gestionnaire de ressources qui n’est pas disponible pour les clients.
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.