/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        G E S T I O N   D E S   P H A S E S   C R I T I Q U E S  :                                                                 */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Utilisation :                                                                                                              */
/*                                                                                                                                   */
/*                    Cette commande est a priori destinee a permettre                                                               */
/*                  le remplacement de :                                                                                             */
/*                                                                                                                                   */
/*                                      $xEa/PhasCriB$vv$Y                                                                           */
/*                                      $xEa/PhasCriE$vv$Y                                                                           */
/*                                                                                                                                   */
/*                  par :                                                                                                            */
/*                                                                                                                                   */
/*                                      $xEa/PhasCriB.PhaseCrit.01$vv$Y                                                              */
/*                                      $xEa/PhasCriE.PhaseCrit.01$vv$Y                                                              */
/*                                                                                                                                   */
/*                  dans la definition des alias {PhasCriB,PhasCriE} via                                                             */
/*                  les variables {$Falias_PhasCriB,$Falias_PhasCriE}.                                                               */
/*                                                                                                                                   */
/*                    Les experiences de chronometrage reposant sur une iteration de                                                 */
/*                  la simple suite de commandes {PhasCriB,PhasCriE} montrent que                                                    */
/*                  malheureusement le gain semble strictement nul (a la seconde                                                     */
/*                  pres), ce que j'ai du mal a comprendre...                                                                        */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xcg/PhaseCrit.01$K' :                                                                                          */
/*                                                                                                                                   */
/*                    Jean-Francois COLONNA (LACTAMME, 20110531095911).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        I N T E R F A C E   ' listG '  :                                                                                           */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        :Debut_listG:                                                                                                              */
/*        :Fin_listG:                                                                                                                */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D I R E C T I V E S   S P E C I F I Q U E S   D E   C O M P I L A T I O N  :                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
@define   PRAGMA_CL_____PAS_DE_LIBRAIRIES_DYNAMIQUES

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F I C H I E R S   D ' I N C L U D E S  :                                                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#include  INCLUDES_MINI

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        P A R A M E T R E S  :                                                                                                     */
/*                                                                                                                                   */
/*===================================================================================================================================*/
#define   ENTRER_DANS_UNE_PHASE_CRITIQUE                                                                                                \
                    VRAI                                                                                                                \
                                        /* Il y a deux modes de fonctionnement : entree ou 'Begin' ('VRAI') et sortie ou 'End'       */ \
                                        /* ('FAUX').                                                                                 */

#define   FORCER_L_ENTREE_DANS_UNE_PHASE_CRITIQUE_QUEL_QUE_SOIT_L_ETAT_DU_FICHIER                                                       \
                    VRAI                                                                                                                \
                                        /* Il y a deux modes de fonctionnement lors de l'entree en phase critique : l'un autorisant  */ \
                                        /* l'absence du fichier ('VRAI') et l'autre pas ('FAUX')...                                  */

#if       (         (defined(CMAP28))                                                                                                   \
           )
                                        /* Introduit le 20070423134356...                                                            */
#    define    PRE_METTRE_A_JOUR_LE_CACHE_DES_DIRECTORIES                                                                               \
                         VRAI                                                                                                           \
                                        /* Si 'IL_NE_FAUT_PAS(executer_une_sequence_en_parallele)' faut-il tenter de pre-mettre      */ \
                                        /* a jour le cache des directories ('VRAI') ou pas ('FAUX') ?                                */
#Aif      (         (defined(CMAP28))                                                                                                   \
           )
#    define    PRE_METTRE_A_JOUR_LE_CACHE_DES_DIRECTORIES                                                                               \
                         FAUX                                                                                                           \
                                        /* Si 'IL_NE_FAUT_PAS(executer_une_sequence_en_parallele)' faut-il tenter de pre-mettre      */ \
                                        /* a jour le cache des directories ('VRAI') ou pas ('FAUX') ?                                */
#Eif      (         (defined(CMAP28))                                                                                                   \
           )

#define   EDITER_LES_MESSAGES_D_ERREUR                                                                                                  \
                    NE_PAS_EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS                                                                    \
                                        /* Indicateur a utiliser pour editer les messages d'erreur des fichiers.                     */

#define   LIMITER_LE_NOMBRE_DE_TENTATIVES                                                                                               \
                    FAUX
#define   NOMBRE_MAXIMAL_DE_TENTATIVES                                                                                                  \
                    INFINI
#define   DUREE_D_ATTENTE_ENTRE_DEUX_TENTATIVES                                                                                         \
                    FDU
                                        /* Nombre maximal de tentatives d'entree dans la phase critique (si necessaire...).          */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        M A C R O S   U T I L E S  :                                                                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   CONTENU_DU_VERROU                                                                                                             \
                    chain_Aconcaten10("DATE="                                                                                           \
                                     ,mise_de_la_date_courante_au_format_____AAAAMMJJhhmmss()                                           \
                                     ," : MACHINE="                                                                                     \
                                     ,sHOTE                                                                                             \
                                     ," ("                                                                                              \
                                     ,mHOTE                                                                                             \
                                     ,COND(IFET(IFNE_chaine(vCOMPUTER,VALEUR_D_UNE_VARIABLE_UNDEF)                                      \
                                               ,IFNE_chaine(vCOMPUTER,amHOTE)                                                           \
                                                )                                                                                       \
                                          ,chain_Aconcaten4(" ex ",C_VERITABLE_QUOTE,vCOMPUTER,C_VERITABLE_QUOTE)                       \
                                          ,ccCHAR(C_VIDE)                                                                               \
                                           )                                                                                            \
                                     ,COND(IFNE_chaine(mHOTE_Force,VALEUR_D_UNE_VARIABLE_UNDEF)                                         \
                                          ,chain_Aconcaten4(" ex ",C_VERITABLE_QUOTE,mHOTE_Force,C_VERITABLE_QUOTE)                     \
                                          ,ccCHAR(C_VIDE)                                                                               \
                                           )                                                                                            \
                                     ,") --> process="                                                                                  \
                                     ,pid                                                                                               \
                                      )                                                                                                 \
                                        /* Definition du contenu du verrou...                                                        */

#define   LECTURE_D_UN_VERROU(verrou_courant)                                                                                           \
                    Bblock                                                                                                              \
                    DEFV(Int,INIT(taille_du_verrou_courant,UNDEF));                                                                     \
                                                                                                                                        \
                    CALS(Fsize_fichier(nom_du_verrou_du_fichier_a_verrouiller                                                           \
                                      ,ADRESSE(taille_du_verrou_courant)                                                                \
                                      ,editer_les_messages_d_erreur                                                                     \
                                       )                                                                                                \
                         );                                                                                                             \
                                                                                                                                        \
                    EGAL(verrou_courant,kMalo(taille_du_verrou_courant));                                                               \
                    CALS(Fload_fichier_non_formatte(nom_du_verrou_du_fichier_a_verrouiller                                              \
                                                   ,verrou_courant                                                                      \
                                                   ,taille_du_verrou_courant                                                            \
                                                   ,size_CHAR                                                                           \
                                                   ,editer_les_messages_d_erreur                                                        \
                                                   ,editer_les_messages_d_erreur                                                        \
                                                    )                                                                                   \
                         );                                                                                                             \
                    Eblock                                                                                                              \
                                        /* Lecture du contenu d'un verrou...                                                         */

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        G E S T I O N   D E S   P H A S E S   C R I T I Q U E S  :                                                                 */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
BCommande(nombre_d_arguments,arguments)
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(CHAR,INIC(POINTERc(nom_du_fichier_a_verrouiller),NOM_UNDEF_VIDE));
                                        /* Nom du fichier a verrouiller par une phase critique...                                    */
     DEFV(CHAR,INIC(POINTERc(nom_du_verrou_du_fichier_a_verrouiller),NOM_UNDEF_VIDE));
                                        /* Nom du verrou du fichier a verrouiller par une phase critique...                          */

     DEFV(Logical,INIT(pre_mettre_a_jour_le_cache_des_directories,PRE_METTRE_A_JOUR_LE_CACHE_DES_DIRECTORIES));
                                        /* Si 'IL_NE_FAUT_PAS(executer_une_sequence_en_parallele)' faut-il tenter de pre-mettre      */
                                        /* a jour le cache des directories ('VRAI') ou pas ('FAUX') ?                                */

     DEFV(CHAR,INIC(POINTERc(postfixe_VERROU),Gvar("v")));
                                        /* Nom du postfixe de verrouillage a utiliser.                                               */
     DEFV(CHAR,INIC(POINTERc(sHOTE),Gvar_sHOTE));
     DEFV(CHAR,INIC(POINTERc(mHOTE),Gvar_mHOTE));
     DEFV(CHAR,INIC(POINTERc(vCOMPUTER),Gvar_vCOMPUTER));
     DEFV(CHAR,INIC(POINTERc(mHOTE_Force),Gvar_mHOTE_Force));
     DEFV(CHAR,INIC(POINTERc(amHOTE),Gvar_amHOTE));
                                        /* Definition de la MACHINE "hote"...                                                        */
     DEFV(CHAR,INIC(POINTERc(pid),chain_Aentier(GvalDefaut("Cshell",Gpid()))));
                                        /* Definition de l'identite du '$CSH' courant (ou du '$X' courant par defaut...).            */

     DEFV(Logical,INIT(entrer_dans_une_phase_critique,ENTRER_DANS_UNE_PHASE_CRITIQUE));
                                        /* Est-ce une entree ('Begin') ou une sortie ('End') ?                                       */

     DEFV(Logical,INIT(forcer_l_entree_dans_une_phase_critique_quel_que_soit_l_etat_du_fichier
                      ,FORCER_L_ENTREE_DANS_UNE_PHASE_CRITIQUE_QUEL_QUE_SOIT_L_ETAT_DU_FICHIER
                       )
          );
                                        /* Il y a deux modes de fonctionnement lors de l'entree en phase critique : l'un autorisant  */
                                        /* l'absence du fichier ('VRAI') et l'autre pas ('FAUX')...                                  */
                                        /*                                                                                           */
                                        /* Voir 'v $Falias_PhasCriB ToUjOuRs_PhasCriB' a ce propos...                                */

     DEFV(Logical,INIT(editer_les_messages_d_erreur,EDITER_LES_MESSAGES_D_ERREUR));
                                        /* Indicateur a utiliser pour editer les messages d'erreur des fichiers.                     */

     DEFV(Logical,INIT(limiter_le_nombre_de_tentatives,LIMITER_LE_NOMBRE_DE_TENTATIVES));
     DEFV(Positive,INIT(nombre_maximal_de_tentatives,NOMBRE_MAXIMAL_DE_TENTATIVES));
     DEFV(Float,INIT(duree_d_attente_entre_deux_tentatives,DUREE_D_ATTENTE_ENTRE_DEUX_TENTATIVES));
                                        /* Nombre maximal de tentatives d'entree dans la phase critique (si necessaire...).          */
                                        /*                                                                                           */
                                        /* Voir 'v $Falias_PhasCriB LiMiT_PhasCriB' et 'v $Falias_PhasCriB LiMiT_PhasCriB' a ce      */
                                        /* propos...                                                                                 */
     /*..............................................................................................................................*/
     GET_ARGUMENTS_(nombre_d_arguments
                   ,BLOC(GET_ARGUMENT_C("fichier_a_verrouiller=""fichier=",nom_du_fichier_a_verrouiller);
                         GET_ARGUMENT_C("VERROU=""verrou=""v=",postfixe_VERROU);

                         GET_ARGUMENT_L("PhasCriB=""Begin=""B=",entrer_dans_une_phase_critique);
                         GET_ARGUMENT_N("PhasCriE=""End=""E=",entrer_dans_une_phase_critique);

                         GET_ARGUMENT_L("forcer_fichier_inexistant=""forcer=""ffi="
                                       ,forcer_l_entree_dans_une_phase_critique_quel_que_soit_l_etat_du_fichier
                                        );

                         GET_ARGUMENT_L("pmajcd=""pmaj=""cache_des_directories=",pre_mettre_a_jour_le_cache_des_directories);

                         GET_ARGUMENT_L("erreurs=",editer_les_messages_d_erreur);

                         GET_ARGUMENT_L("limiter_tentatives=""limiter=",limiter_le_nombre_de_tentatives);
                         GET_ARGUMENT_I("nombre_maximal_tentatives=""tentatives=",nombre_maximal_de_tentatives);
                         GET_ARGUMENT_F("duree=""temporisation=",duree_d_attente_entre_deux_tentatives);
                         )
                    );

     Test(IFGT(duree_d_attente_entre_deux_tentatives,FDEUX))
          Bblock
          PRINT_ERREUR("la duree entre deux tentatives ne peut execeder deux secondes");
          EGAL(duree_d_attente_entre_deux_tentatives,FDEUX);
                                        /* A ce propos 'v $xil/defi_c1$vv$DEF 20110531165758'...                                     */
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     EGAL(nom_du_verrou_du_fichier_a_verrouiller,chain_Aconcaten2(nom_du_fichier_a_verrouiller,postfixe_VERROU));

     Test(IL_FAUT(entrer_dans_une_phase_critique))
          Bblock
          DEFV(Logical,INIT(tenter_la_generation_du_verrou,VRAI));
          DEFV(Positive,INIT(nombre_de_tentatives,ZERO));

          Test(IFOU(IL_FAUT(forcer_l_entree_dans_une_phase_critique_quel_que_soit_l_etat_du_fichier)
                   ,IFET(IL_NE_FAUT_PAS(forcer_l_entree_dans_une_phase_critique_quel_que_soit_l_etat_du_fichier)
                        ,PAS_D_ERREUR(Ftest_fichier_avec_pre_mise_a_jour_du_cache_des_directories
                                          (nom_du_fichier_a_verrouiller
                                          ,pre_mettre_a_jour_le_cache_des_directories
                                          ,NE_PAS_EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS
                                           )
                                      )
                         )
                    )
               )
               Bblock
               Tant(IL_FAUT(tenter_la_generation_du_verrou))
                    Bblock
                    DEFV(CHAR,INIC(POINTERc(contenu_du_verrou_du_fichier_a_verrouiller),CONTENU_DU_VERROU));
                                        /* Generation d'un verrou approprie...                                                       */

                    Test(PAS_D_ERREUR(CODE_ERROR(Fstore_fichier_non_formatte(contenu_du_verrou_du_fichier_a_verrouiller
                                                                            ,nom_du_verrou_du_fichier_a_verrouiller
                                                                            ,chain_taille(contenu_du_verrou_du_fichier_a_verrouiller)
                                                                            ,size_CHAR
                                                                            ,editer_les_messages_d_erreur
                                                                             )
                                                 )
                                      )
                         )
                         Bblock
                         DEFV(CHAR,INIT(POINTERc(verification_du_contenu_du_verrou_du_fichier_a_verrouiller),CHAINE_UNDEF));

                         LECTURE_D_UN_VERROU(verification_du_contenu_du_verrou_du_fichier_a_verrouiller);

                         Test(IFEQ_chaine(verification_du_contenu_du_verrou_du_fichier_a_verrouiller
                                         ,contenu_du_verrou_du_fichier_a_verrouiller
                                          )
                              )
                              Bblock
                              EGAL(tenter_la_generation_du_verrou,FAUX);
                                        /* Lorsque le verrou que l'on relit est bien celui que l'on a ecrit, on considere que        */
                                        /* l'appropriation est bonne et qu'ainsi on est bien rentre dans la phase critique...        */

                              CALS(Chmod(nom_du_verrou_du_fichier_a_verrouiller,NEUT(S_IRUSR)));
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                    Test(IL_FAUT(tenter_la_generation_du_verrou))
                         Bblock
                         Test(IL_FAUT(limiter_le_nombre_de_tentatives))
                              Bblock
                              INCR(nombre_de_tentatives,I);

                              Test(IFGE(nombre_de_tentatives,nombre_maximal_de_tentatives))
                                   Bblock
                                   EGAL(tenter_la_generation_du_verrou,FAUX);
                                        /* Lorsque trop de tentatives ont ete effectuees, on arrete brutalement...                   */

                                   PRINT_ERREUR("trop de tentatives d'entree en phase critique ont ete effectuees");
                                   Eblock
                              ATes
                                   Bblock
                                   Eblock
                              ETes
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                    Test(IL_FAUT(tenter_la_generation_du_verrou))
                         Bblock
                         PETIT_DODO(MUL2(duree_d_attente_entre_deux_tentatives,nano_secondes));
                                        /* Et on attend un peu avant d'iterer...                                                     */
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ETan
               Eblock
          ATes
               Bblock
               PRINT_ERREUR("le fichier n'existait pas");
               CAL1(Prer1("son nom est '%s'.\n",nom_du_fichier_a_verrouiller));
               Eblock
          ETes
          Eblock
     ATes
          Bblock

#define   nom_du_verrou_du_fichier_a_deverrouiller                                                                                      \
                    nom_du_verrou_du_fichier_a_verrouiller                                                                              \
                                        /* Afin d'avoir une notation homogene avec l'action ici accomplie...                         */

          Test(PAS_D_ERREUR(Ftest_fichier_avec_pre_mise_a_jour_du_cache_des_directories(nom_du_verrou_du_fichier_a_deverrouiller
                                                                                       ,pre_mettre_a_jour_le_cache_des_directories
                                                                                       ,NE_PAS_EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS
                                                                                        )
                            )
               )
               Bblock
               DEFV(CHAR,INIT(POINTERc(contenu_du_verrou_du_fichier_a_deverrouiller),CHAINE_UNDEF));

               LECTURE_D_UN_VERROU(contenu_du_verrou_du_fichier_a_deverrouiller);

               CALS(Chmod(nom_du_verrou_du_fichier_a_deverrouiller,OUIN(S_IRUSR,S_IWUSR)));
               CALS(Fdelete_fichier(nom_du_verrou_du_fichier_a_deverrouiller,editer_les_messages_d_erreur));
                                        /* Destruction du verrou...                                                                  */

               CALZ_FreCC(contenu_du_verrou_du_fichier_a_deverrouiller);
               Eblock
          ATes
               Bblock
               PRINT_ERREUR("le verrou n'existait pas");
               CAL1(Prer1("son nom est '%s'.\n",nom_du_verrou_du_fichier_a_deverrouiller));
               Eblock
          ETes

#undef    nom_du_verrou_du_fichier_a_deverrouiller

          Eblock
     ETes

     RETU_Commande;
     Eblock
ECommande



Copyright © Jean-François COLONNA, 2019-2024.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2019-2024.