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

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