#!/bin/bash

#
# Script
#
# g4cParallelJobsExecution.sh
#
#    lancia l'esecuzione parallela dei job che realizzano la
#    simulazione
#

#
# Parametri
#
# <verbose>
#   i valori ammessi per il parametro sono 0 o 1.
#   Se 1 attiva la modalita' verbose di esecuzione dello script
# <macroFileAbsolutePath>
#   path assoluto del file di macro a partire dal quale vengono generati
#   quelli per le simulazioni eseguite dai singoli job
# <workingDirectoryRelativePath>
#   path relativo alla directory g4cParallelSimulation di quella
#   di lavoro che contiene le subdirectory assegnate ai job che
#   realizzano la simulazione, il file con le informazioni relative
#   ai loro istanti di sottomissione e di completamento e il file di
#   output per la modalita' verbose
# <simulationExecutableAbsolutePath>
#   path assoluto dell'eseguibile da assegnare ad ogni job
#   della simulazione parallela
# <jobsTimeOut>
#   numero di secondi dall'inizio della sua esecuzione trascorso il quale un job
#   viene interrotto. Se 0 inibisce il time out
# <parallelJobsPerHost>
#   numero dei job eseguiti in parallelo su ognuno degli host impegnati nella
#   simulazione. Non deve essere maggiore del minimo numero di core riservati
#   alla simulazione su ogni host 
# <hostsList>
#   elenco dei nomi degli host impegnati nella simulazione, separati da
#   virgola e senza blank
# <jobRuntimeFileName>
#   nome del file, nella directory assegnata ad ogni job, nel
#   quale vengono memorizzati i suoi istanti di sottomissione e di
#   completamento
# <geant4EnvVariablesSetUp>
#   path assoluto dello script che setta le variabili di ambiente
#   di Geant4 per l'esecuzione del job
# <tspQueuesPositioning>
#   variabile simbolica che, definendo il posizionamento del file
#   di informazioni per la coda di task gestita da tsp 
#   (task spooler), ne permette l'accesso all'host che la
#   utilizza per gestire l'esecuzione parallela dei job.
#   Al file in questione, memorizzato su ogni host nella directory
#   "\tmp", è assegnato il nome della working directory seguito
#   dal suffisso ".tmp"
# <helpRelativePath>
#   path relativo alla directory g4cParallelSimulation
#   di quella che contiene i messaggi di aiuto alla
#   interazione con la simulazione
# <verbRelativePath>
#   path relativo alla directory g4cParallelSimulation 
#   di quella che contiene gli script di gestione 
#   della modalita'  verbose
# <verbOutputFileRelativePath>
#   path relativo alla directory g4cParallelSimulation del file
#   di output per la modalita' verbose 
#

# Estrae i parametri dello script dalla sua chiamata
verbose=$1
macroFileAbsolutePath=$2
workingDirectoryRelativePath=$3
simulationExecutableAbsolutePath=$4
jobsTimeOut=$5
parallelJobsPerHost=$6
hostsList=$7
jobRuntimeFileName=$8
geant4EnvVariablesSetUp=$9
tspQueuesPositioning=${10}
helpRelativePath=${11}
verbRelativePath=${12}
verbOutputFileRelativePath=${13}

# Accede al nome dello script correntemente in esecuzione
currentScript=$(basename $0)

# Verbose
#   Memorizza nel file di output per la modalita' verbose, se attiva, 
#   l'inizio della esecuzione dello script
$verbRelativePath/verbScriptStarting.sh $verbose \
                                        $currentScript \
                                        $verbOutputFileRelativePath

# Verbose									
#   Memorizza nel file di output per la modalita' verbose, se attiva,
#   il valore dei parametri specificati per l'esecuzione parallela dei
#   job che realizzano la simulazione
$verbRelativePath/verbParallelJobsExecutionParam.sh $verbose \
                                              $currentScript \
                                              $macroFileAbsolutePath \
                                              $workingDirectoryRelativePath \
                                              $simulationExecutableAbsolutePath \
                                              $jobsTimeOut \
                                              $parallelJobsPerHost \
                                              $hostsList \
											  $jobRuntimeFileName \
                                              $geant4EnvVariablesSetUp \
                                              $tspQueuesPositioning \
                                              $verbOutputFileRelativePath


# Inizializza la variabile utilizzata per l'acceso
# alle code di task, gestite da tsp, assegnate agli
# host
TSP=$tspQueuesPositioning

# Estrae il nome del file di macro dal suo path assoluto
macroFileName=$(basename $macroFileAbsolutePath)

# Salva la lista iniziale degli hosts 
tempHostsList=$hostsList

# Inizializza l'host corrente in modo funzionale alla
# scansione della lista degli host
currentHost=""

# Scansiona la lista degli host
while test "$currentHost" != "$hostsList"
do 
   # Estrae il primo host della lista
   currentHost=$(echo $hostsList | cut -f1 -d,)
   
   # Se non e' anche l'ultimo, lo rimuove dalla lista 
   hostsList=$(echo $hostsList | cut -f2- -d,)
   
   # Verbose
   #   Memorizza nel file di output per la modalita' verbose, se attiva,  
   #   l'avvenuta associazione della coda all'host
   $verbRelativePath/verbStpQueueToHostAssociation.sh \
                                                 $verbose \
                                                 $currentScript \
                                                 $workingDirectoryRelativePath \
                                                 $currentHost \
                                                 $verbOutputFileRelativePath
                                                  
   # Effettua una connessione ssh all'host corrente e inizializza
   # la coda a questo assegnata
   ssh $USER@$currentHost "
                                   # dimensiona la coda assegnata all'host
                                   # corrente al numero di job eseguiti in 
								   # parallelo su ognuno degli host impegnati
								   # nella simulazione.
                                   $TSP tsp -S $parallelJobsPerHost
                                   
                                   # svuota la coda assegnata all'host
								   # corrente
                                   $TSP tsp -C

                                   # Debug - Visualizza il contenuto della
                                   # coda assegnata all'host corrente  
                                   # $TSP tsp                                   
                                   "
done

# Ripristina la lista iniziale degli host
hostsList=$tempHostsList

# Estrae l'elenco dei nomi delle directory assegnate
# ai singoli job all'interno della working directory
directorySet=$(ls -1 $workingDirectoryRelativePath | grep $(basename $workingDirectoryRelativePath))

# Per tutti i job: inserisce il job i-esimo 
# nella coda dell'host (i mod numero degli host 
# nella lista degli host impegnati nella simulazione)+1.
# Ogni job è identificato dal nome directory assegnatale
for currentJob in $directorySet
do
   # Rallenta la sequenza di connessioni ssh, per evitare
   # che il server ne rifiuti qualcuna
   sleep 1
   
   # Il primo host della lista diventa l'host corrente
   currentHost=$(echo $hostsList | cut -f1 -d,)

   # Vsualizza l'assegnazione del job corrente
   # all'host corrente
   $helpRelativePath/helpJobsToHostsAssignment.sh $verbose \
                                                  $currentScript \
                                                  $currentJob \
                                                  $currentHost \
                                                  $verbOutputFileRelativePath
   
   # Verbose
   #   Memorizza nel file di output per la modalita' verbose, se attiva, 
   #   l'assegnazione del job corrente all'host corrente
   $verbRelativePath/verbJobsToHostsAssignment.sh $verbose \
                                                  $currentScript \
                                                  $currentJob \
                                                  $currentHost \
                                                  $verbOutputFileRelativePath

   # memorizza la directory che contiene quella di lavoro
   currentDirectory=$(pwd)
   
   # Apre, in background, una connessione verso l'host corrente (incaricato
   # della esecuzione del job corrente)
   ssh $USER@$currentHost \
       "
	   # l'host corrente
	   
       # nel file system condiviso l'host si posiziona nella
       # directory che contiene quella di lavoro
       cd $currentDirectory
       
       # Scrive l'identificativo del job corrente nel file
	   # destinato a contenere i dati relativi ai suoi
	   # istanti di sottomissione e di completamento
       echo "job-$(echo $currentJob|cut -f2 -d\-)" >> \
	      $workingDirectoryRelativePath/$currentJob/$jobRuntimeFileName

       # Setta opportunamente le variabili di ambiente di Geant4
       source $geant4EnvVariablesSetUp

       # Scrive l'istante di sottomissione del job corrente, nei
	   # due formati day month hour:min:sec UTC year e tempo di
	   # internet, nel file destinato a memorizzarlo
       date >> \
          $workingDirectoryRelativePath/$currentJob/$jobRuntimeFileName
       date +%s >> \
          $workingDirectoryRelativePath/$currentJob/$jobRuntimeFileName
       
       # Aggiunge il job corrente alla coda assegnata all'host
	   # corrente, fissandone il timeout 
       $TSP tsp -f -N 1 timeout \
	             $jobsTimeOut"s" \
	             $simulationExecutableAbsolutePath \
                 $workingDirectoryRelativePath/$currentJob/$macroFileName

       # Scrive l'istante di completamento del job corrente,
	   # nei due formati day month hour:min:sec UTC year e tempo di
	   # internet, nel file destinato a memorizzarlo
       date >> \
          $workingDirectoryRelativePath/$currentJob/$jobRuntimeFileName
       date +%s >> \
          $workingDirectoryRelativePath/$currentJob/$jobRuntimeFileName
       " &
	   
   # Sposta il primo host della lista in coda alla lista stessa
   hostsList=$(echo $hostsList | cut -f2- -d,)","$currentHost
done

# Attende il completamento di tutti i job in coda
wait

# Ripristina la lista iniziale degli host
hostsList=$tempHostsList

# Verbose
#    Memorizza nel file di output per la modalità verbose, se attiva
#    il contenuto della coda associata ad ogni host
#
$verbRelativePath/verbHostStpQueueContent.sh $verbose \
                                             $currentScript \
                                             $hostsList \
                                             $TSP \
                                             $verbOutputFileRelativePath
   
#  Verbose
#    Memorizza nel file di output per la modalità verbose, se attiva, 
#    l'uscita dallo script
$verbRelativePath/verbScriptCompletion.sh $verbose \
                                          $currentScript \
                                          $verbOutputFileRelativePath
										  
exit 0
