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

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