*&---------------------------------------------------------------------*
*& Report Z_WAIT_FOR_END_OF_JOBS                                       *
*&---------------------------------------------------------------------*
*& Wait for end of currently running jobs. You can use this program    *
*& in the context of a system refresh in the pre-work. After users have*
*& been locked and kicked out of the system and after job schedulings  *
*& have been suspended (BTCTRNS1 or RLFW_SD_SUSPEND_BATCH_JOBS), there *
*& might be still some jobs running. Wait for the end of these jobs,   *
*& afterwards continue with  pre-work tasks. Use it only after         *
*& execution of BTCTRNS1 resp. RLFW_SD_SUSPEND_BATCH_JOBS.             *
*& For avoiding that long-running jobs cause a delay in the system     *
*& refresh, you can specify that these jobs are to be canceled after   *
*& x seconds waiting for the jobs to be finished.                      *
*& (0 = don't cancel running jobs).                                    *
*&                                                                     *
*& You can add this to the XML file for the pre-work of the system     *
*&   refresh like this:                                                *
*&                                                                     *
*& 1.: In case you already have this program available in the system:  *
*&                                                                     *
*& <Task>                                                              *
*&   <ExecProgram StopOnError="true">                                  *
*&     <Comment>Wait for end of active jobs</Comment>                  *
*&     <ABAPProgram>Z_WAIT_FOR_END_OF_JOBS</ABAPProgram>               *
*&   </ExecProgram>                                                    *
*& </Task>                                                             *
*&                                                                     *
*& or, when using a variant (e.g. for cancelling jobs after 5 minutes  *
*&   wait time)                                                        *
*&                                                                     *
*& <Task>                                                              *
*&   <ExecProgram StopOnError="true">                                  *
*&     <Comment>Wait for end of active jobs</Comment>                  *
*&     <ABAPProgram>Z_WAIT_FOR_END_OF_JOBS</ABAPProgram>               *
*&     <ABAPVariant>CancAfter5Min</ABAPVariant>                        *
*&   </ExecProgram>                                                    *
*& </Task>                                                             *
*&                                                                     *
*& 2.: In case you don't have (replace C:\... with the right path to   *
*&       this file):                                                   *
*&                                                                     *
*& <Task>                                                              *
*&   <InsertProgram StopOnError="true">                                *
*&     <Comment>Wait for end of active jobs</Comment>                  *
*&     <ABAPProgram>Z_WAIT_FOR_END_OF_JOBS</ABAPProgram>               *
*&     <ProgramTitle>Wait for end of active jobs</ProgramTitle>        *
*&     <SourceFile>C:\...\WaitForEndOfActiveJobs.txt</SourceFile>      *
*&     <Overwrite>true</Overwrite>                                     *
*&     <Execute>true</Execute>                                         *
*&   </InsertProgram>                                                  *
*& </Task>                                                             *
*&                                                                     *
*&---------------------------------------------------------------------*
REPORT Z_WAIT_FOR_END_OF_JOBS.
" When entering a value for cancSec, active jobs will be canceled in
"   case they are still active after <cancSec> seconds.
selection-screen begin of line.
  selection-screen comment (60) txt_c for field cancSec.
  parameters: cancSec type i.
selection-screen end of line.
types: begin of JobIdentifier,
         jobcount type btcjobcnt,
         jobname type btcjob,
       end of JobIdentifier.
data: startTime type uzeit.
" Different job status (source: BTCTRNS1)
CONSTANTS:
  btc_running       TYPE tbtco-status VALUE 'R',
  btc_ready         TYPE tbtco-status VALUE 'Y',
  btc_scheduled     TYPE tbtco-status VALUE 'P',
  btc_intercepted   TYPE btcstatus VALUE btc_scheduled,
  btc_released      TYPE tbtco-status VALUE 'S',
  btc_aborted       TYPE tbtco-status VALUE 'A',
  btc_finished      TYPE tbtco-status VALUE 'F',
  btc_put_active    TYPE tbtco-status VALUE 'Z',
  btc_unknown_state TYPE tbtco-status VALUE 'X'.

initialization.
  txt_c = 'Cancel active jobs after x seconds from start'.

start-of-selection.
  write:/ 'Checking active jobs and wait until their end...'.
  startTime = sy-uzeit.
  do.
    " Cancel active jobs after x seconds since program start?
    if cancSec > 0.
      if ( sy-uzeit - startTime > cancSec ).
        perform cancelActiveJobs.
        wait up to 1 seconds.
      endif.
    endif.
    " Are there active or ready jobs?
    select count( * ) from TBTCO where status = @btc_running
                                    or status = @btc_ready. 
    if sy-dbcnt = 0.
      write:/ sy-uzeit, ': No active / ready jobs found.'.
      exit.
    else.
      write:/ sy-uzeit, ':', sy-dbcnt, 'active / ready jobs found.'.
      wait up to 5 seconds.
    endif.
  enddo.

form cancelActiveJobs.
  data: jobs2BeCanceled type standard table of JobIdentifier
            with empty key,
        cancelSubrc like sy-subrc.
  select jobcount, jobname into table @jobs2BeCanceled
      from TBTCO where status = @btc_running
                    or status = @btc_ready.
  loop at jobs2BeCanceled reference into data(j).
    call function 'BP_JOB_ABORT'
      EXPORTING
        JOBCOUNT                   = j->jobcount
        JOBNAME                    = j->jobname
      EXCEPTIONS
        CHECKING_OF_JOB_HAS_FAILED = 1  " Check of job failed
        JOB_ABORT_HAS_FAILED       = 2  " Cancellation failed
        JOB_DOES_NOT_EXIST         = 3  " Job does not exist
        JOB_IS_NOT_ACTIVE          = 4  " Job is not active
        NO_ABORT_PRIVILEGE_GIVEN   = 5  " no authorization
        OTHERS                     = 6.
    cancelSubrc = sy-subrc.
    if cancelSubrc = 0.
      write:/ 'Job', j->jobname, '(', j->jobcount, ') canceled.'.
    else.
      write:/ 'Job', j->jobname, '(', j->jobcount, ')',
              'could not be canceled.'.
      case cancelSubrc.
        when 1. write:/ ' -> CHECKING_OF_JOB_HAS_FAILED'.
        when 2. write:/ ' -> JOB_ABORT_HAS_FAILED'.
        when 3. write:/ ' -> JOB_DOES_NOT_EXIST'.
        when 4. write:/ ' -> JOB_IS_NOT_ACTIVE.'.
        when 5. write:/ ' -> NO_ABORT_PRIVILEGE_GIVEN'.
        when 6. write:/ ' -> OTHER reason'.
      endcase.
    endif.
  endloop.
endform.