source: trunk/libIGCM/libIGCM_debug/libIGCM_debug.ksh @ 1275

Last change on this file since 1275 was 1275, checked in by sdipsl, 8 years ago
  • workaround to avoid issues related to #275
  • Property licence set to
    The following licence information concerns ONLY the libIGCM tools
    ==================================================================

    Copyright © Centre National de la Recherche Scientifique CNRS
    Commissariat à l'Énergie Atomique CEA

    libIGCM : Library for Portable Models Computation of IGCM Group.

    IGCM Group is the french IPSL Global Climate Model Group.

    This library is a set of shell scripts and functions whose purpose is
    the management of the initialization, the launch, the transfer of
    output files, the post-processing and the monitoring of datas produce
    by any numerical program on any plateforme.

    This software is governed by the CeCILL license under French law and
    abiding by the rules of distribution of free software. You can use,
    modify and/ or redistribute the software under the terms of the CeCILL
    license as circulated by CEA, CNRS and INRIA at the following URL
    "http://www.cecill.info".

    As a counterpart to the access to the source code and rights to copy,
    modify and redistribute granted by the license, users are provided only
    with a limited warranty and the software's author, the holder of the
    economic rights, and the successive licensors have only limited
    liability.

    In this respect, the user's attention is drawn to the risks associated
    with loading, using, modifying and/or developing or reproducing the
    software by the user in light of its specific status of free software,
    that may mean that it is complicated to manipulate, and that also
    therefore means that it is reserved for developers and experienced
    professionals having in-depth computer knowledge. Users are therefore
    encouraged to load and test the software's suitability as regards their
    requirements in conditions enabling the security of their systems and/or
    data to be ensured and, more generally, to use and operate it in the
    same conditions as regards security.

    The fact that you are presently reading this means that you have had
    knowledge of the CeCILL license and that you accept its terms.
  • Property svn:keywords set to Revision Author Date
File size: 35.7 KB
RevLine 
[913]1#!/bin/ksh
[2]2
3#**************************************************************
4# Author: Patrick Brockmann, Martial Mancip
[373]5# Contact: Patrick.Brockmann__at__cea.fr Martial.Mancip__at__ipsl.jussieu.fr
6# $Revision::                                          $ Revision of last commit
7# $Author::                                            $ Author of last commit
8# $Date::                                              $ Date of last commit
[2]9# IPSL (2006)
10#  This software is governed by the CeCILL licence see libIGCM/libIGCM_CeCILL.LIC
11#
12#**************************************************************
13
14#==================================================
15# The documentation of this file can be automatically generated
[913]16# if you use the prefix #D- for comments to be extracted.
[2]17# Extract with command: cat lib* | grep "^#D-" | cut -c "4-"
18#==================================================
19
20#==================================================
21# Add high level verbosity
22typeset -i Verbosity=${Verbosity:=3}
23
24#==================================================
25# DEBUG_debug
26# Add low level verbosity
[1083]27DEBUG_debug=${DEBUG_debug:=false}
[2]28
[872]29#==================================================
30# GENERATE RANDOM ERROR ; only apply if ( ${DEBUG_debug} )
[1244]31typeset -r RandomError=false
[872]32
[2]33#==================================================
34# NULL_STR
35# Default null string
[913]36typeset -r NULL_STR="_0_"
[2]37
38#==================================================
39# libIGCM_CurrentTag
40# Current libIGCM tag, check compatibilty with *.card
[1244]41typeset -r libIGCMVersion="2.7"
[2]42
43#==================================================
44# Exit Flag (internal debug)
45# When true, end the master loop AFTER SAVES FILES
46ExitFlag=false
47
48#==================================================
[1243]49# When we start to run the simulation is not finished
50simulationIsOver=false
51
52#==================================================
[1268]53# When we start to run we dont flush AMQP messages
54FlushAMQP=false
55
56#==================================================
[2]57# Declare a stack of functions calls
[59]58unset IGCM_debug_Stack
59unset IGCM_debug_StackArgs
[913]60unset IGCM_debug_StackTiming
[54]61IGCM_debug_Stack[0]=${NULL_STR}
62IGCM_debug_StackArgs[0]=${NULL_STR}
[913]63IGCM_debug_StackTiming[0]=${NULL_STR}
[2]64IGCM_debug_LenStack=0
65
66#D-#==================================================================
[913]67#D-function IGCM_debug_getDate_ms
68#D- * Purpose: Give number of milliseconds since 01-jan-1970
69function IGCM_debug_getDate_ms
70{
[926]71  typeset nanosecs ms
[913]72  # nano secondes since 01-jan-1970
73  nanosecs=$( date +%s%N )
74
75  # truncate the last 6 digits to get milliseconds since 01-jan-1970
76  ms=${nanosecs:0:${#nanosecs}-6}
77
78  echo "$ms"
79}
80
81#D-#==================================================================
82#D-function IGCM_debug_sizeOfTabContent
83#D- * Purpose: Give sumed size of a list of files
[924]84#D- * Usage: IGCM_debug_sizeOfTabContent entityList destination
85#D- *        where entityList is a list of files or directory
86#D- *        where dest is either a directory or a file name
[913]87function IGCM_debug_sizeOfTabContent
88{
[924]89  typeset entityListe destination iEntity sizeKo sumSizeKo sumSizeMo
90
91  eval set +A entityListe \${${1}}
[941]92  destination=${2}
[924]93  sumSizeKo=0
94
95  # Here we will try to compute size (file or directory size) from local path and not from archive.
[941]96  for ((i = 0; i < ${#entityListe[*]}; i += 1)) ; do
97    if [ -f ${entityListe[$i]} ] ; then
98      # One file or a bunch of files has been copied without renaming from a visible filesystem
99      iEntity=${entityListe[$i]}
100    elif [ -f ${entityListe[$i]##/*/} ] ; then
101      # One file or a bunch of files has been copied without renaming from an non visible filesystem
[924]102      # remove path /home/login/../ from entityListe elements
103      iEntity=${entityListe[$i]##/*/}
104    elif [ -f ${destination} ] ; then
[941]105      # a file has been copied and renamed
[924]106      iEntity=${destination}
107    elif [ -f ${destination}/${entityListe[$i]##/*/} ] ; then
108      # a copy in a directory but not in ${PWD}
109      iEntity=${destination}/${entityListe[$i]##/*/}
110    elif [ -d ${entityListe[$i]} ] ; then
[941]111      # a directory has been copied from a non remote place
[924]112      iEntity=${entityListe[$i]}
113    elif [ -d ${destination}/${entityListe[$i]##/*/} ] ; then
[941]114      # a directory has been copied from a remote archive and not renamed
[924]115      iEntity=${destination}/${entityListe[$i]##/*/}
116    elif [ -d ${destination} ] ; then
[941]117      # a directory has been copied from a remote archive and renamed
[924]118      iEntity=${destination}
[917]119    fi
[1083]120    sizeKo=$( du --apparent-size -skL ${iEntity} | gawk '{print $1}' )
[924]121    sumSizeKo=$(( $sumSizeKo + $sizeKo ))
[913]122  done
[924]123  sumSizeMo=$( echo "scale=6;${sumSizeKo}/1024" | bc )
124  echo "${sumSizeKo}|${sumSizeMo}"
[913]125}
126
127#D-#==================================================================
[983]128#D-function IGCM_debug_send_AMQP_msg__MAILTUNNEL
129#D- * Purpose: Take over AMQP C client using mail as a message recipient
130#D- * One argument : base64 encoded message
[1051]131#D- * Attach encoded config.card when starting the simulation
132
[983]133function IGCM_debug_send_AMQP_msg__MAILTUNNEL {
134
[987]135  typeset b64_encoded_msg mail_recipient
[1076]136  typeset buffer send_messages mail_frequency
[987]137  typeset last_mail_date__file
[1234]138  typeset secondsBetweenRefAndLastMail secondsSinceLastMail
[987]139
[983]140  b64_encoded_msg=$1
141
[1072]142  mail_recipient="superviseur@ipsl.jussieu.fr"
[983]143  send_messages=0
144  mail_frequency=3600 # in seconds
145  # use to keep track when was last mail sent (maybe to be replaced with global variable)
[1150]146  last_mail_date__file=${R_BUF}/.stamp.${config_UserChoices_TagName}.${config_UserChoices_JobName}
147  # use to accumulate messages before sending them
148  buffer=${R_BUF}/.buffer.${config_UserChoices_TagName}.${config_UserChoices_JobName}
[983]149
150  # init
151  if [ ! -f "${buffer}" ]; then
[1150]152    touch ${buffer}
[983]153  fi
154
155  if [ ! -f "${last_mail_date__file}" ]; then
[1150]156    touch ${last_mail_date__file}
[983]157  else
[1150]158    # compute last time the file was changed (in seconds)
[1234]159    secondsBetweenRefAndLastMail=$(stat -c %Y ${last_mail_date__file})
160    status=$?
161    #
[1275]162    # Only execute this block when the stat command succeeded.
163    # The stat command might fail in some circumstance but we consider it is ok to continue anyway.
164    if [ ${status} -eq 0 ] ; then
165      secondsSinceLastMail=$(( $(date +%s) - ${secondsBetweenRefAndLastMail} ))
166      # send message when exceeding threshold
167      [ ${secondsSinceLastMail} -gt ${mail_frequency} ] && send_messages=1
[1234]168    fi
[983]169  fi
170
[997]171  # queue messages in the buffer
172  echo ${b64_encoded_msg} >> ${buffer}
173
174  # send mail
[1051]175
[1053]176  if [ X${initBigBro} = Xtrue ] ; then
[1087]177    #echo $(date +"%Y-%m-%dT%H:%M:%S.%N%z") > ${SUBMIT_DIR}/mail.txt
[1051]178    mailx -s "[TEMPORARY AMQP CHANNEL]" -a ${SUBMIT_DIR}/config.card.base64 ${mail_recipient} < ${buffer} # send buffer
179    rm -f $buffer ; touch ${buffer}                                    # clear buffer
180    touch ${last_mail_date__file}                                      # memorize last mail date
181    initBigBro=false
[1150]182  elif [ ${send_messages} -eq 1 ] ; then
[1087]183    #echo $(date +"%Y-%m-%dT%H:%M:%S.%N%z") >> ${SUBMIT_DIR}/mail.txt
[1051]184    mailx -s "[TEMPORARY AMQP CHANNEL]" ${mail_recipient}  < ${buffer} # send buffer
[1150]185    rm -f ${buffer} ; touch ${buffer}                                  # flush the buffer
[1051]186    touch ${last_mail_date__file}                                      # memorize last mail date
[983]187  fi
[987]188
[1189]189  if ( ${FlushAMQP} ) ; then
[1150]190    mailx -s "[TEMPORARY AMQP CHANNEL]" ${mail_recipient}  < ${buffer} # send buffer
191    rm -f ${buffer}                                                    # cleaning behind us
192    rm -f ${last_mail_date__file}                                      # cleaning behind us
193  fi
194
[983]195  # Allways all good for now.
196  return 0
197}
198
199#D-#==================================================================
[1162]200#D-function IGCM_debug_sendAMQP_Metrics
201#D- * Purpose: Take over AMQP C client using mail as a message recipient
[1202]202#D- * Two arguments : - Directory where metrics.json files can be found
203#D- *                 - Metrics Group Name. metrics will be added to this group
[1162]204#D- * Attach encoded metrics.json files.
205
206function IGCM_debug_sendAMQP_Metrics {
207
208  typeset mail_recipient encodedBody
209  if [ X${ActivateBigBro} = Xtrue ] ; then
210    mail_recipient="superviseur@ipsl.jussieu.fr"
211    # Metrics tag on server side
212    code=7100
213    # Usual AMQP message to route messages on server side
[1202]214    encodedBody=$( echo "{${genericSimulationID},\"msgCode\":\"${code}\",\"msgUID\":\"$(uuidgen)\",\"metricsGroupName\":\"${2}\",\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\"}" |  base64 -w 0 )
[1162]215    # send mail
216    attachmentsOptions=""
217    for metricsFile in $( ls $1/*json ) ; do
218      attachmentsOptions="-a ${metricsFile} ${attachmentsOptions}"
219    done
[1204]220    IGCM_debug_Print 2 "IGCM_debug_sendAMQP_Metrics "
[1162]221    echo ${encodedBody}|mailx -s "[TEMPORARY AMQP CHANNEL]" ${attachmentsOptions} ${mail_recipient}
222  fi
223
224  # Allways all good for now.
225  return 0
226}
227
228#D-#==================================================================
[913]229#D-function IGCM_debug_SendAMQP
230#D- * Purpose: Send body; encoded body and config.card to rabbitMQ
[1053]231function IGCM_debug_sendAMQP {
232
[913]233  typeset decal first additionnalOption encodedBody
234
235  # Encode message Body
236  encodedBody=$( echo "${Body}" | base64 -w 0 )
237
238  # Send config.card ?
239  if [ X${1} = Xactivate ] ; then
240    # Encode config.card
241    cat ${SUBMIT_DIR}/config.card | base64 -w 0 > ${SUBMIT_DIR}/config.card.base64
242    # Prepare additionnal option
243    additionnalOption="-f ${SUBMIT_DIR}/config.card.base64"
[1076]244    #
[1051]245    initBigBro=true
[913]246  else
247    additionnalOption=
[1051]248    #
249    initBigBro=false
[913]250  fi
251
252  # Only cosmetics : stack file
[1115]253  if [ X${ActivateStackFilling} = Xtrue ] ; then
254    decal=0
255    while [ ${decal} -lt ${IGCM_debug_LenStack} ]; do
256      printf ' ' >> ${StackFileLocation}/${StackFileName}
257      (( decal = decal + 1 ))
258    done
259    # Log to stack file using human readable format
260    echo "${Body}" >> ${StackFileLocation}/${StackFileName}
261  fi
[913]262
[983]263  # Log separately encoded AMQP message command for reuse in a mock up
[1120]264  #echo sendAMQPMsg -h localhost -p 5672 ${additionnalOption} -b ${encodedBody} >> ${RUN_DIR_PATH}/send.AMQP.${config_UserChoices_JobName}.${config_UserChoices_ExperimentName}.${config_UserChoices_SpaceName}.${config_UserChoices_TagName}.${CumulPeriod}.history.txt
[913]265
266  # Send the message
[983]267  if [ X${BigBrotherChannel} = XMAIL ] ; then
268    IGCM_debug_send_AMQP_msg__MAILTUNNEL "${encodedBody}"
269    status=$?
270  else
271    sendAMQPMsg -h localhost -p 5672 ${additionnalOption} -b ${encodedBody}
272    status=$?
273  fi
274
[913]275  if [ ${status} -gt 0 ] ; then
276    IGCM_debug_Print 2 "IGCM_debug_Push/PopStack/ActivateBigBro : command sendAMQPMsg failed error code ${status}"
[1051]277    echo sendAMQPMsg -h localhost -p 5672 -b "${Body}"
[1090]278    exit 1
[913]279  fi
280}
281
282#D-#==================================================================
[2]283#D-function IGCM_debug_CallStack
[913]284#D-* Purpose: Print the call stack tree from the oldest to the youngest (opposite of the display standard)
[2]285#D-
286function IGCM_debug_CallStack {
[544]287  if ( $DEBUG_debug ) ; then
[913]288    # Cosmetics
[544]289    typeset i decal
[823]290    i=0
[544]291    until [ $i -eq ${IGCM_debug_LenStack} ]; do
292      decal=0
293      until [ $decal -eq ${i} ]; do
[869]294        printf -- ' '
[823]295        (( decal = decal + 1 ))
[544]296      done
[869]297      echo "$i - ${IGCM_debug_Stack[$(( $IGCM_debug_LenStack-$i-1 ))]}" "(${IGCM_debug_StackArgs[$(( $IGCM_debug_LenStack-$i-1 ))]})"
[823]298      ((i = i + 1))
[544]299    done
300  fi
[2]301}
302
303#D-#==================================================================
304#D-function IGCM_debug_PushStack
305#D-* Purpose: Push a function name in the stack
306#D-
307function IGCM_debug_PushStack {
[544]308  if ( $DEBUG_debug ) ; then
[913]309    typeset decal inputs startTime_ms
310
311    # Only cosmetics : stack file
[1115]312    if [ X${ActivateStackFilling} = Xtrue ] ; then
313      echo >> ${StackFileLocation}/${StackFileName}
314      decal=0
315      while [ ${decal} -lt ${IGCM_debug_LenStack} ]; do
316        printf ' ' >> ${StackFileLocation}/${StackFileName}
317        (( decal = decal + 1 ))
318      done
[2]319
[1115]320      # Fill the stack file
321      echo "> ${IGCM_debug_LenStack} : ${@}" >> ${StackFileLocation}/${StackFileName}
322    fi
[926]323
[913]324    # Save input list in an indexed array
[823]325    INPUTS=( $@ )
[913]326
327    # Get timing information
328    startTime_ms=$( IGCM_debug_getDate_ms )
329
[544]330    # We add function call name on beginning of the stack
331    set +A IGCM_debug_Stack -- ${1} ${IGCM_debug_Stack[*]}
[2]332
[913]333    # Save timing in milliseconds in an indexed array
334    set +A IGCM_debug_StackTiming -- ${startTime_ms} ${IGCM_debug_StackTiming[*]}
335
[544]336    # We include the "null" Args in the beginning of the StackArgs
[913]337    set +A IGCM_debug_StackArgs ${NULL_STR} ${IGCM_debug_StackArgs[*]}
338
[544]339    # Then, we shift StackArgs tabular
[1065]340    # Replacing blank separated list by comma separated list of quoted elements (except the first and last element)
[913]341    if [ $# -gt 1 ]; then
[1065]342      IGCM_debug_StackArgs[0]=$(echo ${INPUTS[*]:1} | sed -e "s/\ /\",\"/g" )
[544]343    fi
[855]344
345    # Increment LenStack
[544]346    (( IGCM_debug_LenStack = IGCM_debug_LenStack + 1 ))
[2]347
[869]348    #IGCM_debug_CallStack
[544]349  fi
[2]350}
351
352#D-#==================================================================
353#D-function IGCM_debug_PopStack
354#D-* Purpose: Pop a function name in the stack
355#D-
356function IGCM_debug_PopStack {
[544]357  if ( $DEBUG_debug ) ; then
[926]358    typeset i decal command arguments startTime_ms endTime_ms
[941]359    typeset instrumentation dest prefix
[926]360    # they are not typeset because they are send "by adress" to son functions
361    # we unset them to avoid "memory effect"
362    unset fileList source
[913]363
364    # INTRODUCE SIMPLE ERROR GENERATOR TO TEST SUPERVISOR
365    # PROBABILITY ERROR IS 0.0001 PER COMMAND OR FUNCTION CALL
366    # THERE ARE ~500 COMMAND OR FUNCTION CALL PER PERIOD
367    if ( ${RandomError} ) ; then
368      if [ $((RANDOM%10000)) -le 10 ] ; then
369        IGCM_debug_Print 1 "Random error has been triggered"
[1115]370        if [ X${ActivateStackFilling} = Xtrue ] ; then
371          echo "RANDOM ERROR" >> ${StackFileLocation}/${StackFileName}
372        fi
[913]373        ExitFlag=true
374      fi
375    fi
376
[544]377    if [ "${IGCM_debug_Stack[0]}" = "${1}" ]; then
[913]378      # Everything is cool
379
380      # Get timing information
381      endTime_ms=$( IGCM_debug_getDate_ms )
382
383      # Save Stack information before poping the stack
384      command=${IGCM_debug_Stack[0]}
385
[1084]386      # Go from comma separated list of quoted elements (except the first and the last element)
387      # to unquoted space separated elements in an array
[1083]388      set -A arguments -- $( echo ${IGCM_debug_StackArgs[0]} | sed -e "s/\",\"/\ /g" )
[913]389
390      # Save Stack information before poping the stack
391      startTime_ms=${IGCM_debug_StackTiming[0]}
392
393      # Pop the stack
[823]394      (( IGCM_debug_LenStack = IGCM_debug_LenStack - 1 ))
395      set -A IGCM_debug_Stack -- ${IGCM_debug_Stack[*]:1}
396      set -A IGCM_debug_StackArgs -- ${IGCM_debug_StackArgs[*]:1}
[913]397      set -A IGCM_debug_StackTiming -- ${IGCM_debug_StackTiming[*]:1}
[544]398    else
399      echo 'IGCM_debug_Exit : stack is corrupted ! LenStack =' ${IGCM_debug_LenStack}
400      IGCM_debug_Exit $@
401    fi
[913]402
[914]403    # Special actions depending on command to prepare IGCM_debug_PrintInfosActions call
[913]404    # We are interested in:
405    #  0. Which command performs the work
406    #  1. Size of entity we are working with
407    #  2. Where are we reading
408    #  3. Where are we writing
409    #  4. How long it took
410
[915]411    instrumentation=false
412
[913]413    case ${command} in
[925]414    # Classical copy (only files are given to IGCM_sys_Cp as options)
415    IGCM_sys_Cp)
416      instrumentation=true
417      # All but the latest
418      fileList=${arguments[*]:0:${#arguments[*]}-1}
419      # just need the first file to get the directory
420      source=${arguments[0]}
421      # Nothing but the latest
422      dest=${arguments[${#arguments[*]}-1]}
423      # Size of file whose name are stored in a list
424      entitySize=$( IGCM_debug_sizeOfTabContent fileList ${dest} )
425      ;;
426
[913]427    # Copy from archive machine or from buffer
428    IGCM_sys_Get|IGCM_sys_GetBuffer)
[915]429      instrumentation=true
[913]430      if [ ${#arguments[*]} -eq 2 ] ; then
431        source=${arguments[0]}
432        dest=${arguments[1]}
433        # Size of file whose name are stored in a variable
[917]434        entitySize=$( IGCM_debug_sizeOfTabContent source ${dest} )
[913]435      elif ( [ ${#arguments[*]} -eq 3 ] && [ ${arguments[0]} = '/l' ] ) ; then
[936]436        # IGCM_sys_Get /l liste_file[*] /ccc/scratch/cont003/dsm/p86denv/RUN_DIR/985998_14754/
[913]437        # Keep the array name hosting the all list
[936]438        eval set +A fileList \${${arguments[1]}}
[913]439        # just need the first file to get the directory
[936]440        source=${fileList[0]}
[931]441        dest=${arguments[2]}
[934]442        # Size of file whose name are stored in a list
[936]443        entitySize=$( IGCM_debug_sizeOfTabContent fileList[*] ${dest} )
[913]444      elif [ [ ${#arguments[*]} -ge 3 ] ; then
445       # All but the latest
[916]446        fileList=${arguments[*]:0:${#arguments[*]}-1}
[913]447        # just need the first file to get the directory
448        source=${arguments[0]}
449        # Nothing but the latest
450        dest=${arguments[${#arguments[*]}-1]}
451        # Size of file whose name are stored in a list
[917]452        entitySize=$( IGCM_debug_sizeOfTabContent fileList ${dest} )
[913]453      fi
454      ;;
455
[925]456    # Copy from compute node or copy to archive/buffer
457    IGCM_sys_Get_Master|IGCM_sys_Get_Dir|IGCM_sys_Put_Out|IGCM_sys_PutBuffer_Out)
[924]458      instrumentation=true
[916]459      source=${arguments[0]}
[924]460      dest=${arguments[1]}
461      # Size of file whose name are stored in a variable
462      entitySize=$( IGCM_debug_sizeOfTabContent source ${dest} )
[913]463      ;;
464
465    # Rebuild command
466    IGCM_sys_rebuild|IGCM_sys_rebuild_station)
[915]467      instrumentation=true
[913]468      # All but the first
469      fileList=${arguments[*]:1:${#arguments[*]}-1}
470      # just need a file to get the directory
471      source=${arguments[1]}
472      # Nothing but the first
473      dest=${arguments[0]}
474      # Size of file whose name are stored in a list
[917]475      entitySize=$( IGCM_debug_sizeOfTabContent fileList ${dest} )
[913]476      ;;
[941]477
[926]478    # NCO commands
479    IGCM_sys_ncrcat|IGCM_sys_ncecat|IGCM_sys_ncra|IGCM_sys_ncks|IGCM_sys_cdo)
480      # Example of what we want to catch : only filenames in those command lines
481      # IGCM_sys_ncrcat -O -v ${list_var_final_ncrcat} ${OUT_SE[*]} ${RESULT_SE}
482      # IGCM_sys_ncrcat --hst -v ${liste_coord}${var} ${file1} ${liste_file_tmp[*]} ${file_out}
483      # IGCM_sys_ncrcat -p ${dir} ${liste_file_tmp} --output ${output}
484      # IGCM_sys_ncrcat -x -v ${list_var} -p ${dir} ${liste_file_tmp} --output ${output}
485      instrumentation=true
[941]486      keepGoing=true
487      prefix=.
[926]488      i=0
489      while ( ${keepGoing} ) ; do
[941]490        # the last one is not interesting
491        if [ ${i} -eq ${#arguments[*]}-1 ] ; then
492          keepGoing=false
493        # look after "-p" option. Path prefix is the following arguments
494        elif [ ${arguments[${i}]} = "-p" ] ; then
[926]495          ((i = i + 1))
[941]496          prefix=${arguments[${i}]}
497          ((i = i + 1))
498        elif [ ${i} -eq ${#arguments[*]}-1 ] ; then
[926]499          keepGoing=false
[941]500        # looking for files
501        elif [ -f ${prefix}/${arguments[${i}]} ] ; then
502          fileList="${fileList} ${prefix}/${arguments[${i}]}"
503          ((i = i + 1))
504        # other options are not interesting
[926]505        else
506          ((i = i + 1))
507        fi
508      done
[941]509
[926]510      # i value is at least 1
511      # just need one file to get the directory
[941]512      source=$( echo ${fileList} | gawk '{print $1}' )
[926]513      # Nothing but the latest
514      dest=${arguments[${#arguments[*]}-1]}
515      # Size of file whose name are stored in a list
516      entitySize=$( IGCM_debug_sizeOfTabContent fileList ${dest} )
517      ;;
[913]518    esac
519
520    # Print information related to instrumentation
[915]521    ( ${instrumentation} ) && IGCM_debug_PrintInfosActions ${command} ${entitySize} ${startTime_ms} ${endTime_ms} ${dest} ${source}
[913]522
523    # Only cosmetics : stack file
[1115]524    if [ X${ActivateStackFilling} = Xtrue ] ; then
525      decal=0
526      while [ ${decal} -lt ${IGCM_debug_LenStack} ]; do
527        printf ' ' >> ${StackFileLocation}/${StackFileName}
528        (( decal = decal + 1 ))
529      done
530    fi
[2]531
[855]532    if ( ${ExitFlag} ) ; then
533      # Inform the stack file
[1115]534      if [ X${ActivateStackFilling} = Xtrue ] ; then
535        echo '!!! ExitFlag has been activated !!!' >> ${StackFileLocation}/${StackFileName}
536      fi
[874]537
[1216]538      # Unplugged message 4900 handling for now. To ease downstream treatment.
[1244]539      if [ X${ActivateBigBro} = Xtrue ] ; then
540        if [ X${TaskType} = Xcomputing ]; then
541          # RabbitMQ message code "COMPUTING JOBs COMMAND FAILURE"
542          code=1900
543        elif [ X${TaskType} = Xpost-processing ]; then
544          # RabbitMQ message code "POST-PROCESSING JOBs COMMAND FAILURE"
545          code=2900
546        elif [ X${TaskType} = Xchecking ]; then
547          # RabbitMQ message code "POST-PROCESSING FROM CHECKER JOBs COMMAND FAILURE"
548          code=3900
549        fi
550        # RabbitMQ message body
551        Body=$( echo "{${genericSimulationID},\"msgCode\":\"${code}\",\"msgUID\":\"$(uuidgen)\",\"command\":\"${command}\",\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\"}" )
552
553        # Fill the rabbitMQ queue
554        IGCM_debug_sendAMQP
555      fi
[855]556    else
557      # Inform the stack file
[1115]558      if [ X${ActivateStackFilling} = Xtrue ] ; then
559        echo "< ${IGCM_debug_LenStack} : ${@}" >> ${StackFileLocation}/${StackFileName}
560      fi
[855]561    fi
562
[913]563    # Reset array if necessary
[544]564    if [ ${IGCM_debug_LenStack} = 0 ]; then
565      #echo
566      #IGCM_debug_Print 3 "Clean stack array"
567      #echo
568      unset IGCM_debug_Stack
569      unset IGCM_debug_StackArgs
[913]570      unset IGCM_debug_StackTiming
[544]571      IGCM_debug_Stack[0]=${NULL_STR}
572      IGCM_debug_StackArgs[0]=${NULL_STR}
[913]573      IGCM_debug_StackTiming[0]=${NULL_STR}
[2]574    fi
[544]575  fi
[869]576  #IGCM_debug_CallStack
[2]577}
578
579#D-#==================================================================
[1189]580#D-function IGCM_debug_BigBro_Initialize
[855]581#D-* Purpose: switch rabbitMQ on
582#D-
[1189]583function IGCM_debug_BigBro_Initialize {
584  IGCM_debug_PushStack "IGCM_debug_BigBro_Initialize"
[855]585
[1244]586  typeset postProcessingIDLength postProcessingName postProcessingDate postProcessingDimn postProcessingComp postProcessingFile
[1229]587
[1051]588# Message type standard fields:
589# https://github.com/Prodiguer/prodiguer-docs/wiki/MQ-Standard-Message-Fields
590
591# Message type dictionnary and custom fields:
592# https://github.com/Prodiguer/prodiguer-docs/wiki/Monitoring-Message-Dictionary
593
[868]594  if [ X${BigBrother} = Xtrue ] ; then
[1051]595    # create a unique ID for this specific job
596    jobuid=$(uuidgen)
[913]597
[1244]598    # get the assigned id by the scheduler for that job
599    IGCM_sys_getJobSchedulerID jobSchedulerID
600
[1189]601    if [ X${TaskType} = Xcomputing ]; then
602      if ( ${FirstInitialize} ) ; then
603        # RabbitMQ message code "BEGIN A SIMULATION"
604        code=0000
605        # create and persist a unique id for this simulation
606        simuid=$(uuidgen)
607        IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration simuid ${simuid}
608        # Standard fields for the first message
[1244]609        genericSimulationID=$( echo "\"msgApplication\":\"monitoring\",\"msgProducer\":\"libigcm\",\"msgProducerVersion\":\"${libIGCMVersion}\",\"activity\":\"IPSL\",\"name\":\"${config_UserChoices_JobName}\",\"experiment\":\"${config_UserChoices_ExperimentName}\",\"space\":\"${config_UserChoices_SpaceName}\",\"model\":\"${config_UserChoices_TagName}\",\"startDate\":\"${config_UserChoices_DateBegin}\",\"endDate\":\"${config_UserChoices_DateEnd}\",\"login\":\"${LOGIN}\",\"centre\":\"${CENTER}\",\"machine\":\"${MASTER}\",\"simuid\":\"${simuid}\",\"jobuid\":\"${jobuid}\"" )
[1189]610        # RabbitMQ message body with specific fields associated message codes treated here
[1202]611        Body=$( echo "{${genericSimulationID},\"msgCode\":\"${code}\",\"accountingProject\":\"${PROJECT}\",\"jobWarningDelay\":\"${jobWarningDelay}\",\"msgUID\":\"$(uuidgen)\",\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\"}" )
[1189]612        # Fill the rabbitMQ queue (the config.card in use will be sent)
613        IGCM_debug_sendAMQP activate
614      else
615        # RabbitMQ message code "A NEW COMPUTING JOB IS RUNNING PART OF A SIMULATION"
616        code=1000
617        # retrieve this simulation's unique id
618        IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration simuid
619        simuid=${run_Configuration_simuid}
620        # Using standard fields for message others than the first one. Still subject to change
[1244]621        genericSimulationID=$( echo "\"msgApplication\":\"monitoring\",\"msgProducer\":\"libigcm\",\"msgProducerVersion\":\"${libIGCMVersion}\",\"simuid\":\"${simuid}\",\"jobuid\":\"${jobuid}\"" )
[1189]622        # RabbitMQ message body with specific fields associated message codes treated here
[1244]623        Body=$( echo "{${genericSimulationID},\"msgCode\":\"${code}\",\"accountingProject\":\"${PROJECT}\",\"jobWarningDelay\":\"${jobWarningDelay}\",\"jobSchedulerID\":\"${jobSchedulerID}\",\"jobSubmissionPath\":\"${SUBMIT_DIR}\",\"msgUID\":\"$(uuidgen)\",\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\"}" )
[1189]624        # Fill the rabbitMQ queue
625        IGCM_debug_sendAMQP
626      fi
627
628      # NOT VERY NICE BUT ... IT WORKS
629      # Be sure that the genericSimulationID will be small from now on
630      # Using standard fields for messages others than the first one. Still subject to change
[1244]631      genericSimulationID=$( echo "\"msgApplication\":\"monitoring\",\"msgProducer\":\"libigcm\",\"msgProducerVersion\":\"${libIGCMVersion}\",\"simuid\":\"${simuid}\",\"jobuid\":\"${jobuid}\"" )
[1189]632
633    elif [ X${TaskType} = Xpost-processing ]; then
634      # RabbitMQ message code "A NEW POST-PROCESSING JOB IS RUNNING PART OF A SIMULATION"
635      code=2000
[1076]636      # retrieve this simulation's unique id
[1051]637      IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration simuid
[1086]638      simuid=${run_Configuration_simuid}
[1076]639      # Using standard fields for message others than the first one. Still subject to change
[1244]640      genericSimulationID=$( echo "\"msgApplication\":\"monitoring\",\"msgProducer\":\"libigcm\",\"msgProducerVersion\":\"${libIGCMVersion}\",\"simuid\":\"${simuid}\",\"jobuid\":\"${jobuid}\"" )
[1229]641     
642      # Specify the post-processing task we are dealing with
[1244]643      postProcessingIDLength=$( echo "${Script_Post_Output}" | tr -d -c "\." | wc -c )
[1229]644      postProcessingName=$( echo "${Script_Post_Output}" | gawk -F. '{print $1}' )
645      postProcessingDate=$( echo "${Script_Post_Output}" | gawk -F. '{print $2}' )
[1231]646      postProcessingDimn="null"
647      postProcessingComp="null"
648      postProcessingFile="null"
[1254]649      if [ ${postProcessingIDLength} -eq 2 ] ; then
[1231]650        postProcessingDimn=$( echo "${Script_Post_Output}" | gawk -F. '{print $3}' )
[1254]651      elif [ ${postProcessingIDLength} -eq 4 ] ; then
[1229]652        postProcessingComp=$( echo "${Script_Post_Output}" | gawk -F. '{print $4}' )
653        postProcessingFile=$( echo "${Script_Post_Output}" | gawk -F. '{print $5}' )
654      fi
655
[1087]656      # RabbitMQ message body with specific fields associated message codes treated here
[1244]657      Body=$( echo "{${genericSimulationID},\"msgCode\":\"${code}\",\"accountingProject\":\"${PROJECT}\",\"jobWarningDelay\":\"${jobWarningDelay}\",\"jobSchedulerID\":\"${jobSchedulerID}\",\"jobSubmissionPath\":\"${SUBMIT_DIR}\",\"msgUID\":\"$(uuidgen)\",\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\",\"postProcessingName\":\"${postProcessingName}\",\"postProcessingDate\":\"${postProcessingDate}\",\"postProcessingDimn\":\"${postProcessingDimn}\",\"postProcessingComp\":\"${postProcessingComp}\",\"postProcessingFile\":\"${postProcessingFile}\"}" )
[1087]658      # Fill the rabbitMQ queue
659      IGCM_debug_sendAMQP
[855]660    fi
[913]661    # Turn the flag on
[855]662    ActivateBigBro=true
663  fi
[1189]664  IGCM_debug_PopStack "IGCM_debug_BigBro_Initialize"
[855]665}
666
667#D-#==================================================================
[1189]668#D-function IGCM_debug_BigBro_Finalize
669#D-* Purpose: Finalize rabbitMQ messages exchanges
670#D-
671function IGCM_debug_BigBro_Finalize {
672  IGCM_debug_PushStack "IGCM_debug_BigBro_Finalize"
673
674  # Message type standard fields:
675  # https://github.com/Prodiguer/prodiguer-docs/wiki/MQ-Standard-Message-Fields
676
677  # Message type dictionnary and custom fields:
678  # https://github.com/Prodiguer/prodiguer-docs/wiki/Monitoring-Message-Dictionary
679
680  if ( $DEBUG_debug ) ; then
681    if [ X${ActivateBigBro} = Xtrue ] ; then
682      if [ X${TaskType} = Xcomputing ]; then
683        if ( ${simulationIsOver} ) ; then
684          # RabbitMQ message code "SIMULATION ENDS"
685          code=0100
686          FlushAMQP=true
[1207]687        elif ( ${ExitFlag} ) ; then
688          # RabbitMQ message code "EXIT THE JOBS BECAUSE ERROR(S) HAS BEEN TRIGGERED"
[1244]689          code=1999
[1207]690          FlushAMQP=true
[1189]691        else
692          # RabbitMQ message code "COMPUTING JOB ENDS"
693          code=1100
694        fi
695      elif [ X${TaskType} = Xpost-processing ]; then
[1207]696        if ( ${ExitFlag} ) ; then
697          # RabbitMQ message code "POST-PROCESSING JOB FAILS"
[1244]698          code=2999
[1207]699          FlushAMQP=true
[1244]700        else
[1207]701          # RabbitMQ message code "POST-PROCESSING JOB ENDS"
702          code=2100
703          FlushAMQP=true
704        fi
[1244]705      elif [ X${TaskType} = Xchecking ]; then
706        if ( ${ExitFlag} ) ; then
707          # RabbitMQ message code "POST-PROCESSING JOB FAILS"
708          code=3999
709          FlushAMQP=true
710        else
711          # RabbitMQ message code "POST-PROCESSING JOB ENDS"
712          code=3100
713          FlushAMQP=true
714        fi
[1189]715      fi
716      # RabbitMQ message body
717      Body=$( echo "{${genericSimulationID},\"msgCode\":\"${code}\",\"msgUID\":\"$(uuidgen)\",\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\"}" )
718      # Fill the rabbitMQ queue
719      IGCM_debug_sendAMQP
720    fi
721  fi
722 
723  IGCM_debug_PopStack "IGCM_debug_BigBro_Finalize"
724}
725
726#D-#==================================================================
[2]727#D-function IGCM_debug_Exit
728#D-* Purpose: Print Call Stack and set ExitFlag to true
729#D-
730function IGCM_debug_Exit {
[544]731  IGCM_debug_PushStack "IGCM_debug_Exit"
732  echo "IGCM_debug_Exit : " "${@}"
[913]733  echo
[894]734  echo "!!!!!!!!!!!!!!!!!!!!!!!!!!"
[913]735  echo "!!   ERROR TRIGGERED    !!"
736  echo "!!   EXIT FLAG SET      !!"
737  echo "!------------------------!"
738  echo
[894]739  IGCM_debug_CallStack
[544]740  ExitFlag=true
741  IGCM_debug_PopStack "IGCM_debug_Exit"
[2]742}
743
744#D-#==================================================
745#D-function IGCM_debug_Verif_Exit
746#D-* Purpose: exit with number 1 if ExitFlag is true
747#D-
748function IGCM_debug_Verif_Exit {
[544]749  if ( ${ExitFlag} ) ; then
[1206]750    echo "IGCM_debug_Verif_Exit : Something wrong happened previously."
[1207]751    echo "IGCM_debug_Verif_Exit : ERROR and EXIT keyword will help find out where."
[1206]752    # Only computing TaskType stops the job for now.
753    if [ X${TaskType} = Xcomputing ] ; then
[775]754      IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Fatal"
755      echo "                        EXIT THE JOB."
756      echo
[869]757      IGCM_debug_CallStack
[874]758
[1206]759      # Mail notification
760      IGCM_sys_SendMail
[913]761
[1207]762      # Inform the rabbitMQ queue
763      IGCM_debug_BigBro_Finalize
764
[544]765      # And Good Bye
766      date
767      exit 1
[1206]768
769    elif [ X${TaskType} = Xpost-processing ] ; then
770      # If SpaceName is PROD then we stop when post_processing failed
771      if [ X${config_UserChoices_SpaceName} = XPROD ] ; then
[1220]772        echo "                        EXIT THE POST-PROCESSING JOB."
[1206]773        echo
[1207]774        IGCM_debug_CallStack
775
[1220]776        # Notify the computing job that something wrong happened.
777        IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Fatal"
778
[1206]779        # Mail notification?
780        #IGCM_sys_SendMailPost
[1207]781
782        # Inform the rabbitMQ queue
783        IGCM_debug_BigBro_Finalize
784
[1206]785        # And Good Bye
786        date
787        exit 1
788      else
[1207]789        echo "In config.card the variable SpaceName is not in PROD"
[1206]790        echo "              SO WE DO NOT EXIT THE JOB."
791        echo
792        date
793      fi
794    elif [ X${TaskType} = Xchecking ] ; then
[1207]795      echo "Nothing will happen for now"
[2]796    fi
[544]797  fi
[2]798}
799
800#D-#==================================================================
801#D-function IGCM_debug_Print
802#D-* Purpose: Print arguments according to a level of verbosity.
803#D-
804function IGCM_debug_Print
805{
[544]806  typeset level=$1
807  shift
808
809  if [ X"${1}" = X"-e" ]; then
810    typeset cmd_echo="echo -e"
[2]811    shift
[544]812  else
813    typeset cmd_echo="echo"
814  fi
[2]815
[544]816  if [ ${level} -le ${Verbosity} ] ; then
817    typeset i
818    case "${level}" in
819    1) for i in "$@" ; do
[734]820      ${cmd_echo} $(date +"%Y-%m-%d %T") "--Debug1-->" ${i}
[913]821      done ;;
[544]822    2) for i in "$@" ; do
[734]823      ${cmd_echo} $(date +"%Y-%m-%d %T") "--------Debug2-->" ${i}
[913]824      done ;;
[544]825    3) for i in "$@" ; do
[734]826      ${cmd_echo} $(date +"%Y-%m-%d %T") "--------------Debug3-->" ${i}
[913]827      done ;;
[544]828    esac
829  fi
[2]830}
831
832#D-#==================================================================
833#D-function IGCM_debug_PrintVariables
834#D-* Purpose: Print arguments when match a pattern
835#D-           according to a level of verbosity.
836function IGCM_debug_PrintVariables
837{
[544]838  typeset level=$1
839  shift
[2]840
[830]841  list=$( set | grep ^$1 | sed -e "s/'//g" )
[54]842
[544]843  if [ "X${list}" != X ]  ; then
844    IGCM_debug_Print ${level} ${list}
845  fi
[2]846}
847
848#D-#==================================================================
[914]849#D-function IGCM_debug_PrintInfosActions
[913]850#D-* Purpose: Print information related to instrumentation
851function IGCM_debug_PrintInfosActions
852{
853  typeset actionType=$1
854  typeset entitySize=$2
855  typeset start_ms=$3
856  typeset end_ms=$4
857
858  typeset dest=$5
859  typeset source=$6
860
861  typeset diff_ms entitySizeKo entitySizeMo flux_Ko_ms flux_Ko_s flux_Mo_s
[1090]862  typeset dirFrom dirTo
[913]863
864  diff_ms=$(( $end_ms - $start_ms ))
865  # echo "diff_ms=$diff_ms"
866
867  entitySizeKo=$( echo ${entitySize} | gawk -F"|" '{print $1}' )
868  # echo "entitySizeKo=$entitySizeKo"
869  entitySizeMo=$( echo ${entitySize} | gawk -F"|" '{print $2}' )
870
871  # flux en Ko / ms
872  flux_Ko_ms=$( echo "scale=6;${entitySizeKo}/${diff_ms}" | bc )
873  # echo "flux_Ko_ms=$flux_Ko_ms"
874
875  # flux en Ko / s
876  flux_Ko_s=$(( $flux_Ko_ms * 1000 ))
877  # echo "flux_Ko_s=$flux_Ko_s"
878
879  # flux en Mo / s
880  flux_Mo_s=$( echo "scale=6;${flux_Ko_s}/1024" | bc )
881  # echo "flux_Mo_s=$flux_Mo_s"
882
883  if [ -d $dest ] ; then
[1090]884    dirTo=$( readlink -f ${dest} )
[913]885  else
[1090]886    dirTo=$( readlink -f $( dirname ${dest} ) )
[913]887  fi
888
889  if [ -d $source ] ; then
[1090]890    dirFrom=$( readlink -f ${source} )
[913]891  else
[1090]892    dirFrom=$( readlink -f $( dirname ${source} ) )
[913]893  fi
894
[1094]895  instrumentationContent=$( echo "\"actionName\":\"${actionType}\",\"size_Mo\":\"${entitySizeMo}\",\"duration_ms\":\"${diff_ms}\",\"throughput_Mo_s\":\"${flux_Mo_s}\",\"dirFrom\":\"${dirFrom}\",\"dirTo\":\"${dirTo}\"" )
[1050]896
[1115]897  if [ X${ActivateStackFilling} = Xtrue ] ; then
898    echo "{${instrumentationContent}}" >> ${StackFileLocation}/${StackFileName}
899  fi
[1050]900
901  # Inform the rabbitMQ queue
902  if [ X${ActivateBigBro} = Xtrue ] ; then
903    # RabbitMQ message body
[1065]904    Body=$( echo "{${genericSimulationID},\"msgCode\":\"7000\",\"msgUID\":\"$(uuidgen)\",${instrumentationContent},\"msgTimestamp\":\"$( date +"%Y-%m-%dT%H:%M:%S.%N%z" )\"}" )
[1050]905    # Fill the rabbitMQ queue
906    IGCM_debug_sendAMQP
907  fi
[913]908}
909
910#D-#==================================================================
[2]911#D-function IGCM_debug_Check
912#D- * Purpose: Check the present file by comparison with a reference file
913function IGCM_debug_Check
914{
[544]915  #---------------------
916  if [ ! -n "${libIGCM}" ] ; then
917    echo "Check libIGCM_debug ..........................................[ FAILED ]"
918    echo "--Error--> libIGCM variable is not defined"
919    exit 2
920  fi
[2]921
[544]922  #---------------------
923  if [ ! -n "${Verbosity}" ] ; then
924    echo "Check libIGCM_debug ..........................................[ FAILED ]"
925    echo "--Error--> Verbosity variable is not defined"
926    exit 3
927  fi
[2]928
[544]929  #---------------------
[1118]930  # Need to remove timestamps here
931  diff ${libIGCM}/libIGCM_debug/IGCM_debug_Test.ref <(${libIGCM}/libIGCM_debug/IGCM_debug_Test.ksh | sed -e "s:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]\:[0-9][0-9]\:[0-9][0-9] ::g") > /dev/null 2>&1
[1106]932  status=$?
[2]933
[1118]934  if [ ${status} -eq 0 ] ; then
[544]935    echo "Check libIGCM_debug ..............................................[ OK ]"
936  else
937    echo "Check libIGCM_debug ..........................................[ FAILED ]"
938    echo "--Error--> Execution of ${libIGCM}/libIGCM_debug/IGCM_debug_Test.ksh"
939    echo "           has produced the file IGCM_debug_Test.ref.failed"
940    echo "           Please analyse differences with the reference file by typing:"
941    echo "           diff IGCM_debug_Test.ref.failed ${libIGCM}/libIGCM_debug/IGCM_debug_Test.ref"
942    echo "           Report errors to the author: Patrick.Brockmann@cea.fr"
[1118]943    diff ${libIGCM}/libIGCM_debug/IGCM_debug_Test.ref <(${libIGCM}/libIGCM_debug/IGCM_debug_Test.ksh | sed -e "s:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]\:[0-9][0-9]\:[0-9][0-9] ::g")
[544]944    exit 4
945  fi
946  #---------------------
[2]947}
Note: See TracBrowser for help on using the repository browser.