Transactions
Up ! 5GL permet de créer des applications utilisées en multi-utilisateurs, par exemple pour l'informatique de gestion. Sans précaution particulière, l'application permettrait à un premier utilisateur de modifier les propriétés de plusieurs objets pendant qu'un autre utilisateur serait en train de consulter les propriétés de ces mêmes objets.
S'il n'y a pas de relation entre ces objets, cela est sans conséquence. Mais bien souvent, il existe des règles de gestion, voire des contraintes, imposant que les données soient cohérentes, par exemple en comptabilité lors de mouvements entre comptes.
De ce fait, l'application doit ce comporter comme suit :
- Pour laisser les données cohérentes aux yeux des autres utilisateurs, les modifications connexes doivent être effectuées simultanément.
- Si une des modifications est impossible, parce qu'une contrainte d'intégrité est violée, alors toutes les modifications connexes sont annulées.
Avec ce principe de transaction, les données de l'application restent toujours cohérentes.
Concept de transaction
Une transaction est représentée par un objet du type Transaction. A chaque tâche est associée une transaction qui est créée au lancement de celle-ci. Cette transaction va mémoriser les modifications apportées à chaque objet transactionnel :
- La création d'un nouvel objet transactionnel.
- La modification des objets transactionnels.
- La destruction d'un objet transactionnel.
Tant que la transaction n'est pas validée, ces modifications ne sont visibles que pour la tâche les ayant effectuées. Pour les autres tâches, la transaction assure de ne pas voir :
- Les objets transactionnels créés durant la transaction.
- Les modifications des objets transactionnels non validées.
- Les objets transactionnels détruits durant la transaction.
La validation d'une transaction est demandée par l'appel à la méthode Valider. Up ! Object Management System vérifie alors si les créations, les modifications et les destructions sont licites au regard des contraintes d'intégrité déclarées sur les types des objets ou de leurs propriétés au moyen de l'instruction Contrainte. Pour que la validation ait lieu, aucune contrainte ne doit être mise en défaut. Sinon la transaction est invalidée i.e. les modifications apportées sont annulées et l'exception ValidationImpossible est envoyée.
Une fois la validation établie, les modifications sont définitives et rendues visibles aux autres tâches.
Il est possible d'invalider explicitement les modifications mémorisées par une transaction par l'appel à la méthode Invalider.
Objets transactionnels
Tous les objets ne sont pas gérés selon le principe de transaction. Cela serait trop coûteux en ressources. Pour que les objets d'un type soient gérés selon le principe des transactions, il est nécessaire que le type soit déclaré avec l'attribut Transactionnel.
Quand un type de données n'est pas transactionnel, alors les modifications qui sont apportées à ses objets sont immédiatement visibles par les autres tâches que celle les ayant effectuées.
Imbrication des transactions
Il est possible de déclarer une nouvelle transaction locale à un traitement. En ce cas, elle est imbriquée dans la transaction déjà ouverte. Les modifications des objets transactionnels sont alors mémorisées par cette transaction imbriquée. Cette transaction imbriquée existe temps que l'objet l'identifiant n'est pas détruit i.e temps qu'il est référencé.
La validation ou l'invalidation d'une transaction n'affecte que les modifications mémorisées par celle-ci ainsi que celles de son éventuelle transaction fille :
- Demander à valider une transaction demande en premier lieu de valider les modifications de sa transaction fille. La validation n'a lieu que si les modifications des deux transactions peuvent être validées, et ceci récursivement.
- Invalider une transaction invalide la transaction fille, et ceci récursivement.
Transactions distribuées
Les transactions s'appliquent à tous les objets transactionnels. Cependant, ces derniers peuvent être conservés dans des entrepôts publics qui ne sont pas gérées par le processus de rattachement de la tâche ayant fait les modifications. En ce cas, la demande de validation s'effectue en deux temps selon le principe de la validation en deux temps :
- La demande de validation est publiée à chaque serveur impliqué dans la transaction.
- Chaque serveur vérifie que la validation est possible localement sans pour autant rendre les modifications définitives et rendues visibles aux autres tâches.
- Si un des serveurs ne peut valider la transaction, alors la demande d'annulation des modifications est publiée à chaque serveur impliqué dans la transaction. La transaction est invalidée.
- Si tous les serveurs peuvent valider la transaction, alors la demande de modification définitive est publiée à chaque serveur impliqué dans la transaction. La transaction est alors validée.
Invalidations automatiques des transactions
En règle générale, les transactions sont invalidées lorsque l'appel à la méthode Valider échoue ou lors de l'appel à la méthode Invalider. Cependant, il se peut qu'il existe un imprévu aie lieu dans le programme suite à une exception ou suite à un dysfonctionnement. En ce cas, les transactions ouvertes de la tâche essuyant cet imprévu sont automatiquement invalidées. Voici de tels cas de figure :
- Les objets locaux à un appel sont automatiquement détruits à la fin de cet appel s'il n'y plus aucune référence envers eux. La destruction d'un objet de type Transaction cause l'invalidation automatique de la transaction.
- Une exception est envoyée. Les objets locaux sont automatiquement détruits s'il n'y plus aucune référence envers eux pour chaque appel dépilé ne rattrapant par cette exception. La destruction d'un objet de type Transaction cause l'invalidation automatique de la transaction.
- La tâche est arrêtée par l'appel à la méthode ArreterTache. Toutes les transactions ouvertes par la tâche sont automatiquement invalidées.
- Le programme est arrêté par l'appel à la procédure ArreterProgramme. Toutes les transactions ouvertes par toutes les tâches du programme sont automatiquement invalidées.
- Le programme est arrêté suite à un dysfonctionnement. Toutes les transactions ouvertes par toutes les tâches du programme sont automatiquement invalidées. Cela nécessite néanmoins que la tâche Moniteur soit lancée.
Photographies des données
Il se peut que l'application nécessite de réaliser des calculs qui doivent être inchangées tout au long de ceux-ci. Dans une application multi-utilisateurs ou multi-tâches, il est très difficile de s'assurer que les données ne sont pas modifiées alors qu'un algorithme est en cours. De plus, cela aurait pour effet de bloquer le travail des autres tâches.
Pour remédier à cela, Up ! Application System comporte le concept de photographie : il est possible de demander à prendre une photographie figeant l'état des objets transactionnels le temps nécessaire à un algorithme par appel à la procédure Photographier. Si d'autres tâches modifient des objets transactionnels et valident leurs modifications, ces dernières ne seront pas visibles pour la tâche ayant demandé une photographie temps que cette celle-ci dure.
Un second appel à la procédure Photographier permet de supprimer la photographie. A l'issu, la tâche voit alors les modifications des objets transactionnels validées par les autres tâches durant la photographie.
Entrepôts de retour
Avant qu'un objet transactionnel ne soit modifié, son image avant, constituée des valeurs de ses propriétés, est conservée en vue de pouvoir :
- Invalider la transaction.
- Présenter les valeurs des objets transactionnels avant modification pour les autres tâches que celle l'ayant modifié sans validation.
- Présenter les valeurs des objets transactionnels au moment de la photographie pour les tâches ayant demandé une photographie des données.
Cette image avant est conservée dans un entrepôt spécial appelé entrepôt de retour. Par défaut, il s'agit de l'entrepôt EntrepotSysteme, mais il est possible de la désigner au moyen du paramètre entrepotretour de la configuration d'Up ! Object Management System.
Si l'application utilise au moins un entrepôt protégé, i.e. partagé entre plusieurs processus d'une même machine, alors l'entrepôt de retour doit être protégé. Si l'application utilise au moins un entrepôt public, i.e. partagé entre plusieurs processus de plusieurs machines, alors l'entrepôt de retour doit être public.
Selon le volume de transactions que réalise l'application, vous pouvez régler le nombre d'images avants simultanément allouées avec le paramètre maximageavant. Pour plus de précisions, veuillez vous reporter à la configuration d'Up ! Object Management System.