la notion de groupe d'activation est un concept apparu avec ILE. il permet de cloisonnement des applications à l'intérieur d'un job. + cela apporte une influence sur la portée d'un ouverture en SHARE(*YES) si un programme CLP (dans *DFTACTGRP) ouvre un fichier par OPNQRYF (en SHARE(*YES) donc) et appel un progamme GAP4 : - si le programme GAP4 a été compilé DFTACTGRP(*YES) il subira l'influence de la commande OPNQRYF - si le programme GAP4 a été compilé DFTACTGRP(*NO) DFTACTGRP(xxx) [QILE par ex.] il traitera le fichier dans sa totalité (OPNQRYF ignoré) + cela apporte une influence sur la portée d'un STRCMTCTL la transaction est limité au groupe d'activation CMTSCOPE(*ACTGRP) ou bien est étendue à la totalité du JOB CMTSCOPE(*JOB) |
+ cela influence la gestion des erreurs en ILE, un programme qui ne monitore pas une erreur, voit la même erreur retransmise au programme appellant s'il est dans le même groupe d'activation. A la sortie du groupe (frontière) on recoit CEE9901. + et enfin cela peut modifier profondement l'utilisation de la commande RCLRSC , et donc les fichiers qui restent ouverts. la documentation dit la chose suivante : la commande RCLRSC n'a de portée qu'à l'intérieur du groupe d'activation par défaut. pour un groupe d'activation nommé, il faut utiliser RCLACTGRP un programme ne peut pas passer la commande RCLACTGRP pour le groupe auquel il appartient (contrairement à RCLRSC) |
prenons un exemple : PGM (ACTGRP1) DCL &REP *CHAR 1 CALL ACTGRP2 SNDUSRMSG MSG('rclrsc ?') TOMSGQ(*EXT) MSGRPY(&REP) IF (&REP = 'O') THEN(DO) RCLRSC ENDDO ENDPGM ce premier programme est un CLP PGM (ACTGRP2) CALL ACTGRP3 ENDPGM ce deuxième est un CLLE compilé par CRTBNDCL DFTACTGRP(*YES) |
(ACTGRP3) * Ffichier1 uf e k disk c read fmt1 c call 'ACTGRP4' c return (ACTGRP4) * Ffichier2 uf e k disk c read fmt2 c return ces deux là sont des RPGLE compilés avec CRTBNDRPG DFTACTGRP(*YES) après CALL ACTGRP1, si l'on répond 'O' à la question "rclrsc ?" les fichiers sont bien fermés (DSPJOB option 14) si l'on répond 'N' à la question, les fichiers restent ouverts ,les enregistrements, verrouillés.(DSPRCDLCK) la commande RCLRSC sur la ligne de commande ferme les fichiers |
essayons en passant la commande RCLRSC depuis un RPG (*DFTACTGRP lui aussi) Dcde s 6 inz('RCLRSC') Dcde_lg s 15 5 inz(%len(cde)) Dreponse s 1 c call 'ACTGRP2' c 'rclrsc ?' dsply '*EXT' reponse c if reponse = 'O' c call 'QCMDEXC' c parm cde c parm cde_lg c endif c eval *inlr = *on nous constatons exactement le même fonctionnement. si des programmes RPG sont compilés par l'option par défaut sans modifier les valeurs standard de compilation, cela fonctionne comme au temps du GAP III (comme s'il n'y avait pas de groupe d'activation) |
mais si vous souhaitez utiliser cette notion de groupe d'activation ou si vous linkez vos programmes (ou programme de service) en laissant la valeur par défaut (groupe d'activation nommé QILE) voilà ce qui se passe : nous compilons ACTGRP2, 3 et 4 dans QILE lancons ACTGRP1, les fichiers restent ouverts (avec ou sans RCLRSC), RCLRSC sur la ligne de commande n'a pas d'effet. IL FAUT PASSER la commande RCLACTGRP QILE pour fermer les fichiers. modifions ACTGRP2 : PGM (ACTGRP2) CALL ACTGRP3 rclactgrp QILE ENDPGM puis compilons le dans le groupe d'activation QILE, le même que ACTGRP3/4. |
ACTGRP2 recoit CPF1654 :"Activation Groupe QILE cannot be deleted" si ACTGRP2 est placé dans un groupe d'activation différent ou dans le groupe d'activation par défaut, tout se passe bien, les fichiers sont bien fermés. Le problème est bien réel avec les programmes de services utilisant des fichiers base de données avec des spécifs F globales. si le programme de service est dans *DFTACTGRP, la commande RCLRSC ferme les fichiers ouverts par le programme de service, mais le programme de service reste chargé en mémoire. Lors d'un deuxième appel (suite à RCLRSC), il plante avec MCH3401 "Tentative d'accès à tout ou partie d'un objet qui n'existe plus." en effet le code étant resté en mémoire il cherche à utiliser l'ODP (le résultat d'un ordre OPEN) qui a été détruit par le RCLRSC. |
il faut alors placer le programe de service dans un groupe spécifique (mettons FONCTIONS), si vous acceptez que les fichiers restent ouverts continuellement. RCLRSC ne fermant que les fichiers ouverts par les pgm dans *DFTACTGRP Si vous souhaitez fermer les fichiers ouverts par le *SRVPGM - placez tous vos programmes applicatifs dans un groupe nommé et compilez vos programmes de service avec ACTGRP(*CALLER). [val. par défaut] - gérez les OPEN et les CLOSE dans le programme de service (-> V5R40) (fichier en USROPN puis OPEN et CLOSE dans le code) - Utilisez la nouveauté V6 permettant de placer une spécif F locale c.a.d dans la fonction elle même. P MAfonction B FMONFICHIERIF E disk ... |
Attention, dans ce cas : Vous devez faire vos entrées/sortie via DS (autre nouveauté V6) les fichiers sont fermés automatiquement à la fin de la procédure, sauf à utiliser STATIC, qui garde les fichier ouverts et les variables chargées. Exemple ------- P lecture B Fvins IF E DISK QUALIFIED D PI 50 D code 10I 0 CONST Din DS LIKEREC(vins.vins) /free chain code vins IN; return IN.VIN_NOM; /end-free P lecture E |
en conclusion : si vous souhaitez rendre vos applications plus indépendantes les unes des autres (contrôle de validation, limite de la portée d'un OPNQRYF) et mieux gérer vos programmes de service : utilisez un groupe d'activation nommé (QILE par exemple), lancé par un CL situé dans un autre (*DFTACTGRP ?) qui se termine par RCLACTGRP QILE. Si vous ne souhaitez pas utiliser ces notions, compilez par: CRTBDNRPG DFTACTGRP(*YES) valeur par défaut. ou ... DFTACTGRP(*NO) ACTGRP(*caller) certaines API imposent DFTACTGRP(*NO) ou bien CRTPGM ACTGRP(*CALLER) si vous linkez des procédures. mais surveillez les "effets de bord..." (*SRVPGM avec spécif F globale) |