#!/bin/ksh #create_ioassign version: 20130305 set -eu #======================================================================= # # Script create_ioassign # ---------------------- # # Purpose : To create IOASSIGN file for the given ODB database # # Usage : create_ioassign # ----- -l dbname ; database name # [-d dirname ; location of ioassign_file] # [-n npools] # [-x] ; expand ioassign_file to get rid of percent-d's # [-t task] ; component databases; use with -x # [-s] ; use this if surface analysis # [-e] ; use this if ensemble data assimilation # [-q] ; be quiet (except for fatal errors) # # Parameters : dbname - database name, like ECMA or CCMA; must be supplied # ---------- dirname - directory where the IOASSIGN will be placed ; # the default: $PWD # npools - number of pools (default: from $dbname/ECMA.dd) # task - component database(s); like -t amsua for ECMA.amsua # #======================================================================= ARGS="$0 $*" USAGE1="$0 -l dbname [-d dirname] [-n npools]" USAGE2=" [-x (to expand ioassign) [-s (if surface analysis)] -t task1 [-t task2] ...]" USAGE3=" [-q (quiet)] [-b iobufsize]" dbname=none dir=. npools=0 expand=0 alltasks="" surf=0 ensemble=0 silence=0 errflg=0 FLAGS="d:l:n:sqt:xe" while getopts $FLAGS option do case $option in l) dbname=$OPTARG;; d) dir="$OPTARG";; n) npools=$OPTARG;; s) surf=1;; e) ensemble=1;; q) silence=1;; t) alltasks="$alltasks $OPTARG";; x) expand=1;; \?) errflg=1;; esac done if [[ $silence -eq 0 ]] ; then echo "$ARGS" >&2 fi #======================================================================= # Check parameters #======================================================================= if [[ $dbname = none ]] ; then echo "$0: An invalid dbname=$dbname was supplied via -l option" >&2 errflg=1 fi [[ -d $dir ]] || mkdir -p $dir || errflg=1 if [[ ! -d $dir ]] ; then echo "$0: Database dir '$dir' not found" >&2 errflg=1 fi if [[ $expand -eq 1 && "$alltasks" = "" ]] ; then alltasks=$(cd $dir/.. ; \ls -C1pd $dbname.* | \ awk -F/ '{print $1}' | sed "s/^$dbname\.//g" | sort -u) fi if [[ $errflg -ne 0 ]] ; then echo "$ARGS" >&2 echo $USAGE1 >&2 echo $USAGE2 >&2 echo $USAGE3 >&2 exit 1 fi ddfile=$dir/$dbname.dd if [[ $npools -le 0 ]] ; then # try to find out correct no. of pools if [[ -s $ddfile ]] ; then npools=$(head -5 $ddfile | tail -1) else npools=${ODB_IOASSIGN_MAXPROC:=0} # If == 0, can be usually a bad thing ;-( fi if [[ $silence -eq 0 ]] ; then echo "$0: Total no. of pools was detected automatically from file '$ddfile' ;" >&2 echo " Using value for npools='$npools'" >&2 fi fi io_method=${ODB_IO_METHOD:=4} if [[ -s $ddfile ]] ; then iom=$(head -1 $ddfile | awk 'BEGIN {n=0;} {if (NF >= 3) n=$3;} END {print n;}') [[ $iom -ne 0 ]] || io_method=$iom fi #-- More I/O-buffering when either less pools or I/O-method found to be horizontal concatenation if [[ $npools -lt 32 ]] || [[ $io_method -eq 4 ]] ; then iodef="-r 8m -w 8m -p 8m -e 8m" else iodef="-r 1m -w 1m -p 1m -e 1m" fi #-- Get list of tables either from existing $ddfile or using latest known tables if [[ -s $ddfile ]] ; then tables=$(egrep "^@" $ddfile | awk '{print $1}' | perl -pe 's#\@# #g;') else #-- Known tables in alphabetical order tables="aeolus_auxmet aeolus_hdr aeolus_l2c" tables="$tables body bufr bufr_tables bufr_tables_desc" tables="$tables ddrs desc errstat hdr index poolmask resat" tables="$tables rtovs rtovs_body rtovs_mlev rtovs_pred rtovs_slev" tables="$tables sat satem satob scatt scatt_body smos ralt" tables="$tables ssmi ssmi_body ssmi_mlev ssmi_slev" tables="$tables timeslot_index update limb resat_averaging_kernel" tables="$tables radar radar_body radar_station" tables="$tables surfbody_feedback modsurf radiance allsky co2_sink cloud_sink collocated_imager_information" tables="$tables auxiliary auxiliary_body radiance_body allsky_body fcdiagnostic" tables="$tables gbrad gbrad_body gnssro gnssro_body" tables="$tables ensemble conv conv_body raingg raingg_body" #-- Include only minimal amount of update tables # Note: can't use MXUP_TRAJ, since $NMXUPD in data layout may have a larger value jpmxup=10 # from source code of IFS ; see ifs/module/parcma.F90 uptraj=0 while [[ $uptraj -lt $jpmxup ]] do ((uptraj += 1)) tables="$tables update_$uptraj" done jpmxenkf=120 # from source code of IFS ; see ifs/module/parcma.F90 enkf_count=0 while [[ $enkf_count -lt $jpmxenkf ]] do ((enkf_count += 1)) tables="$tables enkf_$enkf_count" done jpmxenda=100 # from source code of IFS ; see ifs/module/parcma.F90 enda_count=0 while [[ $enda_count -lt $jpmxenda ]] do ((enda_count += 1)) tables="$tables enda_$enda_count" done enda_count=0 while [[ $enda_count -lt $jpmxenda ]] do ((enda_count += 1)) tables="$tables surfbody_feedback_$enda_count" done jpmxfcdiag=20 #from source code of IFS ; see ifs/module/parcma.F90 fcdiag_count=0 while [[ $fcdiag_count -lt $jpmxfcdiag ]] do ((fcdiag_count += 1)) tables="$tables fcdiagnostic_body_$fcdiag_count" done fi #-- Start creating IOASSIGN-file (in the fastest possible way ?) # ioassign -s -n $npools $iodef -a \$ODB_DATAPATH_$dbname/%d/$cmd $dbname..%d unset IOASSIGN || : tmpfile=__ioassign__.$$ cat /dev/null > $tmpfile ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.dd $dbname >> $tmpfile ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.sch $dbname.sch >> $tmpfile ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.flags $dbname.flags >> $tmpfile ioassign -s -a \$ODB_SRCPATH_$dbname/$dbname.iomap $dbname.iomap >> $tmpfile #-- dca : direct column access -files (globally one file per table) # only applicable for self-contained databases i.e. $expand == 0 dcadir=dca if [[ $expand -eq 0 ]] && [[ $alltasks == "" ]] ; then echo "tables=$tables" awk \ '(NR==1) { dca=$0; };(NR >= 2) { \ for (i=1; i<=NF; i++) { x=dca; gsub("TABLENAME",$i,x); print x; }}' >> $tmpfile \ </dev/null | head -1) if [[ "$hdrgz" != "" ]] ; then cmd=".gz -c #gzip" else cmd="" fi if [[ $ensemble -eq 1 ]] ; then dots="/../../" else dots="/" fi #-- No gzipping of QTARFILE ($ODB_IO_METHOD = 3) ioassign -s -n $npools $iodef -a \$ODB_DATAPATH_$dbname/%d/QTARFILE $dbname.QTARFILE.%d >> $tmpfile if [[ $alltasks != "" ]];then #e.g. multiple tasks - ECMA.conv, ECMA.amsua etc if [[ $surf -eq 1 ]] ; then dots="/../../" else dots="/../" fi p=0 for task in $alltasks do # read npools in this xCMA.x from the .dd file d=$dir$dots$dbname.$task ddfile=$d/$dbname.dd np=$(head -5 $ddfile | tail -1) # Calculate global pool number range for this ECMA.x ((psta = p + 1)) ((pend = p + np)) p=$pend ioassign -S $psta -s -n $np $iodef -a \$ODB_DATAPATH_$dbname$dots$dbname.$task/%d/%s$cmd $dbname.%s.%d >> $tmpfile done else # e.g. single CCMA ioassign -s -n $npools $iodef -a \$ODB_DATAPATH_$dbname$dots%d/%s$cmd $dbname.%s.%d >> $tmpfile fi else # Expand #-- Create template file for table=_xxx_ for subsequent filtering tbl=_xxx_ template=__template__.$$ cat /dev/null > $template p=0 if [[ $surf -eq 1 ]] ; then dots="../.." else dots=".." fi for task in $alltasks do d=$dir/$dots/$dbname.$task ddfile=$d/$dbname.dd if [[ $silence -eq 0 ]] ; then echo "$0: Processing $ddfile ; p=$p" >&2 fi if [[ -s $ddfile ]] ; then #-- Sense whether gzipped already ? hdrgz=$(find [0-9]* -type f -name 'hdr.gz' -print 2>/dev/null | head -1) if [[ "$hdrgz" != "" ]] ; then cmd=".gz -c #gzip" else cmd="" fi np=$(head -5 $ddfile | tail -1) ((psta = p + 1)) ((pend = p + np)) #-- In the following the %d after "-a" option i.e. physical filename # expands (-x) between range [1 .. $np], but the logical filename's %d # expands between range [$psta .. $pend] i.e [$psta .. $psta + $np - 1] (due to -S) ioassign -s -x -n $np -S $psta $iodef \ -a \$ODB_DATAPATH_$dbname/$dots/$dbname.$task/%d/$tbl$cmd \ $dbname.$tbl.%d >> $template p=$pend fi # if [[ -s $ddfile ]] done if [[ $p -ne $npools ]] ; then if [[ $silence -eq 0 ]] ; then echo "$0: ***Warning: Inconsistent no. of pools found=$p ; expected=$npools" >&2 fi fi #-- Now filter "_xxx_" across all tables using Perl to create final IOASSIGN-file # for tbl in $tables # do # perl -pe "s/_xxx_/$tbl/g" < $template >> $tmpfile # done cat << \EOF > create_ioassign_perl.pl use strict; use warnings; my $tables = $ENV{'tables'}; my @tables=split(/\s+/,$tables); my $templ_file=$ENV{'template'}; my $tmpfile=$ENV{'tmpfile'}; my(@lines); if(!open(INFIL,$templ_file)) { print STDERR "Can't open $templ_file for reading\n"; die("Can't open $templ_file for reading\n"); } open(OUT,">>$tmpfile"); @lines=; close INFIL; my $line; for (@tables) { my $tbl=$_; for (@lines) { $line=$_; $line=~s/_xxx_/$tbl/g; print OUT $line; } } EOF export tables template tmpfile perl create_ioassign_perl.pl rm -f $template fi rm -f $dir/*IOASSIGN* || true cp $tmpfile $dir/$dbname.IOASSIGN rm -f $tmpfile # for compatibility & convenience (cd $dir ; \rm -f IOASSIGN.$dbname ; \ln -s $dbname.IOASSIGN IOASSIGN.$dbname) (cd $dir ; \rm -f IOASSIGN ; \ln -s $dbname.IOASSIGN IOASSIGN) exit 0