#include #include #include #include #include "cctk.h" #include "cctk_Arguments.h" #include "cctk_Parameters.h" #include "cctk_Termination.h" #include "cctk_Timers.h" #include "ManualTermination.h" enum{ BUFLEN = 128 }; /* On first call, pass parameter terminate_filename. If it is null will construct file name in /tmp based on PBS_JOBID. Subsequent calls ignore the argument, and return a static buffer. */ const char * MT_get_terminate_filename( CCTK_STRING terminate_filename ) { static char buf[BUFLEN]; if( strlen( buf ) != 0 ) return buf; if( strlen( terminate_filename ) == 0 ) { const char * pbs_jobid = getenv("PBS_JOBID"); snprintf( buf, BUFLEN, "/tmp/cactus_terminate.%s", pbs_jobid ); } else { snprintf( buf, BUFLEN, "%s", terminate_filename ); } return buf; } int ManualTermination_StartTimer (CCTK_ARGUMENTS) { DECLARE_CCTK_ARGUMENTS; DECLARE_CCTK_PARAMETERS; int retval = 0; int ierr; int TimerIndex; /* only one processor needs to query the elapsed runtime */ if (CCTK_MyProc (cctkGH) != 0) { return (0); } /* Create timer */ TimerIndex = CCTK_TimerCreate("WatchWalltime"); /* Start timer */ ierr = CCTK_TimerStart("WatchWalltime"); *watchminutes = output_remtime_every_minutes*1.0e0; CCTK_VInfo (CCTK_THORNSTRING, "Started Timer"); CCTK_VInfo (CCTK_THORNSTRING, "Reminding you every %d " "minutes about remaining walltime.", output_remtime_every_minutes); if( termination_from_file ) { FILE *termfile = fopen( MT_get_terminate_filename(termination_file), "w" ); if( termfile != NULL ) { fprintf( termfile, "%d", 0 ); fclose( termfile ); } else { CCTK_VWarn (CCTK_WARN_ABORT, __LINE__, __FILE__, "ManualTermination", "Could not open termination file '%s'. Error: %d", MT_get_terminate_filename(NULL), strerror(errno)); } } return (retval); } int ManualTermination_ResetMinutes (CCTK_ARGUMENTS) { DECLARE_CCTK_ARGUMENTS; DECLARE_CCTK_PARAMETERS; *watchminutes = output_remtime_every_minutes*1.0e0; return 0; } int ManualTermination_CheckWalltime (CCTK_ARGUMENTS) { DECLARE_CCTK_ARGUMENTS; DECLARE_CCTK_PARAMETERS; int retval,ierr; cTimerData *info; const cTimerVal *walltime; CCTK_REAL time; /* only one processor needs to query the elapsed runtime */ if (CCTK_MyProc (cctkGH) != 0) { return (0); } info = CCTK_TimerCreateData(); ierr = CCTK_Timer("WatchWalltime",info); /* stop timer */ ierr = CCTK_TimerStop("WatchWalltime"); /* get walltime */ walltime = CCTK_GetClockValue("gettimeofday",info); time = CCTK_TimerClockSeconds(walltime); CCTK_TimerDestroyData(info); /* Start timer */ ierr = CCTK_TimerStart("WatchWalltime"); if ( (time/60.0e0 > *watchminutes) && *watchminutes != 0) { *watchminutes = (*watchminutes)+output_remtime_every_minutes*1.0e0; CCTK_INFO ("***********************************************************"); CCTK_VInfo (CCTK_THORNSTRING, "Remaining wallclock time for your job " "is %1.2f minutes. :-)", (max_walltime*60.0-time/60.0)); CCTK_INFO ("***********************************************************"); } if (time/60.0e0 >= (max_walltime*60.0e0 - on_remaining_walltime*1.0e0)) { CCTK_VInfo (CCTK_THORNSTRING, "Remaining wallclock time for your job " "is %1.2f minutes. Triggering termination ...", (max_walltime*60.0-time/60.0)); CCTK_TerminateNext (cctkGH); } retval = 0; return (retval); }