Pārlūkot izejas kodu

correction checkpoint-user1.oar
et ajout du script checkpoint-user1bis.oar
(checkpoint manuel tel que décrit https://www-calculco.univ-littoral.fr/utilisation/lancer-un-calcul#h2-2-oardel)

Philippe Marion 7 gadi atpakaļ
vecāks
revīzija
b237c5281d

+ 32 - 27
checkpoint/checkpoint-user1.oar

@@ -8,7 +8,7 @@
 
 # commande: oarsub -S ./checkpoint-user1.oar
 
-# Cet exemple est arrêté 2 fois ( 3 jobs consécutifs pour finir)
+# Cet exemple est arrêté 1 fois ( 2 jobs consécutifs pour finir)
 
 #
 #  IMPORTANT:
@@ -22,8 +22,8 @@
 #
 #  Le programme associé à ce script est un simple compteur
 #   ( 1 incrémentation / secondes ) en C.
-#   - son excécution dur 10 mn
-#   - ce script OAR, pour l'exemple, ne prévoit que 5mn (trop court!) 
+#   - son exécution (normal) dure 4 mn
+#   - ce script OAR, pour l'exemple, ne prévoit que 3mn30 (trop court!) 
 #   - le script OAR reçoit (d'OAR) le signal checkpoint 12.
 #     Il renvoit le signal 2 (SIGINT) au programme timer
 #   - À réception de ce dernier (interruption) le timer sauve
@@ -31,8 +31,8 @@
 #   - timer10mn est arrêté mais est relancé par OAR
 # 
 #-------------- paramètres OAR---------------------------
-#OAR -l cpu=1/core=1,walltime=00:5:00 
-#OAR -n start_and_restart
+#OAR -l cpu=1/core=1,walltime=00:3:30 
+#OAR -n checkpoint-user1
 
 # Les fichiers de sortie sans paramètres $OAR_JOBID
 # (=> les jobs successifs écrivent dans les mêmes fichiers)
@@ -41,11 +41,6 @@
 
 #OAR -q default
 
-#IMPORTANT:
-#   - par NFS: a priori pas de problème
-#   - sur SCRATCH : il faut reprendre sur la même machine
-#  par exemple : 
-#OAR -p network_address = 'orval08' 
 ## besteffort est optionnel 
 #OAR -t besteffort
 ## idempotent ne l'est pas 
@@ -60,14 +55,14 @@
 
 #---------- la tâche à exécuter   ------------------------ 
 # compilation ( peut être commenté si déjà compilé) 
-gcc compteur10mn.c  -o timer10mn
-# Note (compteur10mn.c): gère son propre checkpoint (SIGINT)
+gcc compteur4mn.c  -o timer4mn
+# Note (compteur4mn.c): gère son propre checkpoint (SIGINT)
 #----------- pré-traitement -----------------------------
 # DWTFYW !
 echo "Debut du job ${OAR_JOB_ID}"
 
 #----------- lancement de la tâche ----------------------
-./timer10mn &
+./timer4mn &
 
 #---------------------------------------------------------
 # gestion de signaux
@@ -78,7 +73,22 @@ echo "Debut du job ${OAR_JOB_ID}"
 
 # pid du programme = pid de la dernière commande (: ./timer10mn)
 
-PID=$!
+PROGPID=$!
+
+echo "le PROG PID est : $PROGPID"
+
+# fonction de traitement du signal OAR
+sighandler() {
+    echo "reception checkpoint OAR (signal12)"
+    # demande de checkpoint (-c) au programme
+    # SIGINT = 2 = "CRTL + C" (cf compteur10mn.c)
+    kill -s 2 $PROGPID
+    # IMPORTANT : pause
+    sleep 4
+    [ -n "$PROGPID" ] && kill -9 $PROGPID
+    SCRIPT_CHECKPOINTED="YES"
+    echo "checkpoint : $SCRIPT_CHECKPOINTED"
+    }
 
 # signal Unix attendu par OAR (defaut = SIGUSR1/10, forcé ici
 # à 12 par le paramètre --signal 12 (cf. param OAR au début)
@@ -90,21 +100,16 @@ EXIT_UNFINISHED=99
 
 # si le script OAR reçoit le SIGUSR2 (signal 12), checkpoint!
 
-# Rq tentative d'envoyer le même signal au prog: ne fonctione pas!?
-# SIGUSR2 = 12 kill rééllement le programme :
-#   => pas de checkpoint
-#   => boucle infinie!
-
-# Du coup: 
-# SIGINT = 2 = "CRTL + C" fonctionne 
-trap "echo commande trap (script OAR); kill -s 2 $PID ; exit $EXIT_UNFINISHED" $CHKPNT_SIGNAL
-#
+# indique au script OAR de capter le signal 12 
+trap sighandler  $CHKPNT_SIGNAL
 
-# obliger le script OAR à attendre l'exécution du PROG
-# (sinon il s'exécute jusqu'au bout et ne récupérera
-# jamais le signal checkpoint !)
+# wait indispensable pour maintien des communucations
+# (signaux) entre ce script et le PROG
+while kill -0 "$PROGPID" 2>/dev/null; do
+    wait $PROGPID
+done
 
-wait $PID
+[ -n "$SCRIPT_CHECKPOINTED" ] && exit 99
 
 #---------------------------------------------------------
 # fin du programme:  postraitement

+ 118 - 0
checkpoint/checkpoint-user1bis.oar

@@ -0,0 +1,118 @@
+#!/bin/bash
+
+#-------------------  CHECKPOINT  --------------------------- 
+
+#
+#  exemple de programme qui vient illustrer le cas décrit : 
+# https://www-calculco.univ-littoral.fr/utilisation/lancer-un-calcul#h2-2-oardel
+
+# commande: oarsub -S ./checkpoint-user1bis.oar
+
+# cet exemple reprend l'exemple exemple 1 (checkpoint-user1.oar)
+# avec un programmer timer de 4mn 
+# simplement c'est l'utilisateur qui déclencle le checkpoint
+# en supprimant son job avec la commande:
+
+#    oardel -c -s SIGUSR2 XXXXX, où XXXX est le n° du job (JobID)
+# 
+
+#   Le checkpoint crée le fichier context_compteur.txt. Relancer le
+#   script OAR ultérieurement entraîne un reprise du programme à
+#   partir de ce contexte.
+
+# 
+#-------------- paramètres OAR---------------------------
+#OAR -l cpu=1/core=1,walltime=00:5:00 
+#OAR -n checkpoint-user1bis
+
+# Les fichiers de sortie sans paramètres $OAR_JOBID
+# (=> les jobs successifs écrivent dans les mêmes fichiers)
+#OAR -O OAR-ckpt-user1bis.out
+#OAR -E OAR-ckpt-user1bis.err
+
+#OAR -q default
+
+
+#IMPORTANT:
+#   - par NFS: a priori pas de problème
+#   - sur SCRATCH : il faut reprendre sur la même machine
+#  par exemple : 
+##OAR -p network_address = 'orval08' 
+## besteffort est optionnel 
+#OAR -t besteffort
+
+# signal envoyé par OAR (SIGUSR2)
+#OAR --signal 12 
+
+#---------- la tâche à exécuter   ------------------------ 
+# compilation ( peut être commenté si déjà compilé) 
+gcc compteur4mn.c  -o timer4mn
+# Note (compteur4mn.c): gère son propre checkpoint (SIGINT)
+#----------- pré-traitement -----------------------------
+# DWTFYW !
+echo "Debut du job ${OAR_JOB_ID}"
+
+#----------- lancement de la tâche ----------------------
+./timer4mn &
+
+#---------------------------------------------------------
+# gestion de signaux
+#---------------------------------------------------------
+# Warning: c'est le script OAR qui reçoit le signal 12!
+#  => il faut le capter et le transmettre au PROG
+####################################################
+
+# pid du programme = pid de la dernière commande (: ./timer10mn)
+
+PROGPID=$!
+
+echo "le PROG PID est : $PROGPID"
+
+# fonction de traitement du signal OAR
+sighandler() {
+    echo "reception checkpoint OAR (signal12)"
+    # demande de checkpoint (-c) au programme
+    # SIGINT = 2 = "CRTL + C" (cf compteur10mn.c)
+    kill -s 2 $PROGPID
+    # IMPORTANT: pause (creation du fichier contexte)
+    sleep 5
+    [ -n "$PROGPID" ] && kill -9 $PROGPID
+    SCRIPT_CHECKPOINTED="YES"
+    echo "checkpoint : $SCRIPT_CHECKPOINTED"
+    }
+
+# signal Unix attendu par OAR (defaut = SIGUSR1/10, forcé ici
+# à 12 par le paramètre --signal 12 (cf. param OAR au début)
+CHKPNT_SIGNAL=12
+
+# valeur de sortie en cas de checlpoint :
+# on laisse la valeur 99 nécessaire à l'option "--idempotent"
+# (restart automatique)
+# Dans le cas manuel, cette valeur peut être autre, l'important
+# est d'en fixer une pour sortir du programme sans aller à la fin
+# du script OAR (sinon le contexte est suppimé . cf les dernières lignes) 
+EXIT_UNFINISHED=99
+
+# si le script OAR reçoit le SIGUSR2 (signal 12), checkpoint!
+
+# indique au script OAR de capter le signal 12 
+trap sighandler  $CHKPNT_SIGNAL
+
+# wait indispensable pour maintien des communucations
+# (signaux) entre ce script et le PROG
+while kill -0 "$PROGPID" 2>/dev/null; do
+    wait $PROGPID
+done
+
+# sortir ici ( sinon suppression du fichier context_compteur.txt )
+[ -n "$SCRIPT_CHECKPOINTED" ] && exit $EXIT_UNFINISHED
+
+#---------------------------------------------------------
+# fin du programme:  postraitement
+#---------------------------------------------------------
+# DWTFYW!
+echo " ---post treatement---"
+echo " ...suppression du fichier temporaire context_compteur.txt"
+rm -f context_compteur.txt
+echo " c'est FINI ! "
+exit $?

+ 95 - 0
checkpoint/compteur4mn.c

@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>  //sleep
+
+
+/*
+ - compteur sur 10 mn (affichage incrementations toutes les secondes)
+ - capture de signaux ( pour test de checkpointing avec dmtcp /OAR Caclculco)
+ - le compteur est sauvegardé dans un fichier sur capture de signal (SIGINT /2)
+     -> à réutiliser pour reprise de travaux après checkpointing ) 
+ */
+#define SIZE 1
+#define NUMELEM 5
+
+/*compteur  variable globale ( main et signal ) */
+int compteur;
+//findice_ckpt
+FILE * fp;
+
+
+void sig_handler(int signal)
+{
+switch (signal)
+  {
+  case SIGINT:
+    // code exécuté si on reçoit SIGINt (CTRL+C);        
+    printf("SIGINT recu (programme C)\n");
+    printf("valeur du compteur enregistre: %d\n", compteur);
+    // fichier de sauvegarde du "contexte" ( l'indice = nb de secondes!
+    fp = fopen("context_compteur.txt", "wb");
+    if(fp == NULL) {
+        printf("error creating file");
+    }
+    else {
+      fwrite( &compteur , sizeof(int) , 1 , fp);
+      fflush(fp);
+      fclose(fp);
+    }
+    break;
+
+  case SIGUSR1:        
+    // code normalement exécuté si on reçoit SIGUSR2 (OAR?) ou SIGUSR1 (dmtcp);
+    // NE FONCTIONNE PAS ( c'est donc le SIGINT 2 ci- dessus qui est utlisé dans
+    // checkpoint-user1.oar
+    printf("signal checkpoint SIGUSR1 recu \n");
+    printf("valeur du compteur: %d\n", compteur);
+    fp = fopen("context_compteur.txt", "wb");
+    if(fp == NULL) {
+        printf("error creating file");
+    }
+    else {
+      fwrite( &compteur , sizeof(int) , 1 , fp);
+      fclose(fp);
+    }
+
+    break;
+
+    default :
+    // sortie
+    exit(0);
+  }
+}
+
+
+//int main( int argc, char *argv[] )
+int main(void)
+{
+  if (signal(SIGINT, sig_handler) == SIG_ERR)
+    printf("\n ne peut pas recevoir SIGINT\n");
+
+  // ----- test si un checkpoint existe ---- 
+  // si oui, lecture de la valeur dans le fichier
+  int i ;
+  fp = fopen("context_compteur.txt", "rb");
+  if (fp){
+    fread( &i , sizeof(int) , 1 , fp);
+    printf("valeur compteur au precedent checkpoint = %d\n", i);
+    fclose(fp);
+  }else{
+    i=0;
+  }
+  // ---- le Compteur propremen dit ---------
+  // 10 mn(environ: ce n'est pas un chrono!)
+  
+  for (compteur=i; compteur <=240; compteur++)
+    {
+      printf("compteur = %d\n", compteur);
+      // force l'écriture sur la sortie
+      fflush(stdout);
+      sleep(1);
+    }
+  return 0;
+}