#! /bin/csh -f
#
#  Setup a service for fetching Plasma States from a prior TRANSP or PTRANSP
#  run.
#
#  There are three main actions:
#    "INIT" -- set up the service connection to a specific run; cache data 
#              from MDS+ server as needed.
#    "FETCH" -- fetch a plasma state from the specified run at indicated time.
#    "KILL" -- shut down the service connection.
#
#  A "trxpl" executable is resident under piped script control, when the
#  service is active, i.e. between the INIT and KILL invokations.
#
#  While the server is resident, the requisite time dependent TRANSP data
#  is in memory; extraction of each plasma state is rapid and efficient.
#
#    (csh subprocedures: ichannel, uread_server, uread_send_wait).
#
#  Arguments to main actions:
#    INIT <FILE|MDS+> <TRANSP-path> <output-path> [mdescr-filename]
#    FETCH <time> <output-path> <state-name> [sawtooth] [mhdeq]
#    KILL <output-path>
#
#  where: <FILE|MDS+> selects file based or MDS+ based TRANSP run data access;
#    (literal strings "FILE" or "MDS+" to be provided);
#
#    and: <TRANSP-path> is the file path or MDS+ path to the run; a FILE path 
#         is a <directory-path>/<runid>; <runid>.CDF sought in the directory.
#         An MDS+ path is a string of form 
#           <MDS+-server>:<MDS+-treename>(<MDS+-number>)  ..or..
#           <MDS+-server>:<MDS+-treename>(<tok.yy>,<runid>)
#             (the proper syntax to use depends on the server)
#               example: TRANSPGRID.PPPL.GOV:TRANSP(TFTR.88,37065P35)
#
#    and: <output-path> is an existing directory where output data is to
#         be written; if at INIT time the directory does not exist but it's
#         parent does exist, it will be created with "mkdir".
#
#    and: <time> is the time at which to extract the data;
#
#    and: <state-name> is the name of the state file to write
#         (omit ".cdf" i.e. give <state-name> = "abc" to get file "abc.cdf")
#
#    and: [sawtooth] is an optional keyword, a hint for an immediate
#         post-sawtooth time point.
#
#    and: [mhdeq] is an optional keyword, a request that TRANSP MHD equilibrium
#         data be included in the output state; by default it is omitted.
#
#  there can be multiple concurrently active services but only one service
#  associated with each <output-path>.  The <output-path> specification 
#  identifies the service instance, which is why it is a required argument
#  for every action.
#-------------------------------
#

# For debugging
  set TRX_LOGDIR = /p/tsc/trxpl
  set TRX_LOG    = $TRX_LOGDIR/trxpl_server.log
  if ( -w $TRX_LOG ) then
     set ROOT_DIR = `pwd`
     set uname = `whoami`
     set NODE = `hostname`
     set DO_LOG = 1
  endif
#-----------------------

  @ ier = 0
  if ( $#argv < 2 ) then
    @ ier++
  else
    set action = $1
    if ( "$action" != "INIT" && "$action" != "FETCH" && \
         "$action" != "KILL" ) then
      @ ier++
    endif
  endif

  if ( $ier > 0 ) then
    echo " ?syntax: trxpl_server < INIT | FETCH | KILL > <args...> "
    exit 1
  endif

#------------------------------------------------------
  if ( "$action" == "FETCH" ) then
    if ( $#argv < 4 ) then
      @ ier++
    else

      set time = $2
      set opath = $3
      set state_name = $4

      set cpath = $opath/trxpl_comm

      set stype = light
      set sawmode = normal

      @ iargc = 4
      while ( $iargc < $#argv )
        @ iargc++
        set this_arg = $argv[$iargc]
        if ( "$this_arg" == "mhdeq" ) then
          set stype = heavy
        else if ( "$this_arg" == "sawtooth" ) then
          set stype = sawtooth
        else 
          @ ier++
          echo " ?trxpl_server: unrecognized keyword: $this_arg "
        endif
      end
    endif

    if ( $ier > 0 ) then
      echo " ?syntax: trxpl_server FETCH <time> <output-path> <state-name> [sawtooth] [mhdeq]"
      exit 1
    endif

    echo "FETCH syntax OK"

    if ( ! -d $opath ) then
      @ ier++
      echo " trxpl_server FETCH: server output directory not found: $opath ..."
    endif

    if ( ! -d $cpath ) then
      @ ier++
      echo " trxpl_server FETCH: server comm directory not found: $cpath ... "
    endif

    if ( $ier > 0 ) then
      exit 1
    endif

    set uscript = tr_playback
    set stpath = $opath/$state_name

    echo uread_server send $cpath wait:$stpath.mdescr @$uscript /stype=$stype \
              /time=$time /wpath=\"$stpath\" /key=$sawmode

    uread_server send $cpath wait:$stpath.mdescr @$uscript /stype=$stype \
              /time=$time /wpath=\"$stpath\" /key=$sawmode

    set tstat = $status

    if ( $tstat != 0 ) then
      echo " ? trxpl_server -- FETCH failed. "
      exit 1
    endif

    rm -f $stpath.mdescr
    rm -f $stpath.sconfig

    echo "========"
    echo "FETCH OK"
    echo "========"
  endif
#------------------------------------------------------
  if ( "$action" == "INIT" ) then
    if ( $#argv != 4 && $#argv != 5 ) then
      @ ier++
    else

      set mode = $2
      set tpath = $3
      set opath = $4
      set mdescr = NONE
      if ( $#argv == 5 ) then
        set mdescr = $5
      endif
    endif

    if ( "$mode" != "FILE" && "$mode" != "MDS+" ) then
      @ ier++
    endif

    if ( $ier > 0 ) then
      echo " ?syntax: trxpl_server INIT <FILE|MDS+> <TRANSP-path> <output-path> [mdescr-filename]"
      exit 1
    endif

# Verify we don't alredy have an open channel 
    if ( -f $opath/trxpl_comm/pid.dat ) then
       echo " %trxpl_server -W- $opath was already initialized"
       echo "                   will KILL $opath"
       if ($?DO_LOG) then
          echo "`date`  -W-   ${uname}: $ROOT_DIR $opath was already initialized" >> $TRX_LOG
          echo "                                     will KILL $opath on $NODE" >> $TRX_LOG
       endif
       uread_server kill $opath/trxpl_comm
       sleep 2
    else
# if user deleted directory, check for ichannel
       set plist=`ps uxw | grep ichannel | grep $opath/trxpl_comm | awk '{print $2}'`
       @ i = 0
       while ( $i < $#plist ) 
         @ i++
         echo "==========================================================================="
         echo " %trxpl_server -W- ichannel $opath/trxpl_comm pid=$plist[$i] already running"
         echo "                            will initialize new one"
         echo "==========================================================================="
         if ($?DO_LOG) then
           echo "`date`  -W-   ${uname}: $opath pid=$plist[$i] already running on $NODE" >> $TRX_LOG
           echo "                                     will initialize new $opath in $ROOT_DIR" >> $TRX_LOG
         endif
       end
    endif

    if ( ! -d $opath ) then
      # try to create
      mkdir $opath
    endif

    if ( ! -d $opath ) then
      echo " ?trxpl_server INIT: could not find or create output path: $opath "
      exit 1
    endif

    set cpath = $opath/trxpl_comm

    echo " INIT syntax OK: $mode $tpath $opath $cpath "

    if ( -d $cpath ) then
      echo " INIT: make clean communications directory: $cpath "
      # save pid
      if ( -f $cpath/pid.dat ) then
          mv $cpath/pid.dat $opath/
          mv $cpath/progname.dat $opath/ >& /dev/null
      endif
      rm -r $cpath
      mkdir $cpath
      if ( -f $opath/pid.dat ) then
          mv $opath/pid.dat $cpath/
          mv $opath/progname.dat $cpath/ >& /dev/null
      endif
    endif

    set stype = heavy
    set time = 0.0
    set sawpath = $opath/sawtimes.dat
    set propath = $opath/protimes.dat
    set uscript = tr_playback_init

    if ( ! $?RPLOT_CACHE ) then
      setenv RPLOT_CACHE TRUE
    endif

    unsetenv RPLOT_CACHE_ONLY

    echo "trxpl_server INIT -- I/O test; load MDS+ cache..."

    echo trxpl @$uscript /stype=$stype \
              /mode=$mode /path=\"$tpath\" /time=$time \
              /wpath=\"$opath/init_test\" \
              /propath=\"$propath\" \
              /sawpath=\"$sawpath\" \
              /mdescr=\"$mdescr\" 

    trxpl @$uscript /stype=$stype \
              /mode=$mode /path=\"$tpath\" /time=$time \
              /wpath=\"$opath/init_test\" \
              /propath=\"$propath\" \
              /sawpath=\"$sawpath\" \
              /mdescr=\"$mdescr\" 

    set tstat = $status

    if ( $tstat != 0 ) then
      echo " ? trxpl_server -- INIT failed. "
      exit 1
    endif

    echo "============"
    echo "INIT TEST OK"
    echo "============"

    # OK -- server launch...

    setenv RPLOT_CACHE_ONLY TRUE
    set uscript = tr_playback_start

    echo uread_server init $cpath trxpl @$uscript \
            /mode=$mode /path=\"$tpath\" /time=$time /mdescr=\"$mdescr\" 

    echo uread_server init $cpath trxpl @$uscript \
            /mode=$mode /path=\"$tpath\" /time=$time /mdescr=\"$mdescr\"  \
            >$opath/init.cmd

    uread_server init $cpath trxpl @$uscript \
            /mode=$mode /path=\"$tpath\" /time=$time /mdescr=\"$mdescr\" 

    set tstat = $status

    if ( $tstat != 0 ) then
      echo " ? trxpl_server -- INIT failed. "
      exit 1
    endif

    echo "======="
    echo "INIT OK"
    echo "======="

    # Write record for debugging   
    if ($?DO_LOG) then
       set DATE=`date`  
       echo "$DATE -INIT- ${uname}: $ROOT_DIR $cpath">>  $TRX_LOG
       echo "                                     on $NODE" >> $TRX_LOG
    endif
  endif    

#------------------------------------------------------
  if ( "$action" == "KILL" ) then
    if ( $#argv > 2 ) then
      echo " ?syntax: trxpl_server KILL <output-path> "
      exit 1
    endif

    set opath = $2
    set cpath = $opath/trxpl_comm

    if ( ! -d $opath ) then
      @ ier++
      echo " trxpl_server KILL: server output directory not found: $opath ... "
    endif

    if ( ! -d $cpath ) then
      @ ier++
      echo " trxpl_server KILL: server comm directory not found: $cpath ... "
    endif

    if ( $ier > 0 ) then
      exit 1
    endif

    echo " KILL OK: $opath $cpath "
    uread_server kill $cpath
    rm -f $opath/init.cmd
# Write record for debugging 
    if ($?DO_LOG) then
       set DATE=`date`    
       echo "$DATE -KILL- ${uname}: $ROOT_DIR $cpath" >>  $TRX_LOG
       echo "                                     on $NODE" >> $TRX_LOG
    endif    

  endif

#------------------------------------------------------
  exit 0
