#!/bin/sh

#   Nov 25/16   S. Kharin (Simplify and remove more junk)
#   Nov 2016  - N. Swart  (Adapt to using sqlite database (via fdb),
#                          and remove excess junk )
#   Feb 25/02 - F.Majaess (Revised for SX6)
#   Jan 05/00 - F.Majaess (Added kz/kaze)
#   Jan 21/99 - F.Majaess (Added yo/yonaka)
#   Jul 14/97 - F.Majaess (Revise for hiru)
#   Mar 18/97 - F.Majaess (Revise for group file ownership)
#   Aug 26/96 - F.Majaess (Revise to use "samefs" instead of relying on "df")
#   Jul 15/96 - F.Majaess (Revise for SX4)
#   Dec 08/95 - F.Majaess (Replace 'hostname' calls by "$HOSTID")
#   Jun 05/95 - F. Majaess (disble changing c3cnet RUNPATH to 3rcnet on sx3r)
#   May 29/95 - F. Majaess (Temporarily change c3cnet RUNPATH to 3rcnet on sx3r)
#   Feb 13/95 - F. Majaess (enforce "pfn" to be in lower case)
#   Nov 08/94 - F. Majaess (Modify for sx3r)
#   Jan 31/94 - F. Majaess (Ensure error detection due to filesystem failure)
#   Dec 29/93 - F. Majaess (Modify for saving files from other than
#                           "$RUNPATH")
#   Mar 08/93 - E. Chan (Save with no file access for "others")
#   Jan 19/92 - E. Chan (Add printing out of info at completion of script)
#   Nov 24/92 - E. Chan (Modify to save files on current file system
#                        and add corresponding symbolic links to the
#                        official CCRD/N data directory)
#   Nov 18/92 - E. Chan (Replace copy of file to data directory with a
#                        move followed by a symbolic link)
#   Sep 08/92 - E. Chan (Modify check for executable binaries for MIPS)
#   Sep 10/91 - E. Chan

#id save - saves a file on the user's own run directory and establishes
#id        a symbolic link by the same name on the offical CCRD/N data
#id        directory

#   AUTHOR  - E. Chan

#hd PURPOSE - If the current directory is residing on the same filesystem
#hd           as the user's '$RUNPATH' directory then:
#hd             "save" moves the file into the user's own '$RUNPATH' directory
#hd             and appends an edition number to the filename.
#hd
#hd             After the file is moved, a symbolic link to the file is made
#hd             in the directory from which "save" was invoked to replace
#hd             the local version of the file. This is like a copy operation
#hd             without incurring the penalty for I/O.
#hd           otherwise,
#hd             "save" copies the file into the user's own '$RUNPATH' directory
#hd             which can reside on the other back-end machine if running on
#hd             the back-end and appends an edition number to the filename.
#hd
#hd             In addition, a ".fn"_Link soft link to the permanent dataset is
#hd             created.
#hd
#hd           The edition number is in the form of a three digit extension
#hd           following a period. If other editions of the same file already
#hd           exist, "save" generates the next higher edition by default.
#hd
#hd           The information on the file, including its fullpath, is saved
#hd           into the database at $DATAPATH_DB. This
#hd           allows users running on other file systems to access the file
#hd           simply by using the information established in '$DATAPATH_DB'.
#hd           The database can be queried using the utility `fdb`.

#pr PARAMETERS:
#pr
#pr   POSITIONAL
#pr
#pr     fn     = name of file in directory from which script is invoked
#pr
#pr     pfn    = name of file saved on user's own '$RUNPATH' directory
#pr
#pr   PRIMARY
#pr
#pr     ed     = edition number of offical CCRD/N file
#pr              (default: the latest edition)
#pr
#pr
#pr fil_grpname= User has the option of specifying one of
#pr              'ccrn_shr/ccrn_stf/ccrn_net/ccrn_rcm/ccrn_mam/ccrn_gst'
#pr              group ownership on the saved file.
#pr              (=$DEFFGRP).
#pr

#ex EXAMPLE:
#ex
#ex     save data datfile ed=3
#ex
#ex     The above example moves a file called 'data' into the user's own
#ex     '$RUNPATH' directory with the name 'datfile.003'. If the edition
#ex     number is not specified, the file is saved as the latest edition.
#ex     A symbolic link to 'datfile.003' is made in the directory from which
#ex     save is invoked. The link is named 'data' as a replacement for the
#ex     local version of the file.
#ex

#  * Reset field separators (otherwise those defined in the parent process
#  * will be used and these may cause problems if they include special
#  * characters used in this script).

IFS=' '
export IFS

#  * Capture command line arguments in "arg_list"

arg_list=$@

#  * Obtain the file names and any specified option.

for arg in $arg_list
do
  case $arg in
      -*) set $arg                                         ;;
    ed=*) ed=`expr $arg : 'ed=\([0-9]*\)'`                 ;;
    fil_grpname=*) eval "$arg"                             ;;
       *) tmp1=${fn:+$arg} ; pfn=${pfn:=$tmp1}              ;
          fn=${fn:=$arg}
  esac
done

#  * Set variable 'AWK' to the version of "awk" to be used.

AWK=${AWK:='awk'}

#  * Ensure filenames have been specified.

if [ -z "$fn" -o -z "$pfn" ] ; then
  echo "  Abort in SAVE: must specify both input and output files"
  exit 1
fi

# convert all characters to lower case
pfn=`echo $pfn | tr '[A-Z]' '[a-z]'`

# check for illegal characters in name
case "$pfn" in
  *[!-a-z.0-9_/]*)
      # pfn includes illegal characters
      echo "  Abort in SAVE: File ${pfn} contains illegal characters." ; exit 1 ;;
esac

# replace colons with spaces
DATAPATH_DBs=`echo $DATAPATH_DB | sed 's/:/ /g'`

# use the first database in the list
DATAPATH_DB=`echo $DATAPATH_DBs | cut -f1 -d' '`
export DATAPATH_DB

# create an empty database if it does not exist
if [ ! -s $DATAPATH_DB ] ; then
  fdb empty
fi

#  * Setup for back-end target machine based on $RUNPATH.

#  * Generate the edition number 
if [ -n "$ed" ] ; then 
    # If edition number is supplied, check if file exists 
    # with this edition number and abort if so
    ed=`echo $ed | $AWK '{printf "%03d",$1}'`
    fdb -t exists $pfn $ed
    if [ "$?" -eq 0 ]; then
       # This is always a fatal error
       echo "$error in SAVE: edition number $ed already exists for file $pfn"
       exit 1
    fi
else
   #  * Check if previous editions exist and set the edition number.
   #  * If previous editions do not exist, set the edition number to '1'.
   #  * Otherwise, add one to the highest existing edition number.
   # If the file does not exists in the database then use edition number 000
   ed_from_db=$(fdb version $pfn) || ed_from_db=000

   # Increment the version number by 1
   ed=`echo $ed_from_db | $AWK '{printf "%03d",$1+1}'`
fi

# If running at Dorval site, check for proper file group ownership
# (if specified)...

if [ "$SITE_ID" = 'Dorval' ] ; then
 fil_grpname='ccrn_shr'
else
 unset fil_grpname
fi

# Ensure RUNPATH exists
if [ ! -d "${RUNPATH}/." ] ; then
  echo "$error in SAVE: Invalid subdirectory for RUNPATH --> $RUNPATH <-- !"
  exit 1
fi

#  * Verify that file to be saved exists.
if [ ! -f "$fn" -a ! -d "$fn" ] ; then
  echo "$error in SAVE: file $fn does not exist"
  exit 1
fi

if [ "$ed" -gt 999 ] ; then
  echo "$error in SAVE: trying to save edition $ed (max: 999)"
  exit 1
fi

#  * Move the file into the user's "run" directory defined by the user's
#  * own '$RUNPATH'. Establish a symbolic link in current directory using
#  * the name of the local version of the file. If, however, '$fn' is
#  * already a symbolic link, then copy the file associated with the link.

file=$RUNPATH/$pfn.$ed
if [ -L "$fn" ] ; then
  # fn is a symbolic link. Resolve the link and copy the corresponding file.
  fn_link=`readlink $fn`
  if samefs $fn_link $file ; then
    # if files reside on the same file system, make a hard link
    ln $fn_link $file
  else
    # otherwise, make a copy
    cp -p $fn_link $file
  fi
  if [ "$?" -ne 0 ] ; then
    echo "$error in SAVE: file $fn has not been copied"
    exit 1
  fi
else
  # fn is not a sym link. Move it.
  mv $fn $file
  if [ "$?" -ne 0 ] ; then
    echo "$error in SAVE: file $fn has not been copied"
    exit 1
  fi
  # establish link to the moved file
  ln -s $file $fn
  if [ "$?" -ne 0 ] ; then
    echo "$error in SAVE: link $fn can not be established"
    echo "                to $file file"
    exit 1
  fi
fi

if [ -n "$fil_grpname" ] ; then
  chgrp $fil_grpname $file
fi

#  * The file is saved without write permissions but groupe readable(executable)

chmod a-w,ug+r $file
if [ -x "$file" ] ; then
  chmod ug+x $file
fi

# Make the entry into the database
ntrymax=50 # maximum number of attempts to save file name in the database
ntry=1
while true ; do
  fdb save -a $file && status="$?" || status="$?"
  if [ $status -ne 0 ]; then
    if [ $ntry -gt $ntrymax ] ; then
      echo "  Abort in SAVE: Unable to save $file in database $DATAPATH_DB ntry=$ntry status=$status"
      echo `date -u +'%Y-%m-%d %H:%M:%S'` $USER  "Abort in SAVE: Unable to save $file in database $DATAPATH_DB ntry=$ntry status=$status" >> ${DATAPATH_DB}_failures.txt
      # fdb failed.
      exit  1
    else
      echo "Warning in SAVE: Unable to save $file in database $DATAPATH_DB ntry=$ntry status=$status"
      echo `date -u +'%Y-%m-%d %H:%M:%S'` $USER  "Warning in SAVE: Unable to save $file in database $DATAPATH_DB ntry=$ntry status=$status" >> ${DATAPATH_DB}_failures.txt
      sleep 10
    fi
  else
    break
  fi
  ntry=$((ntry+1))
done

#  * Print out onto standard output the successful completion of the
#  * script.

echo "0** $0 $*"
echo "    File $fn is saved as $file"
echo "0--------  End save  ---------------------------------------------------       0"

exit
