#!/bin/bash 
# COPYIN - copy the indicated files from the indicated node and directory
#  to the current directory.  This is a utility script for the
#  data assimilation implementation on Beowulf clusters.
#
# SYNOPSIS
#   copyin [options] files
#
# OPTIONS
#   -w dir  : Copy files from node to dir 
#   -N node : Remote machine to copy from (default: current node)
#   -r      :  If remote copies are successful, remove files on the source node.
#   -v      :  print the current version date and exit.
#
# DESCRIPTION
#  Copyin copies files from the indicated directory on the node named by -N.
#  If the remote node is the same as the current node, then copyin does
#  an ordinary copy (with cp), provided that the source directory differs
#  from the current one.  Files should be absolute pathnames.
#
# NOTES
#  The command-line arguments to this script are a subset of those to
#  the component programs of the data assimilation software.
#
# REVISION HISTORY
#  11/29/04 : bug fixes.
#  09/10/04 : allowed the destination and source nodes to be the same.
#  10/03/03 : previous production version.
#
# EXAMPLES
#  1. When -N is not specified, the node is the local node, and
#  copyin -d dir files is equivalent to cp files dir.
#
#  2. copyin -N node4 -d /final/dir /scratch/abc /home/def
#  copies node4:/scratch/abc to /fina/dir/abc on the local node
#  and node4:/home/def to /final/dir/def on the local node.
#
#------------------------------------------------------------------------
#set -x
function usage {
    echo "Usage: $0 [options] files"
    echo "Version: $version"
    echo "Options:"
    echo "-h (to print this message)"
    echo "-N node_name (current: $NODE)"
    echo "-d destination directory on local node; default: current dir"
    echo "   The argument to -d should be an absolute pathname."
    echo "-r (remove files on remote node upon successful copying)"
    echo " files should be absolute pathnames on node_name."
    exit 1
}
#------------------------------------------------------------------------
function copy_from_node {
# Copy the files in the argument list from a remote node.
# Check that everything arrived OK; if contents are garbled during
# transmission, then retry once.
#
   errcode=0
   for srcfile in $*
   do
      base=$(basename $srcfile)
      local=$DESTDIR/$base
      rcp ${SRCNODE}:$srcfile $local
      rcpret=$?
      if [ $rcpret -eq 0 ]
      then
         local localsum=$(cksum $local | cut -d ' ' -f 1-2)
         local srcheck=$(rsh $SRCNODE cksum $srcfile | cut -d ' ' -f 1-2)
         if [ "$localsum" != "$srcheck" ]   # try again
         then
	 rcp ${SRCNODE}:$srcfile $local
	 srcheck=$(rsh $SRCNODE cksum $srcfile | cut -d ' ' -f 1-2)
	 if [ "$localsum" != "$srcheck" ]   # give up
	 then
	    echo $0: "error copying $srcfile from $SRCNODE" 1>&2
	    echo $0: "copied checksum: $localsum" 1>&2
	    echo $0: "original checksum: $srcheck" 1>&2
	    errcode=1
	 fi
         fi
      else
         return $rcpret
      fi
      if [ $remove -eq 1 -a $rcpret -eq 0 ]
      then
         rsh $SRCNODE rm -f $srcfile
      fi
   done
   return $errcode
}
#------------------------------------------------------------------------
function copy_locally {
   errcode=0
   if ! cp $* $DESTDIR
   then
      errcode=1
   elif [ $remove -ne 0 ]
   then
      rm -f $*
   fi
   return $errcode
}
#------------------------------------------------------------------------
#  Set defaults

version="11/29/04"
host=$(hostname -a)  # current node
SRCNODE=$host  # default
DESTDIR=.  # current directory is default
remove=0    # don't delete source files when copying is complete

#  Parse the command line
while getopts hN:d:r opt
do
    case $opt in
    h)  usage;;
    N)  SRCNODE=$OPTARG;;
    r)  remove=1;;
    d)  DESTDIR=$OPTARG;;
    v)  echo $0: version: $version; exit 0 ;;
    \?) usage ;;
    esac
done

#  Get rid of the options after parsing
shift $(expr $OPTIND - 1)

if [ $SRCNODE != $host ]
then
   copy_from_node $*
   ek=$?
   if [ $ek -ne 0 ]
   then
      exit $ek
   fi
else
   if ! copy_locally $*
   then
      exit 1
   fi
   if [ $remove -ne 0 ]
   then
      rm -f $*
   fi
fi
exit $errcode
