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

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