?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE job management queued file job internal interfaces' ??
MODULE qfm$queue_file_job_manager;

{ PURPOSE:
{   This module contains the Queue File Management system core interfaces for managing files in the
{ input queue and the Known Job List (KJL).
{
{ DESIGN:
{   These procedures execute in ring one and can be called from ring 3.  These procedures access
{ the ring one table the Known Job List (KJL).  It is contained in mainframe pageable.  A signature
{ lock is used in order to ensure synchronous access to the KJL.

?? NEWTITLE := 'Global Declarations Referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dft$rpc_parameters
*copyc dme$tape_errors
*copyc jmc$class_names
*copyc jmc$input_queue_full_message
*copyc jmc$job_management_id
*copyc jmc$kjl_maximum_entries
*copyc jmc$maximum_job_count
*copyc jmc$status_message_text
*copyc jme$queued_file_conditions
*copyc jmt$clock_time
*copyc jmt$default_job_attributes
*copyc jmt$initiated_job_list_entry
*copyc jmt$input_application_index
*copyc jmt$input_descriptor
*copyc jmt$input_file_location
*copyc jmt$job_attributes
*copyc jmt$job_class_limits
*copyc jmt$job_class_set
*copyc jmt$job_control_block
*copyc jmt$job_counts
*copyc jmt$job_internal_information
*copyc jmt$job_mode_set
*copyc jmt$job_recovery_information
*copyc jmt$job_state
*copyc jmt$job_state_set
*copyc jmt$job_status_count
*copyc jmt$job_status_options
*copyc jmt$job_status_results
*copyc jmt$job_system_label
*copyc jmt$kjl_application_state_set
*copyc jmt$kjl_client_index
*copyc jmt$kjl_entry_kind
*copyc jmt$kjl_entry_kind_set
*copyc jmt$kjl_index
*copyc jmt$kjl_server_index
*copyc jmt$known_job_list
*copyc jmt$known_job_list_entry
*copyc jmt$known_job_list_extended
*copyc jmt$name
*copyc jmt$queue_file_password
*copyc jmt$release_input_file_list
*copyc jmt$results_keys
*copyc jmt$system_job_parameters
*copyc jmt$system_supplied_name
*copyc jmt$terminate_job_action
*copyc jmt$valid_mainframe_set
*copyc jmt$work_area
*copyc osc$timesharing
*copyc osd$integer_limits
*copyc oss$mainframe_pageable
*copyc oss$mainframe_paged_literal
*copyc ost$byte
*copyc ost$halfword
*copyc ost$signature_lock
*copyc ost$status
*copyc ost$user_identification
?? POP ??
*copyc dpp$put_critical_message
*copyc iop$job_tape_mounts_active
*copyc jmp$determine_job_class_name
*copyc jmp$force_candidate_refresh
*copyc jmp$get_ijle_p
*copyc jmp$notify_job_scheduler_of_job
*copyc jmp$set_event_and_ready_sched
*copyc ofp$job_operator_menus_active
*copyc ofp$job_operator_msgs_active
*copyc osp$clear_mainframe_sig_lock
*copyc osp$monitor_fault_to_status
*copyc osp$set_mainframe_sig_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$test_sig_lock
*copyc pmp$convert_binary_mainframe_id
*copyc pmp$convert_mainframe_to_binary
*copyc pmp$delay
*copyc pmp$get_executing_task_gtid
*copyc pmp$get_mainframe_id
*copyc pmp$ready_task
*copyc pmp$set_system_flag
*copyc pmp$zero_out_table
*copyc qfp$check_for_profile_mismatch
*copyc syp$continue_to_cause
*copyc syp$disestablish_cond_handler
*copyc syp$establish_condition_handler
*copyc jmv$ijl_p
*copyc jmv$jcb
*copyc jmv$job_class_table_p
*copyc jmv$job_counts
*copyc jmv$job_scheduler_table
*copyc jmv$maximum_job_class_in_use
*copyc jmv$null_date_time
*copyc jmv$refresh_job_candidates
*copyc jmv$sched_profile_is_loading
*copyc jmv$system_job_ssn
*copyc osv$mainframe_pageable_heap
?? TITLE := 'Global Variables Declared in this Module', EJECT ??

  CONST
    max_job_tape_mount_attempts = 30,
    one_second = 1000 {milliseconds},
    system_job_kjl_index = 1;

  VAR
    jmv$input_file_recovery_option: [XDCL, #GATE, oss$mainframe_pageable] ost$byte := 0,
    jmv$job_counts_lock: [XDCL, #GATE, oss$mainframe_pageable] ost$signature_lock,
    jmv$job_history_active: [XDCL, #GATE, oss$mainframe_pageable] boolean := FALSE,
    jmv$known_job_list: [XDCL, #GATE, oss$mainframe_pageable] jmt$known_job_list,
    jmv$kjl_p: [XDCL, #GATE, oss$mainframe_pageable] ^array [1 .. * ] of jmt$known_job_list_entry := NIL,
    jmv$kjlx_p: [XDCL, #GATE, oss$mainframe_pageable] ^array [1 .. * ] of jmt$known_job_list_extended := NIL,
    jmv$maximum_known_jobs: [XDCL, #GATE, oss$mainframe_pageable] ost$halfword := 250,
    jmv$time_to_ready_deferred_job: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    qfv$kjl_lock: [XDCL, oss$mainframe_pageable] ost$signature_lock,
    qfv$current_kjl_limit: [XDCL, #GATE, oss$mainframe_pageable] jmt$kjl_index := 0,
    qfv$terminate_job_action_set: [XDCL, #GATE, oss$mainframe_pageable] jmt$terminate_job_action_set :=
          $jmt$terminate_job_action_set [jmc$tja_kill_disabled],
    null_binary_mainframe_id: [STATIC, READ, oss$mainframe_paged_literal] pmt$binary_mainframe_id := [0, 0],
    jmv$default_job_attributes: [XDCL, #GATE, oss$mainframe_pageable] jmt$default_job_attributes;

?? TITLE := 'convert_state_to_entry_kind', EJECT ??

{ PURPOSE:
{   The purpose of this request is to convert a job state to its Known Job List entry-kind
{ equivalent.

  PROCEDURE convert_state_to_entry_kind
    (    job_state: jmt$job_state;
     VAR kjl_entry_kind: jmt$kjl_entry_kind;
     VAR status: ost$status);

    CASE job_state OF
    = jmc$deferred_job =
      kjl_entry_kind := jmc$kjl_deferred_entry;

    = jmc$queued_job =
      kjl_entry_kind := jmc$kjl_queued_entry;

    = jmc$initiated_job =
      kjl_entry_kind := jmc$kjl_initiated_entry;

    = jmc$terminating_job =
      kjl_entry_kind := jmc$kjl_terminated_entry;

    = jmc$completed_job =
      kjl_entry_kind := jmc$kjl_completed_entry;

    ELSE
      osp$set_status_abnormal (jmc$job_management_id, jme$invalid_job_state, '', status);
    CASEND;
  PROCEND convert_state_to_entry_kind;
?? OLDTITLE ??
?? NEWTITLE := 'find_client_mainframe_id', EJECT ??

{ PURPOSE:
{   This request searches the Known Job List Client Table for the specified mainframe
{   identifier and adds it if it does not exist.
{
{ DESIGN:
{   If the mainframe identifier is found return the kjl client index.  If the mainframe
{   identifier is not found then assign a new kjl client index.  If the kjl client list
{   is full set the client_mainframe_id_in_kjl to FALSE.
{
{ NOTES:
{   The Known Job List (KJL) must be locked when this request is issued.

  PROCEDURE find_client_mainframe_id
    (    client_mainframe_id: pmt$binary_mainframe_id;
     VAR client_mainframe_id_in_kjl: boolean;
     VAR kjl_client_index: jmt$kjl_client_index);

    VAR
      local_kjl_client_index: jmt$kjl_client_index;

    client_mainframe_id_in_kjl := FALSE;

  /search_for_mainframe_id/
    FOR local_kjl_client_index := jmc$kjl_client_this_mainframe TO UPPERVALUE (jmt$kjl_client_index) DO
      IF jmv$known_job_list.client_data.state_data [local_kjl_client_index].mainframe_id =
            client_mainframe_id THEN
        client_mainframe_id_in_kjl := TRUE;
        kjl_client_index := local_kjl_client_index;
        EXIT /search_for_mainframe_id/;
      IFEND;
    FOREND /search_for_mainframe_id/;
    IF (NOT client_mainframe_id_in_kjl) THEN

    /search_for_empty_client_entry/
      FOR local_kjl_client_index := jmc$kjl_client_this_mainframe + 1 TO UPPERVALUE (jmt$kjl_client_index) DO
        IF jmv$known_job_list.client_data.state_data [local_kjl_client_index].mainframe_id =
              null_binary_mainframe_id THEN
          jmv$known_job_list.client_data.state_data [local_kjl_client_index].mainframe_id :=
                client_mainframe_id;
          client_mainframe_id_in_kjl := TRUE;
          kjl_client_index := local_kjl_client_index;
          EXIT /search_for_empty_client_entry/;
        IFEND;
      FOREND /search_for_empty_client_entry/;
    IFEND;
  PROCEND find_client_mainframe_id;
?? OLDTITLE ??
?? NEWTITLE := 'find_destination_usage', EJECT ??

{ PURPOSE:
{   The purpose of this request is to find the specified destination_usage in the application table
{ and return with the application index.  If there is no application registered for the destination_usage
{ specified the value jmc$unassigned_input_index is returned.
{
{ DESIGN:
{   Starting with the index of the last application, search backwards through the chain until
{ the destination_usage is found or there are no more applications to search.
{
{ NOTES:
{   The Known Job List (KJL) MUST be locked when this request is made.

  PROCEDURE find_destination_usage
    (    destination_usage: jmt$destination_usage;
     VAR application_index: jmt$input_application_index);

    IF (destination_usage = jmc$ve_usage) OR (destination_usage = jmc$ve_local_usage) THEN
      application_index := jmc$ve_input_application_index;
    ELSE

      application_index := UPPERBOUND (jmv$known_job_list.application_table);

      WHILE (jmv$known_job_list.application_table [application_index].destination_usage <>
            destination_usage) AND (application_index <> jmc$unassigned_input_index) DO
        application_index := application_index - 1;
      WHILEND;
    IFEND;
  PROCEND find_destination_usage;
?? TITLE := 'find_job_by_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to find a job assigned to a particular application by using its
{ system_job_name.
{
{ DESIGN:
{   Search the Known Job List (KJL) for the job that has been assigned to the application specified.
{ If the entry in the KJL is not found, return a kjl_index of jmc$kjl_undefined_index.
{
{ NOTES:
{   The KJL must be locked when this request is issued.

  PROCEDURE find_job_by_application
    (    system_job_name: jmt$system_supplied_name;
         application_index: jmt$input_application_index;
     VAR kjl_index: jmt$kjl_index);

    VAR
      application_state: jmt$kjl_application_state;

  /search_for_the_specified_file/
    FOR application_state := SUCC (jmc$kjl_application_unused) TO UPPERVALUE (application_state) DO
      kjl_index := jmv$known_job_list.application_table [application_index].state_data [application_state].
            first_entry;
      WHILE kjl_index <> jmc$kjl_undefined_index DO
        IF jmv$kjl_p^ [kjl_index].system_job_name = system_job_name THEN
          EXIT /search_for_the_specified_file/;
        ELSE
          kjl_index := jmv$kjl_p^ [kjl_index].application_forward_link;
        IFEND;
      WHILEND;
    FOREND /search_for_the_specified_file/;
  PROCEND find_job_by_application;
?? OLDTITLE ??
?? NEWTITLE := 'find_server_mainframe_id', EJECT ??

{ PURPOSE:
{   This request searches the Known Job List Server Table for the specified mainframe
{   identifier and adds it if it does not exist.
{
{ DESIGN:
{   If the mainframe identifier is found return the kjl server index.  If the mainframe
{   identifier is not found then assign a new kjl server index.
{
{ NOTES:
{   The Known Job List (KJL) must be locked when this request is issued.

  PROCEDURE find_server_mainframe_id
    (    server_mainframe_id: pmt$binary_mainframe_id;
     VAR kjl_server_index: jmt$kjl_server_index);

    VAR
      first_available_server_index: jmt$kjl_server_index,
      local_kjl_server_index: jmt$kjl_server_index;

    first_available_server_index := jmc$kjl_server_this_mainframe;

  /search_for_mainframe_id/
    FOR local_kjl_server_index := jmc$kjl_server_this_mainframe TO UPPERVALUE (jmt$kjl_server_index) DO
      IF jmv$known_job_list.server_data.state_data [local_kjl_server_index].mainframe_id =
            server_mainframe_id THEN
        kjl_server_index := local_kjl_server_index;
        RETURN;
      ELSEIF (jmv$known_job_list.server_data.state_data [local_kjl_server_index].mainframe_id =
            null_binary_mainframe_id) AND (first_available_server_index = jmc$kjl_server_this_mainframe) THEN
        first_available_server_index := local_kjl_server_index;
      IFEND;
    FOREND /search_for_mainframe_id/;
    jmv$known_job_list.server_data.state_data [first_available_server_index].mainframe_id :=
          server_mainframe_id;
    kjl_server_index := first_available_server_index;
  PROCEND find_server_mainframe_id;
?? OLDTITLE ??
?? NEWTITLE := 'get_job_from_scheduler', EJECT ??

{ PURPOSE:
{   The purpose of this request is to force the job scheduler to un-acquire a job that has been acquired.
{
{ DESIGN:
{   Relink the KJL entry supplied to the application state supplied on the request.  Notify the
{ Scheduler that it needs to refresh the candidate queue.  Once the scheduler has run, it will return the
{ the job to the NEW application state.  This will permit the KJL to be locked and the entry should no
{ longer be acquired.
{
{ NOTES:
{   The KJL MUST be locked on entry to this request.  In addition, this request will always exit with the
{ KJL locked.

  PROCEDURE get_job_from_scheduler
    (    kjl_index: jmt$kjl_index;
         destination_application_state: jmt$kjl_application_state;
     VAR job_name_has_changed: boolean);

    TYPE
      kjl_application_state_set = set of jmt$kjl_application_state;

    VAR
      application_state_wait_set: kjl_application_state_set,
      ignore_status: ost$status,
      system_job_name: jmt$system_supplied_name;

    application_state_wait_set := $kjl_application_state_set
          [jmc$kjl_application_acquired, jmc$kjl_application_modified, jmc$kjl_application_terminated];
    system_job_name := jmv$kjl_p^ [kjl_index].system_job_name;

{*** Temporary test code...  If it works, keep it.

    IF ve_job (kjl_index) AND (jmv$kjl_p^ [kjl_index].application_state IN application_state_wait_set) AND
          (jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_queued_entry) THEN
      jmp$force_candidate_refresh ({ flush_candidate_queue } TRUE);
    IFEND;
    job_name_has_changed := jmv$kjl_p^ [kjl_index].system_job_name <> system_job_name;
    RETURN;

{ If the job scheduler has the job we must wait for it to give it up.  For all other applications,
{ nothing is done.

    WHILE ve_job (kjl_index) AND (jmv$kjl_p^ [kjl_index].application_state IN application_state_wait_set) AND
          (jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_queued_entry) DO
      qfp$relink_kjl_application (kjl_index, jmc$ve_input_application_index, destination_application_state);
      jmv$refresh_job_candidates := TRUE;
      notify_input_application (jmc$ve_input_application_index, kjl_index);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);

{ Because the job scheduler is attempting to initiate the job we must wait for it to return control.
{ The job scheduler will run when it can and recognize that it has work to do.

      WHILE (jmv$kjl_p^ [kjl_index].application_state = destination_application_state) AND
            (jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_queued_entry) DO
        pmp$delay (100, ignore_status);
      WHILEND;
      osp$set_mainframe_sig_lock (qfv$kjl_lock);

    WHILEND;

{ Make sure that the job did not disappear since the KJL was unlocked.  If it did, present the caller with
{ an error to say that the job is gone.

    job_name_has_changed := jmv$kjl_p^ [kjl_index].system_job_name <> system_job_name;
  PROCEND get_job_from_scheduler;
?? OLDTITLE ??
?? NEWTITLE := 'notify_input_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to ready an input application's control task.
{
{ NOTES:
{   The Known Job List (KJL) should be locked when this request is issued in order to ensure that
{ the global_task_id in the KJL's application table is valid.  If it isn't, the result will be to
{ cause a task to become ready before its scheduled time.  This is not generally a problem.
{ With this in mind, it is okay to make this request without the KJL locked, but it is preferred to
{ have the structure locked.

  PROCEDURE notify_input_application
    (    application_index: jmt$input_application_index;
         kjl_index: jmt$kjl_index);

    VAR
      ignore_status: ost$status;

    IF application_index <> jmc$unassigned_input_index THEN
      IF application_index = jmc$ve_input_application_index THEN
        jmp$notify_job_scheduler_of_job (jmv$kjl_p^ [kjl_index].job_class, kjl_index);
      ELSE
        pmp$ready_task (jmv$known_job_list.application_table [application_index].global_task_id,
              ignore_status);
      IFEND;
    IFEND;
  PROCEND notify_input_application;
?? OLDTITLE ??
?? NEWTITLE := '[INLINE] ve_job', EJECT ??

{ PURPOSE:
{   This function indicates if the job is a NOS/VE job rather than a job destined for a remote system.

  FUNCTION [INLINE] ve_job
    (    kjl_index: jmt$kjl_index): boolean;

    ve_job := jmv$kjlx_p^ [kjl_index].input_file_location <> jmc$ifl_store_and_forward_queue;
  FUNCEND ve_job;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$activate_deferred_family', EJECT ??
*copy qfh$activate_deferred_family

{ NOTE:
{   This request is only meaningful for NOS/VE jobs that are destined for the job scheduler.

  PROCEDURE [XDCL, #GATE] qfp$activate_deferred_family
    (    family_name: ost$name);

    VAR
      current_clock_time: jmt$clock_time,
      deferred_job: boolean,
      kjl_index: jmt$kjl_index,
      next_kjl_index: jmt$kjl_index;

    current_clock_time := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

{ Scan the deferred thread for jobs that are deferred because their login family is not available.
{ If the job is not deferred for any other reason, requeue the job and notify the scheduler.

    kjl_index := jmv$known_job_list.state_data [jmc$kjl_deferred_entry].first_entry;
    WHILE kjl_index <> jmc$kjl_undefined_index DO
      next_kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
      IF ve_job (kjl_index) AND (jmv$kjlx_p^ [kjl_index].login_user_identification.family = family_name) THEN
        jmv$kjl_p^ [kjl_index].login_family_available := TRUE;
        deferred_job := (current_clock_time < jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate) OR
              jmv$kjl_p^ [kjl_index].job_deferred_by_operator OR jmv$kjl_p^ [kjl_index].job_deferred_by_user;

        IF NOT deferred_job THEN
          qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_queued_entry);
          qfp$relink_kjl_application (kjl_index, jmc$ve_input_application_index, jmc$kjl_application_new);
          notify_input_application (jmc$ve_input_application_index, kjl_index);
        IFEND;
      IFEND;
      kjl_index := next_kjl_index;
    WHILEND;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$activate_deferred_family;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$change_input_attributes', EJECT ??
*copy qfh$change_input_attributes

  PROCEDURE [XDCL, #GATE] qfp$change_input_attributes
    (    system_label: jmt$job_system_label;
         job_class: jmt$job_class;
         privileged_job: boolean;
         earliest_clock_time_to_initiate: jmt$clock_time;
         latest_clock_time_to_initiate: jmt$clock_time;
         current_clock_time: jmt$clock_time;
         valid_mainframe_set: jmt$valid_mainframe_set;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      deferred_job: boolean,
      entry_kind: jmt$kjl_entry_kind,
      ignore_status: ost$status,
      job_name_has_changed: boolean,
      kjl_index: jmt$kjl_index,
      profile_mismatch: boolean,
      system_job_name: jmt$system_supplied_name,
      time_deferred_job: boolean;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

  /find_entry_in_kjl/
    FOR entry_kind := LOWERVALUE (entry_kind) TO UPPERVALUE (entry_kind) DO
      IF entry_kind IN $jmt$kjl_entry_kind_set [jmc$kjl_deferred_entry, jmc$kjl_queued_entry] THEN
        kjl_index := jmv$known_job_list.state_data [entry_kind].first_entry;
        WHILE kjl_index <> jmc$kjl_undefined_index DO
          IF (jmv$kjl_p^ [kjl_index].system_job_name = system_label.system_job_name) THEN
            EXIT /find_entry_in_kjl/;
          ELSE
            kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
          IFEND;
        WHILEND;
      IFEND;
    FOREND /find_entry_in_kjl/;

{ If the entry was not in the KJL then something is wrong.

    IF kjl_index = jmc$kjl_undefined_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_label.system_job_name,
            status);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      RETURN;
    IFEND;

{ If the job is assigned to another mainframe its attributes cannot be changed.

    IF jmv$kjl_p^ [kjl_index].client_index > jmc$kjl_client_this_mainframe THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$input_is_initiated, system_label.system_job_name,
            status);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      RETURN;
    IFEND;

    find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);
    system_job_name := jmv$kjl_p^ [kjl_index].system_job_name;

{ get the job from the job scheduler in case it has the job.

    get_job_from_scheduler (kjl_index, jmc$kjl_application_modified, job_name_has_changed);
    IF job_name_has_changed THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      RETURN;
    IFEND;

{ Check if the scheduling profile structure has changed since the job class was selected.

    qfp$check_for_profile_mismatch (system_label.active_profile_version, profile_mismatch);
    IF profile_mismatch OR jmv$sched_profile_is_loading THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$scheduling_profile_changed, '', status);
    ELSE

      jmv$kjl_p^ [kjl_index].user_job_name := system_label.user_job_name;
      IF NOT privileged_job THEN
        jmv$kjl_p^ [kjl_index].job_submission_time := current_clock_time;
      IFEND;
      jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate := earliest_clock_time_to_initiate;
      jmv$kjl_p^ [kjl_index].job_category_set := system_label.job_category_set;
      jmv$kjl_p^ [kjl_index].job_priority := 0;
      jmv$kjl_p^ [kjl_index].job_deferred_by_operator := system_label.job_deferred_by_operator;
      jmv$kjl_p^ [kjl_index].job_deferred_by_user := system_label.job_deferred_by_user;

      jmv$kjl_p^ [kjl_index].next_destination_usage := system_label.job_destination_usage;
      jmv$kjlx_p^ [kjl_index].latest_clock_time_to_initiate := latest_clock_time_to_initiate;

      jmv$kjlx_p^ [kjl_index].output_disposition_key := system_label.job_attributes.output_disposition_key;
      jmv$kjlx_p^ [kjl_index].valid_mainframe_set := valid_mainframe_set;

{ Is the job a deferred job??

      time_deferred_job := (current_clock_time < earliest_clock_time_to_initiate);
      deferred_job := time_deferred_job OR system_label.job_deferred_by_operator OR
            system_label.job_deferred_by_user OR (NOT jmv$kjl_p^ [kjl_index].login_family_available);
      IF deferred_job AND (jmv$kjl_p^ [kjl_index].application_state <= jmc$kjl_application_new) THEN
        IF time_deferred_job AND (earliest_clock_time_to_initiate < jmv$time_to_ready_deferred_job) THEN
          jmv$time_to_ready_deferred_job := earliest_clock_time_to_initiate;
        IFEND;
        qfp$relink_kjl_entry (kjl_index, job_class, jmc$kjl_deferred_entry);
        IF jmv$kjl_p^ [kjl_index].application_state = jmc$kjl_application_new THEN

{ The application index on this request is unimportant since the target is unused.

          qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
        IFEND;
        jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;

      ELSE
        IF jmv$kjl_p^ [kjl_index].application_state > jmc$kjl_application_new THEN

{ If the destination has changed or the job is now deferred it must be taken away
{ from the application.  Note that since the job is acquired, it must be taken away
{ using the application protocol.  Therefore any state transitions, e.g. going to
{ deferred will take place when the application returns the job.

          IF (jmv$kjl_p^ [kjl_index].destination_usage = jmv$kjl_p^ [kjl_index].next_destination_usage) AND
                (NOT deferred_job) THEN
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_modified);
          ELSE
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_terminated);
          IFEND;
        ELSE
          qfp$relink_kjl_entry (kjl_index, job_class, jmc$kjl_queued_entry);
          find_destination_usage (jmv$kjl_p^ [kjl_index].next_destination_usage, application_index);
          qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_new);
          jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
        IFEND;
        notify_input_application (application_index, kjl_index);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$change_input_attributes;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$defer_deactivated_family', EJECT ??
*copy qfh$defer_deactivated_family

{ NOTE:
{   This request is only meaningful for NOS/VE jobs that are destined for the job scheduler.
{   This request will not defer leveled jobs.

  PROCEDURE [XDCL, #GATE] qfp$defer_deactivated_family
    (    family_name: ost$name);

    VAR
      current_clock_time: jmt$clock_time,
      deferred_job: boolean,
      kjl_entry_kind: jmt$kjl_entry_kind,
      kjl_index: jmt$kjl_index,
      next_kjl_index: jmt$kjl_index;

    current_clock_time := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

{ Take all jobs away from the job scheduler.

    jmp$force_candidate_refresh ({ flush_candidate_queue } TRUE);

{ Scan the deferred and queued threads for jobs that need to be deferred because their
{ login family is not available.  If the job belongs the another mainframe (a leveled job)
{ do not defer it.  Let the job leveler task deal with it.

    FOR kjl_entry_kind := LOWERVALUE (jmt$kjl_entry_kind) TO UPPERVALUE (jmt$kjl_entry_kind) DO
      IF kjl_entry_kind IN $jmt$kjl_entry_kind_set [jmc$kjl_deferred_entry, jmc$kjl_queued_entry] THEN
        kjl_index := jmv$known_job_list.state_data [kjl_entry_kind].first_entry;
        WHILE kjl_index <> jmc$kjl_undefined_index DO
          next_kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
          IF ve_job (kjl_index) AND (jmv$kjlx_p^ [kjl_index].login_user_identification.family =
                family_name) AND (jmv$kjl_p^ [kjl_index].server_index = jmc$kjl_server_this_mainframe) THEN
            jmv$kjl_p^ [kjl_index].login_family_available := FALSE;
            IF kjl_entry_kind <> jmc$kjl_deferred_entry THEN
              qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_deferred_entry);
              qfp$relink_kjl_application (kjl_index, jmc$ve_input_application_index,
                    jmc$kjl_application_unused);
            IFEND;
          IFEND;
          kjl_index := next_kjl_index;
        WHILEND;
      IFEND
    FOREND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$defer_deactivated_family;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] qfp$relink_kjl_application', EJECT ??
*copy qfh$relink_kjl_application

{ DESIGN:
{   Upon entry to the procedure, the KJL entry contains the destination_usage and application_state that
{ defines the application thread that the entry belongs to.  The entry is removed from this thread and
{ added to the thread described by the application_index and destination_state supplied on the request.
{

  PROCEDURE [XDCL] qfp$relink_kjl_application
    (    kjl_index: jmt$kjl_index;
         destination_application_index: jmt$input_application_index;
         destination_state: jmt$kjl_application_state);

    VAR
      source_state: jmt$kjl_application_state,
      source_application_index: jmt$input_application_index;

    find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, source_application_index);
    source_state := jmv$kjl_p^ [kjl_index].application_state;

    CASE source_state OF
    = jmc$kjl_application_unused =
      ;

    ELSE

{ Delete the entry from its application thread.

      IF jmv$kjl_p^ [kjl_index].application_reverse_link = jmc$kjl_undefined_index THEN
        jmv$known_job_list.application_table [source_application_index].state_data [source_state].
              first_entry := jmv$kjl_p^ [kjl_index].application_forward_link;
      ELSE
        jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].application_reverse_link].
              application_forward_link := jmv$kjl_p^ [kjl_index].application_forward_link;
      IFEND;

      IF jmv$kjl_p^ [kjl_index].application_forward_link = jmc$kjl_undefined_index THEN
        jmv$known_job_list.application_table [source_application_index].state_data [source_state].
              last_entry := jmv$kjl_p^ [kjl_index].application_reverse_link;
      ELSE
        jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].application_forward_link].
              application_reverse_link := jmv$kjl_p^ [kjl_index].application_reverse_link;
      IFEND;

{ Decrement the count for the application/state thread

      jmv$known_job_list.application_table [source_application_index].state_data [source_state].
            number_of_entries := jmv$known_job_list.application_table [source_application_index].
            state_data [source_state].number_of_entries - 1;
    CASEND;


    CASE destination_state OF

    = jmc$kjl_application_unused =

{ Make the entry unused.

      jmv$kjl_p^ [kjl_index].application_reverse_link := jmc$kjl_undefined_index;
      jmv$kjl_p^ [kjl_index].application_forward_link := jmc$kjl_undefined_index;

    ELSE

{ Insert the entry at the end of the destination thread.

      IF jmv$known_job_list.application_table [destination_application_index].state_data [destination_state].
            last_entry = jmc$kjl_undefined_index THEN
        jmv$kjl_p^ [kjl_index].application_reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].application_forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.application_table [destination_application_index].state_data [destination_state].
              first_entry := kjl_index;
        jmv$known_job_list.application_table [destination_application_index].state_data [destination_state].
              last_entry := kjl_index;
      ELSE
        jmv$kjl_p^ [kjl_index].application_reverse_link := jmv$known_job_list.
              application_table [destination_application_index].state_data [destination_state].last_entry;
        jmv$kjl_p^ [jmv$known_job_list.application_table [destination_application_index].
              state_data [destination_state].last_entry].application_forward_link := kjl_index;
        jmv$kjl_p^ [kjl_index].application_forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.application_table [destination_application_index].state_data [destination_state].
              last_entry := kjl_index;
      IFEND;

{ Increment the count of the number of entries in the state

      jmv$known_job_list.application_table [destination_application_index].state_data [destination_state].
            number_of_entries := jmv$known_job_list.application_table [destination_application_index].
            state_data [destination_state].number_of_entries + 1;
    CASEND;

    jmv$kjl_p^ [kjl_index].application_state := destination_state;
  PROCEND qfp$relink_kjl_application;
?? TITLE := '[XDCL] qfp$relink_kjl_client', EJECT ??
*copy qfh$relink_kjl_client

  PROCEDURE [XDCL] qfp$relink_kjl_client
    (    kjl_index: jmt$kjl_index;
         destination_client_index: jmt$kjl_client_index);

    VAR
      source_client_index: jmt$kjl_client_index;

    source_client_index := jmv$kjl_p^ [kjl_index].client_index;

{ Remove the entry from the client "source" thread

    IF source_client_index <> jmc$kjl_client_undefined THEN
      IF jmv$kjl_p^ [kjl_index].client_reverse_link = jmc$kjl_undefined_index THEN
        jmv$known_job_list.client_data.state_data [source_client_index].first_entry :=
              jmv$kjl_p^ [kjl_index].client_forward_link;
      ELSE
        jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].client_reverse_link].client_forward_link :=
              jmv$kjl_p^ [kjl_index].client_forward_link;
      IFEND;

      IF jmv$kjl_p^ [kjl_index].client_forward_link = jmc$kjl_undefined_index THEN
        jmv$known_job_list.client_data.state_data [source_client_index].last_entry :=
              jmv$kjl_p^ [kjl_index].client_reverse_link;
      ELSE
        jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].client_forward_link].client_reverse_link :=
              jmv$kjl_p^ [kjl_index].client_reverse_link;
      IFEND;

{ Decrement the count for the client thread

      jmv$known_job_list.client_data.state_data [source_client_index].number_of_entries :=
            jmv$known_job_list.client_data.state_data [source_client_index].number_of_entries - 1;
    IFEND;

{ Add the entry to the destination client thread

    IF destination_client_index = jmc$kjl_client_undefined THEN
      jmv$kjl_p^ [kjl_index].client_reverse_link := jmc$kjl_undefined_index;
      jmv$kjl_p^ [kjl_index].client_forward_link := jmc$kjl_undefined_index;

    ELSE

{ Insert the entry at the end of the destination thread.

      IF jmv$known_job_list.client_data.state_data [destination_client_index].last_entry =
            jmc$kjl_undefined_index THEN
        jmv$kjl_p^ [kjl_index].client_reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].client_forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.client_data.state_data [destination_client_index].first_entry := kjl_index;
        jmv$known_job_list.client_data.state_data [destination_client_index].last_entry := kjl_index;
      ELSE
        jmv$kjl_p^ [kjl_index].client_reverse_link := jmv$known_job_list.client_data.
              state_data [destination_client_index].last_entry;
        jmv$kjl_p^ [jmv$known_job_list.client_data.state_data [destination_client_index].last_entry].
              client_forward_link := kjl_index;
        jmv$kjl_p^ [kjl_index].client_forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.client_data.state_data [destination_client_index].last_entry := kjl_index;
      IFEND;

{ Increment the count of the number of entries for the client

      jmv$known_job_list.client_data.state_data [destination_client_index].number_of_entries :=
            jmv$known_job_list.client_data.state_data [destination_client_index].number_of_entries + 1;
    IFEND;

    jmv$kjl_p^ [kjl_index].client_index := destination_client_index;
  PROCEND qfp$relink_kjl_client;
?? TITLE := '[XDCL] qfp$relink_kjl_entry', EJECT ??
*copy qfh$relink_kjl_entry

{ DESIGN:
{   The entry state in the KJL entry is used to determine the state thread that the entry is currently in.
{   The entry state chain is maintained as a doubly linked list so it can be searched backwards.
{
{   The job class thread is ordered by job priority.  So whenever an entry is added to KJL it is placed
{   in the job class thread at the proper position.

  PROCEDURE [XDCL] qfp$relink_kjl_entry
    (    kjl_index: jmt$kjl_index;
         destination_job_class: jmt$job_class;
         destination_entry_kind: jmt$kjl_entry_kind);

    VAR
      bias_priority: integer,
      current_microsecond_clock: jmt$clock_time,
      insertion_index: jmt$kjl_index,
      job_priority: integer,
      source_job_class: jmt$job_class,
      source_entry_kind: jmt$kjl_entry_kind,
      ve_destined_job: boolean;

?? NEWTITLE := '[INLINE] job_selection_priority', EJECT ??

{ PURPOSE:
{   Calculate a jobs priority without restricting it to the jmt$job_priority
{   type range.

    FUNCTION [INLINE] job_selection_priority
      (    kjl_index: jmt$kjl_index): integer;

      IF kjl_index = jmc$kjl_undefined_index THEN
        job_selection_priority := 0;
      ELSEIF jmv$job_class_table_p^ [destination_job_class].initiation_age_interval <>
            jmc$unlimited_prio_age_interval THEN
        job_selection_priority := ((current_microsecond_clock - jmv$kjl_p^ [kjl_index].job_submission_time) *
              jmv$job_class_table_p^ [destination_job_class].selection_priority.increment DIV
              jmv$job_class_table_p^ [destination_job_class].initiation_age_interval) +
              jmv$kjl_p^ [kjl_index].priority_bias;
      ELSE
        job_selection_priority := jmv$kjl_p^ [kjl_index].priority_bias;
      IFEND;
    FUNCEND job_selection_priority;

?? OLDTITLE, EJECT ??

    osp$set_mainframe_sig_lock (jmv$job_counts_lock);

    ve_destined_job := ve_job (kjl_index);
    source_job_class := jmv$kjl_p^ [kjl_index].job_class;
    source_entry_kind := jmv$kjl_p^ [kjl_index].entry_kind;

{ Delete the entry from its thread

    IF jmv$kjl_p^ [kjl_index].reverse_link = jmc$kjl_undefined_index THEN
      jmv$known_job_list.state_data [source_entry_kind].first_entry := jmv$kjl_p^ [kjl_index].forward_link;
    ELSE
      jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].reverse_link].forward_link := jmv$kjl_p^ [kjl_index].forward_link;
    IFEND;

    IF jmv$kjl_p^ [kjl_index].forward_link = jmc$kjl_undefined_index THEN
      jmv$known_job_list.state_data [source_entry_kind].last_entry := jmv$kjl_p^ [kjl_index].reverse_link;
    ELSE
      jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].forward_link].reverse_link := jmv$kjl_p^ [kjl_index].reverse_link;
    IFEND;

{ Decrement the count of the number of entries in the state

    jmv$known_job_list.state_data [source_entry_kind].number_of_entries := jmv$known_job_list.
          state_data [source_entry_kind].number_of_entries - 1;

{ If the job is in the queued state it must be removed from the job class thread
{ and the counts must be updated.

    CASE source_entry_kind OF
    = jmc$kjl_queued_entry =

{ The job is only entered into the job class thread if it is a VE job.

      IF ve_destined_job THEN
        IF jmv$kjl_p^ [kjl_index].class_reverse_link = jmc$kjl_undefined_index THEN
          jmv$known_job_list.queued_class_entries [source_job_class].
                first_queued_class_entry := jmv$kjl_p^ [kjl_index].class_forward_link;
        ELSE
          jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].class_reverse_link].class_forward_link :=
                jmv$kjl_p^ [kjl_index].class_forward_link;
        IFEND;

        IF jmv$kjl_p^ [kjl_index].class_forward_link = jmc$kjl_undefined_index THEN
          jmv$known_job_list.queued_class_entries [source_job_class].
                last_queued_class_entry := jmv$kjl_p^ [kjl_index].class_reverse_link;
        ELSE
          jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].class_forward_link].class_reverse_link :=
                jmv$kjl_p^ [kjl_index].class_reverse_link;
        IFEND;
        jmv$kjl_p^ [kjl_index].class_forward_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].class_reverse_link := jmc$kjl_undefined_index;
        jmv$job_counts.job_class_counts [source_job_class].queued_jobs := jmv$job_counts.
              job_class_counts [source_job_class].queued_jobs - 1;
        jmv$job_counts.queued_jobs := jmv$job_counts.queued_jobs - 1;
      IFEND; { ve_destined_job

    ELSE
      ;
    CASEND;

{ Add the entry to the destination thread.

    CASE destination_entry_kind OF

    = jmc$kjl_unused_entry =

{ First, zero out the entry.

      pmp$zero_out_table (^jmv$kjl_p^ [kjl_index], #SIZE (jmv$kjl_p^ [kjl_index]));

{ Insert in the "unused" thread.  Trace backwards to find the next previous unused entry to insert after.

      insertion_index := kjl_index - 1;
      WHILE (insertion_index <> jmc$kjl_undefined_index) AND
            (jmv$kjl_p^ [insertion_index].entry_kind <> jmc$kjl_unused_entry) DO
        insertion_index := insertion_index - 1;
      WHILEND;
      IF insertion_index = jmc$kjl_undefined_index THEN

{ Insert at the "head" of the unused thread

        jmv$kjl_p^ [kjl_index].reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].forward_link := jmv$known_job_list.state_data [jmc$kjl_unused_entry].
              first_entry;
        jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry := kjl_index;
        IF jmv$kjl_p^ [kjl_index].forward_link <> jmc$kjl_undefined_index THEN
          jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].forward_link].reverse_link := kjl_index;
        IFEND;
      ELSE

{ Insert in the unused thread.

        jmv$kjl_p^ [kjl_index].reverse_link := insertion_index;
        jmv$kjl_p^ [kjl_index].forward_link := jmv$kjl_p^ [insertion_index].forward_link;
        IF jmv$kjl_p^ [kjl_index].forward_link <> jmc$kjl_undefined_index THEN
          jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].forward_link].reverse_link := kjl_index;
        IFEND;
        jmv$kjl_p^ [insertion_index].forward_link := kjl_index;
      IFEND;

    ELSE

{ Insert at the end of the destination thread.

      IF jmv$known_job_list.state_data [destination_entry_kind].last_entry = jmc$kjl_undefined_index THEN
        jmv$kjl_p^ [kjl_index].reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.state_data [destination_entry_kind].first_entry := kjl_index;
        jmv$known_job_list.state_data [destination_entry_kind].last_entry := kjl_index;
      ELSE
        jmv$kjl_p^ [kjl_index].reverse_link := jmv$known_job_list.state_data [destination_entry_kind].
              last_entry;
        jmv$kjl_p^ [jmv$known_job_list.state_data [destination_entry_kind].last_entry].forward_link :=
              kjl_index;
        jmv$kjl_p^ [kjl_index].forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.state_data [destination_entry_kind].last_entry := kjl_index;
      IFEND;
    CASEND;

{ Increment the count for the destination thread.

    jmv$known_job_list.state_data [destination_entry_kind].number_of_entries :=
          jmv$known_job_list.state_data [destination_entry_kind].number_of_entries + 1;

{ The entry must be inserted in the class thread and job counts must be updated.

    CASE destination_entry_kind OF
    = jmc$kjl_queued_entry =
      IF ve_destined_job THEN
        jmv$job_counts.queued_jobs := jmv$job_counts.queued_jobs + 1;
        jmv$job_counts.job_class_counts [destination_job_class].queued_jobs :=
              jmv$job_counts.job_class_counts [destination_job_class].queued_jobs + 1;

{ If the job is a ve job it needs to be placed in the job class thread at the appropriate
{ priority position.  It is assumed that the job being entered is lower priority than all
{ other jobs in the class so start searching for an insertion location at the end of the
{ job class thread.

        current_microsecond_clock := #FREE_RUNNING_CLOCK (0);
        jmv$kjl_p^ [kjl_index].priority_bias := 0;
        job_priority := job_selection_priority (kjl_index);
        insertion_index := jmv$known_job_list.queued_class_entries [destination_job_class].
              last_queued_class_entry;

{ If the job class defines a multiple job bias then check if any jobs were
{ submitted by this user within the bias limit.

        IF (insertion_index <> jmc$kjl_undefined_index) AND
              (jmv$job_class_table_p^ [destination_job_class].multiple_job_bias > 0) THEN
          bias_priority := job_priority + jmv$job_class_table_p^ [destination_job_class].multiple_job_bias;

{ Skip over any jobs submitted after this job was.

          WHILE (insertion_index <> jmc$kjl_undefined_index) AND
                (jmv$kjl_p^ [insertion_index].job_submission_time > jmv$kjl_p^ [kjl_index].
                job_submission_time) OR (jmv$kjlx_p^ [insertion_index].login_user_identification <>
                jmv$kjlx_p^ [kjl_index].login_user_identification) AND
                (job_priority > job_selection_priority (insertion_index)) DO
            insertion_index := jmv$kjl_p^ [insertion_index].class_reverse_link;
          WHILEND;

{ Now, scan backwards either until a job is found with a large enough priority
{ to be outside the multiple_job_bias range or a job of with the same user
{ identification is found.  If the second condition occurs, then we must apply
{ a bias to the new job so its priority is multiple_job_bias less then the job
{ just found.

          WHILE (insertion_index <> jmc$kjl_undefined_index) AND
                (bias_priority > job_selection_priority (insertion_index)) DO
            IF jmv$kjlx_p^ [insertion_index].login_user_identification =
                  jmv$kjlx_p^ [kjl_index].login_user_identification THEN
              jmv$kjl_p^ [kjl_index].priority_bias := job_selection_priority (insertion_index) -
                    bias_priority;
              job_priority := job_priority + jmv$kjl_p^ [kjl_index].priority_bias;
              insertion_index := jmc$kjl_undefined_index;
            ELSE
              insertion_index := jmv$kjl_p^ [insertion_index].class_reverse_link;
            IFEND;
          WHILEND;
          insertion_index := jmv$known_job_list.queued_class_entries [destination_job_class].
                last_queued_class_entry;
        IFEND;

{ Scan backwards until a job until a job of equal or greater priority is found.

        WHILE (insertion_index <> jmc$kjl_undefined_index) AND
              (job_priority > job_selection_priority (insertion_index)) DO
          insertion_index := jmv$kjl_p^ [insertion_index].class_reverse_link;
        WHILEND;

{ Skip jobs of equal priority that have a later submittion time.

        WHILE (insertion_index <> jmc$kjl_undefined_index) AND
              (job_priority = job_selection_priority (insertion_index)) AND
              (jmv$kjl_p^ [insertion_index].job_submission_time > jmv$kjl_p^ [kjl_index].
              job_submission_time) DO
          insertion_index := jmv$kjl_p^ [insertion_index].class_reverse_link;
        WHILEND;

        IF insertion_index = jmc$kjl_undefined_index THEN

{ Insert at the head of the job class thread.

          jmv$kjl_p^ [kjl_index].class_reverse_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].class_forward_link := jmv$known_job_list.
                queued_class_entries [destination_job_class].first_queued_class_entry;
          jmv$known_job_list.queued_class_entries [destination_job_class].first_queued_class_entry :=
                kjl_index;
          IF jmv$kjl_p^ [kjl_index].class_forward_link = jmc$kjl_undefined_index THEN
            jmv$known_job_list.queued_class_entries [destination_job_class].last_queued_class_entry :=
                  kjl_index;
          ELSE
            jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].class_forward_link].class_reverse_link := kjl_index;
          IFEND;
        ELSE

{ Insert in the job class thread.

          jmv$kjl_p^ [kjl_index].class_forward_link := jmv$kjl_p^ [insertion_index].class_forward_link;
          jmv$kjl_p^ [kjl_index].class_reverse_link := insertion_index;
          IF jmv$kjl_p^ [kjl_index].class_forward_link = jmc$kjl_undefined_index THEN
            jmv$known_job_list.queued_class_entries [destination_job_class].last_queued_class_entry :=
                  kjl_index;
          ELSE
            jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].class_forward_link].class_reverse_link := kjl_index;
          IFEND;
          jmv$kjl_p^ [insertion_index].class_forward_link := kjl_index;
        IFEND;
      IFEND;

    ELSE
      ;
    CASEND;

    jmv$kjl_p^ [kjl_index].entry_kind := destination_entry_kind;
    jmv$kjl_p^ [kjl_index].job_class := destination_job_class;
    osp$clear_mainframe_sig_lock (jmv$job_counts_lock);

  PROCEND qfp$relink_kjl_entry;
?? TITLE := '[XDCL, #GATE] qfp$relink_kjl_server', EJECT ??
*copy qfh$relink_kjl_server

  PROCEDURE [XDCL, #GATE] qfp$relink_kjl_server
    (    kjl_index: jmt$kjl_index;
         destination_server_index: jmt$kjl_server_index);

    VAR
      source_server_index: jmt$kjl_server_index;

    source_server_index := jmv$kjl_p^ [kjl_index].server_index;

{ Remove the entry from the server "source" thread

    IF source_server_index <> jmc$kjl_server_undefined THEN
      IF jmv$kjl_p^ [kjl_index].server_reverse_link = jmc$kjl_undefined_index THEN
        jmv$known_job_list.server_data.state_data [source_server_index].first_entry :=
              jmv$kjl_p^ [kjl_index].server_forward_link;
      ELSE
        jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].server_reverse_link].server_forward_link :=
              jmv$kjl_p^ [kjl_index].server_forward_link;
      IFEND;

      IF jmv$kjl_p^ [kjl_index].server_forward_link = jmc$kjl_undefined_index THEN
        jmv$known_job_list.server_data.state_data [source_server_index].last_entry :=
              jmv$kjl_p^ [kjl_index].server_reverse_link;
      ELSE
        jmv$kjl_p^ [jmv$kjl_p^ [kjl_index].server_forward_link].server_reverse_link :=
              jmv$kjl_p^ [kjl_index].server_reverse_link;
      IFEND;

{ Decrement the count for the server thread

      jmv$known_job_list.server_data.state_data [source_server_index].number_of_entries :=
            jmv$known_job_list.server_data.state_data [source_server_index].number_of_entries - 1;
    IFEND;

{ Add the entry to the destination server thread

    IF destination_server_index = jmc$kjl_server_undefined THEN
      jmv$kjl_p^ [kjl_index].server_reverse_link := jmc$kjl_undefined_index;
      jmv$kjl_p^ [kjl_index].server_forward_link := jmc$kjl_undefined_index;

    ELSE

{ Insert the entry at the end of the destination thread.

      IF jmv$known_job_list.server_data.state_data [destination_server_index].last_entry =
            jmc$kjl_undefined_index THEN
        jmv$kjl_p^ [kjl_index].server_reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].server_forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.server_data.state_data [destination_server_index].first_entry := kjl_index;
        jmv$known_job_list.server_data.state_data [destination_server_index].last_entry := kjl_index;
      ELSE
        jmv$kjl_p^ [kjl_index].server_reverse_link := jmv$known_job_list.server_data.
              state_data [destination_server_index].last_entry;
        jmv$kjl_p^ [jmv$known_job_list.server_data.state_data [destination_server_index].last_entry].
              server_forward_link := kjl_index;
        jmv$kjl_p^ [kjl_index].server_forward_link := jmc$kjl_undefined_index;
        jmv$known_job_list.server_data.state_data [destination_server_index].last_entry := kjl_index;
      IFEND;

{ Increment the count of the number of entries for the server

      jmv$known_job_list.server_data.state_data [destination_server_index].number_of_entries :=
            jmv$known_job_list.server_data.state_data [destination_server_index].number_of_entries + 1;
    IFEND;

    jmv$kjl_p^ [kjl_index].server_index := destination_server_index;
  PROCEND qfp$relink_kjl_server;
?? TITLE := 'validate_application_access', EJECT ??

{ PURPOSE:
{    This request will validate that the executing task is the legitimate user of the destination usage
{  specified.  The index into the application table for the specified destination_usage is returned.
{

  PROCEDURE validate_application_access
    (    destination_usage: jmt$destination_usage;
     VAR application_index: jmt$input_application_index;
     VAR status: ost$status);

    VAR
      global_task_id: ost$global_task_id;

    status.normal := TRUE;
    find_destination_usage (destination_usage, application_index);
    IF application_index = jmc$unassigned_input_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$destination_usage_incorrect, destination_usage,
            status);
    ELSE
      pmp$get_executing_task_gtid (global_task_id);
      IF global_task_id <> jmv$known_job_list.application_table [application_index].global_task_id THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$application_not_permitted, destination_usage,
              status);
      IFEND;
    IFEND;
  PROCEND validate_application_access;
?? TITLE := '[XDCL, #GATE] jmp$record_job_attributes', EJECT ??
*copy jmh$record_job_attributes

  PROCEDURE [XDCL, #GATE] jmp$record_job_attributes
    (    job_attributes_p: ^jmt$job_attributes;
         job_recovery_information_p: ^jmt$job_recovery_information;
     VAR status: ost$status);

    VAR
      kjl_index: jmt$kjl_index;


    PROCEDURE scch
      (    mf: ost$monitor_fault;
           ctc: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      osp$monitor_fault_to_status (mf, ctc, status);
      EXIT jmp$record_job_attributes;
    PROCEND scch;

    status.normal := TRUE;
    kjl_index := jmv$jcb.job_id;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);
    syp$establish_condition_handler (^scch);
    jmv$kjlx_p^ [kjl_index].job_controller := job_attributes_p^.job_controller;
    jmv$kjlx_p^ [kjl_index].originating_ssn := job_attributes_p^.originating_ssn;
    jmv$kjlx_p^ [kjl_index].timesharing_job := (job_attributes_p^.originating_application_name =
          osc$timesharing);
    jmv$kjlx_p^ [kjl_index].output_disposition_key := job_attributes_p^.output_disposition_key;
    jmv$kjlx_p^ [kjl_index].job_initiation_time := job_attributes_p^.job_initiation_time;
    IF jmv$kjlx_p^ [kjl_index].job_mode <> jmc$batch THEN
      ALLOCATE jmv$kjlx_p^ [kjl_index].system_label_p IN osv$mainframe_pageable_heap^;
      jmv$kjlx_p^ [kjl_index].system_label_p^ := job_recovery_information_p^.job_system_label;
    ELSE
      jmv$kjlx_p^ [kjl_index].system_label_p := NIL;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND jmp$record_job_attributes;
?? TITLE := '[XDCL, #GATE] jmp$set_job_history_state', EJECT ??
*copy jmh$set_job_history_state

  PROCEDURE [XDCL, #GATE] jmp$set_job_history_state
    (    state: boolean);

    jmv$job_history_active := state;

  PROCEND jmp$set_job_history_state;
?? TITLE := '[XDCL, #GATE] jmp$set_job_mode', EJECT ??
*copy jmh$set_job_mode

  PROCEDURE [XDCL, #GATE] jmp$set_job_mode
    (    mode: jmt$job_mode;
     VAR status: ost$status);

    status.normal := TRUE;

    jmv$jcb.ijle_p^.job_mode := mode;
    jmv$kjlx_p^ [jmv$jcb.job_id].job_mode := mode;
    IF mode IN $jmt$job_mode_set [jmc$interactive_cmnd_disconnect, jmc$interactive_line_disconnect,
          jmc$interactive_sys_disconnect] THEN
      jmv$kjlx_p^ [jmv$jcb.job_id].terminal_name := osc$null_name;
    IFEND;
  PROCEND jmp$set_job_mode;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$acquire_modified_input', EJECT ??
*copy qfh$acquire_modified_input

  PROCEDURE [XDCL, #GATE] qfp$acquire_modified_input
    (    job_destination_usage: jmt$destination_usage;
     VAR input_descriptor: jmt$input_descriptor;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    validate_application_access (job_destination_usage, application_index, status);
    IF status.normal THEN
      kjl_index := jmv$known_job_list.application_table [application_index].
            state_data [jmc$kjl_application_modified].first_entry;
      IF kjl_index <> jmc$kjl_undefined_index THEN
        input_descriptor.system_job_name := jmv$kjl_p^ [kjl_index].system_job_name;
        input_descriptor.user_job_name := jmv$kjl_p^ [kjl_index].user_job_name;
        qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_acquired);
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$input_queue_is_empty, '', status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$acquire_modified_input;
?? TITLE := '[XDCL, #GATE] qfp$acquire_new_input', EJECT ??
*copy qfh$acquire_new_input

  PROCEDURE [XDCL, #GATE] qfp$acquire_new_input
    (    job_destination_usage: jmt$destination_usage;
     VAR input_descriptor: jmt$input_descriptor;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    validate_application_access (job_destination_usage, application_index, status);
    IF status.normal THEN
      kjl_index := jmv$known_job_list.application_table [application_index].
            state_data [jmc$kjl_application_new].first_entry;
      IF kjl_index <> jmc$kjl_undefined_index THEN
        input_descriptor.system_job_name := jmv$kjl_p^ [kjl_index].system_job_name;
        input_descriptor.user_job_name := jmv$kjl_p^ [kjl_index].user_job_name;
        qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_acquired);
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$input_queue_is_empty, '', status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$acquire_new_input;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$change_terminate_job_action', EJECT ??
*copy qfh$change_terminate_job_action

  PROCEDURE [XDCL, #GATE] qfp$change_terminate_job_action
    (    terminate_job_action_set: jmt$terminate_job_action_set);

    qfv$terminate_job_action_set := terminate_job_action_set;
  PROCEND qfp$change_terminate_job_action;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$discard_job', EJECT ??
*copy qfh$discard_job

  PROCEDURE [XDCL, #GATE] qfp$discard_job;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    qfp$relink_kjl_entry (jmv$jcb.job_id, jmv$kjl_p^ [jmv$jcb.job_id].job_class, jmc$kjl_terminated_entry);
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$discard_job;
?? TITLE := '[XDCL, #GATE] qfp$discard_job_output', EJECT ??
*copy qfh$discard_job_output

  PROCEDURE [XDCL, #GATE] qfp$discard_job_output
    (    output_disposition_key: jmt$output_disposition_keys);

    osp$set_mainframe_sig_lock (qfv$kjl_lock);
    jmv$kjlx_p^ [jmv$jcb.job_id].output_disposition_key := output_disposition_key;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$discard_job_output;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$expand_kjl', EJECT ??
*copy qfh$expand_kjl

{ NOTES:
{   The KJL must be locked when this request is issued.  The only exception to
{ this is during system recovery when access to the KJL is synchronous.

  PROCEDURE [XDCL, #GATE] qfp$expand_kjl;

    CONST
      expand_increment = 100;

    VAR
      kjl_index: jmt$kjl_index,
      new_kjl_limit: jmt$kjl_index;

    IF qfv$current_kjl_limit < jmc$kjl_maximum_entries THEN
      IF qfv$current_kjl_limit + expand_increment > jmc$kjl_maximum_entries THEN
        new_kjl_limit := jmc$kjl_maximum_entries;
      ELSE
        new_kjl_limit := qfv$current_kjl_limit + expand_increment;
      IFEND;
      FOR kjl_index := qfv$current_kjl_limit + 1 TO new_kjl_limit - 1 DO
        jmv$kjl_p^ [kjl_index].forward_link := kjl_index + 1;
        jmv$kjl_p^ [kjl_index].reverse_link := kjl_index - 1;
        jmv$kjl_p^ [kjl_index].entry_kind := jmc$kjl_unused_entry;
      FOREND;
      jmv$kjl_p^ [new_kjl_limit].forward_link := jmc$kjl_undefined_index;
      jmv$kjl_p^ [new_kjl_limit].reverse_link := new_kjl_limit - 1;
      jmv$kjl_p^ [new_kjl_limit].entry_kind := jmc$kjl_unused_entry;

      jmv$known_job_list.state_data [jmc$kjl_unused_entry].number_of_entries :=
            jmv$known_job_list.state_data [jmc$kjl_unused_entry].number_of_entries + new_kjl_limit -
            qfv$current_kjl_limit;
      IF jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry = jmc$kjl_undefined_index THEN
        jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry := qfv$current_kjl_limit + 1;
        jmv$kjl_p^ [qfv$current_kjl_limit + 1].reverse_link := jmc$kjl_undefined_index;
        jmv$known_job_list.state_data [jmc$kjl_unused_entry].last_entry := new_kjl_limit;

      ELSE
        jmv$kjl_p^ [qfv$current_kjl_limit + 1].reverse_link := jmv$known_job_list.
              state_data [jmc$kjl_unused_entry].last_entry;
        jmv$kjl_p^ [jmv$known_job_list.state_data [jmc$kjl_unused_entry].last_entry].forward_link :=
              qfv$current_kjl_limit + 1;
        jmv$known_job_list.state_data [jmc$kjl_unused_entry].last_entry := new_kjl_limit;
      IFEND;
      qfv$current_kjl_limit := new_kjl_limit;
    IFEND;
  PROCEND qfp$expand_kjl;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$get_input_file_location', EJECT ??
*copy qfh$get_input_file_location

{ DESIGN:
{   Use kjl_search to get the job's kjl_index.  Return the input file location
{ and login family from the kjl entry.

  PROCEDURE [XDCL, #GATE] qfp$get_input_file_location
    (    system_job_name: jmt$system_supplied_name;
     VAR location: jmt$input_file_location;
     VAR family: ost$family_name;
     VAR status: ost$status);

    VAR
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    kjl_search (system_job_name, -$jmt$kjl_entry_kind_set [], kjl_index);
    IF kjl_index = jmc$kjl_undefined_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
    ELSE
      location := jmv$kjlx_p^ [kjl_index].input_file_location;
      family := jmv$kjlx_p^ [kjl_index].login_user_identification.family;
    IFEND;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);

  PROCEND qfp$get_input_file_location;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$get_input_q_from_unassigned', EJECT ??
*copy qfh$get_input_q_from_unassigned

  PROCEDURE [XDCL, #GATE] qfp$get_input_q_from_unassigned
    (VAR system_supplied_names: array [1 .. * ] of jmt$system_supplied_name;
     VAR number_of_jobs_found: integer;
     VAR status: ost$status);

    VAR
      kjl_index: jmt$kjl_index,
      result_size: integer;

    status.normal := TRUE;
    number_of_jobs_found := 0;
    result_size := UPPERBOUND (system_supplied_names);

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

{ Scan the UNASSIGNED job class thread for input jobs.  Jobs in a class thread
{ have a destination_usage of VE.

    kjl_index := jmv$known_job_list.queued_class_entries [jmc$unassigned_job_class].first_queued_class_entry;
    WHILE kjl_index <> jmc$kjl_undefined_index DO
      number_of_jobs_found := number_of_jobs_found + 1;
      IF number_of_jobs_found <= result_size THEN
        system_supplied_names [number_of_jobs_found] := jmv$kjl_p^ [kjl_index].system_job_name;
      IFEND;
      kjl_index := jmv$kjl_p^ [kjl_index].class_forward_link;
    WHILEND;

{ Scan the deferred thread for input jobs in the UNASSIGNED job class which
{ are VE jobs.

    kjl_index := jmv$known_job_list.state_data [jmc$kjl_deferred_entry].first_entry;
    WHILE kjl_index <> jmc$kjl_undefined_index DO
      IF jmv$kjl_p^ [kjl_index].job_class = jmc$unassigned_job_class THEN
        IF ve_job (kjl_index) THEN
          number_of_jobs_found := number_of_jobs_found + 1;
          IF number_of_jobs_found <= result_size THEN
            system_supplied_names [number_of_jobs_found] := jmv$kjl_p^ [kjl_index].system_job_name;
          IFEND;
        IFEND;
      IFEND;
      kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
    WHILEND;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);

  PROCEND qfp$get_input_q_from_unassigned;
?? TITLE := '[XDCL, #GATE] qfp$get_job_counts', EJECT ??
*copy qfh$get_job_counts

  PROCEDURE [XDCL, #GATE] qfp$get_job_counts
    (VAR job_counts: jmt$job_counts);

    osp$set_mainframe_sig_lock (jmv$job_counts_lock);
    job_counts := jmv$job_counts;
    osp$clear_mainframe_sig_lock (jmv$job_counts_lock);
  PROCEND qfp$get_job_counts;
?? TITLE := '[XDCL, #GATE] qfp$get_job_internal_info', EJECT ??
*copy qfh$get_job_internal_info

  PROCEDURE [XDCL, #GATE] qfp$get_job_internal_info
    (    system_job_name: jmt$system_supplied_name;
     VAR job_internal_info: jmt$job_internal_information;
     VAR status: ost$status);

    VAR
      entry_kind: jmt$kjl_entry_kind,
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    FOR entry_kind := SUCC (jmc$kjl_unused_entry) TO UPPERVALUE (entry_kind) DO
      IF entry_kind IN $jmt$kjl_entry_kind_set [jmc$kjl_initiated_entry, jmc$kjl_terminated_entry] THEN

        kjl_index := jmv$known_job_list.state_data [entry_kind].first_entry;

      /search_for_ssn/
        WHILE kjl_index <> jmc$kjl_undefined_index DO

          IF jmv$kjl_p^ [kjl_index].system_job_name = system_job_name THEN
            job_internal_info.jmtr_global_taskid := jmv$kjlx_p^ [kjl_index].job_monitor_global_task_id;
            job_internal_info.job_mode := jmv$kjlx_p^ [kjl_index].job_mode;
            job_internal_info.ijl_ordinal := jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal;
            job_internal_info.timesharing_job := jmv$kjlx_p^ [kjl_index].timesharing_job;
            osp$clear_mainframe_sig_lock (qfv$kjl_lock);
            RETURN;
          IFEND;

          kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
        WHILEND /search_for_ssn/;
      IFEND;
    FOREND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
    osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
  PROCEND qfp$get_job_internal_info;
?? TITLE := '[XDCL, #GATE] qfp$get_job_status', EJECT ??
*copy qfh$get_job_status

  PROCEDURE [XDCL, #GATE] qfp$get_job_status
    (    user_identification: ost$user_identification;
         caller_ssn: jmt$system_supplied_name;
         privileged_job: boolean;
         valid_for_scheduling_displays: boolean;
         status_options: ^jmt$job_status_options;
         status_results_keys_p: ^jmt$results_keys;
     VAR status_results_seq_p: ^jmt$work_area;
     VAR number_of_jobs_found: jmt$job_status_count;
     VAR status: ost$status);

    VAR
      ijl_entry_p: ^jmt$initiated_job_list_entry,
      job_class_kjl_index: jmt$kjl_index,
      job_state: jmt$job_state,
      job_state_set: jmt$job_state_set,
      kjl_entry_kind: jmt$kjl_entry_kind,
      kjl_index: jmt$kjl_index,
      name_index: ost$positive_integers,
      option_index: ost$positive_integers,
      qualified_entry_found: boolean,
      result_index: ost$positive_integers,
      status_results_seq_full: boolean;

?? NEWTITLE := 'add_job_to_status_result_seq', EJECT ??

{ PURPOSE:
{   The purpose of this request is to add a job to the job status results
{   sequence supplied on the request.

    PROCEDURE add_job_to_status_results_seq
      (    status_results_keys_p: ^jmt$results_keys;
       VAR status_results_seq_p: ^jmt$work_area;
       VAR status_results_seq_full: boolean);

      VAR
        client_index: jmt$kjl_client_index,
        boolean_p: ^boolean,
        cpu_time_used_p: ^jmt$cpu_time_used,
        display_message_p: ^jmt$display_message,
        ignore_status: ost$status,
        input_file_location_p: ^jmt$input_file_location,
        internal_index_p: ^integer,
        job_class_position_p: ^jmt$job_count_range,
        job_initiation_time_p: ^jmt$date_time,
        job_mode_p: ^jmt$job_mode,
        job_state_p: ^jmt$job_state,
        job_tape_mount_attempts: integer,
        job_tape_mounts_active: boolean,
        local_status: ost$status,
        mainframe_id_p: ^pmt$mainframe_id,
        name_value_p: ^ost$name,
        operator_action_posted_p: ^boolean,
        page_faults_p: ^jmt$page_faults,
        system_job_name_p: ^jmt$system_supplied_name;


      IF status_results_keys_p <> NIL THEN

      /fill_in_each_status_result/
        FOR result_index := 1 TO UPPERBOUND (status_results_keys_p^) DO
          CASE status_results_keys_p^ [result_index] OF

          = jmc$client_mainframe_id =
            NEXT mainframe_id_p IN status_results_seq_p;
            IF mainframe_id_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;

{ The client index in the KJL will be jmc$kjl_client_undefined if the job is not
{ assigned to the job scheduler (or initiated).  If the job was assigned by a server
{ mainframe, then return this mainframe's identifier as the client mainframe id.

            client_index := jmv$kjl_p^ [kjl_index].client_index;
            IF jmv$kjl_p^ [kjl_index].server_index > jmc$kjl_server_this_mainframe THEN
              client_index := jmc$kjl_client_this_mainframe;
            IFEND;
            IF client_index > jmc$kjl_client_undefined THEN
              pmp$convert_binary_mainframe_id (jmv$known_job_list.client_data.state_data [client_index].
                    mainframe_id, mainframe_id_p^, { ignore } local_status);
            ELSE
              mainframe_id_p^ := '';
            IFEND;

          = jmc$control_family =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kjlx_p^ [kjl_index].job_controller.family;

          = jmc$control_user =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kjlx_p^ [kjl_index].job_controller.user;

          = jmc$cpu_time_used =
            NEXT cpu_time_used_p IN status_results_seq_p;
            IF cpu_time_used_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF (job_state IN $jmt$job_state_set [jmc$initiated_job, jmc$terminating_job]) AND
                  ve_job (kjl_index) THEN
              jmp$get_ijle_p (jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal, ijl_entry_p);
              cpu_time_used_p^.job_mode_time := ijl_entry_p^.statistics.cp_time.time_spent_in_job_mode DIV
                    1000;
              cpu_time_used_p^.monitor_mode_time := ijl_entry_p^.statistics.cp_time.time_spent_in_mtr_mode DIV
                    1000;
            ELSE
              cpu_time_used_p^.job_mode_time := 0;
              cpu_time_used_p^.monitor_mode_time := 0;
            IFEND;

          = jmc$display_message =
            NEXT display_message_p IN status_results_seq_p;
            IF display_message_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF (job_state IN $jmt$job_state_set [jmc$initiated_job, jmc$terminating_job]) AND
                  ve_job (kjl_index) THEN
              jmp$get_ijle_p (jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal, ijl_entry_p);
              display_message_p^.size := ijl_entry_p^.display_message.display_message.size;
              display_message_p^.value := ijl_entry_p^.display_message.display_message.text;

            ELSEIF jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_deferred_entry THEN
              IF NOT jmv$kjl_p^ [kjl_index].login_family_available THEN
                display_message_p^.size := STRLENGTH (jmc$dm_login_family_unavailable);
                display_message_p^.value := jmc$dm_login_family_unavailable;
              ELSEIF jmv$kjl_p^ [kjl_index].job_deferred_by_operator THEN
                display_message_p^.size := STRLENGTH (jmc$dm_job_deferred_by_operator);
                display_message_p^.value := jmc$dm_job_deferred_by_operator;
              ELSEIF jmv$kjl_p^ [kjl_index].job_deferred_by_user THEN
                display_message_p^.size := STRLENGTH (jmc$dm_job_deferred_by_user);
                display_message_p^.value := jmc$dm_job_deferred_by_user;
              ELSE { IF jmv$kjl_p^ [kjl_index].earliest_run_time < current_clock_time THEN
                display_message_p^.size := STRLENGTH (jmc$dm_waiting_for_ert);
                display_message_p^.value := jmc$dm_waiting_for_ert;
              IFEND;
            ELSE
              display_message_p^.size := 0;
              display_message_p^.value := '';
            IFEND;

          = jmc$input_file_location =
            NEXT input_file_location_p IN status_results_seq_p;
            IF input_file_location_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            input_file_location_p^ := jmv$kjlx_p^ [kjl_index].input_file_location;

          = jmc$internal_index =
            NEXT internal_index_p IN status_results_seq_p;
            IF internal_index_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            internal_index_p^ := kjl_index;

          = jmc$job_class =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF ve_job (kjl_index) THEN
              jmp$determine_job_class_name (jmv$kjl_p^ [kjl_index].job_class, name_value_p^, local_status);
              IF NOT local_status.normal THEN
                name_value_p^ := jmc$unknown_class_name;
              IFEND;
            ELSE
              name_value_p^ := jmc$unknown_class_name;
            IFEND;

          = jmc$job_class_position =
            NEXT job_class_position_p IN status_results_seq_p;
            IF job_class_position_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF (job_state = jmc$queued_job) AND ve_job (kjl_index) AND valid_for_scheduling_displays THEN
              job_class_position_p^ := 1;
              job_class_kjl_index := jmv$known_job_list.queued_class_entries
                    [jmv$kjl_p^ [kjl_index].job_class].first_queued_class_entry;
              WHILE (job_class_kjl_index <> kjl_index) AND (job_class_kjl_index <> jmc$kjl_undefined_index) DO
                job_class_position_p^ := job_class_position_p^ +1;
                job_class_kjl_index := jmv$kjl_p^ [job_class_kjl_index].class_forward_link;
              WHILEND;
            ELSE
              job_class_position_p^ := 0;
            IFEND;

          = jmc$job_deferred_by_operator =
            NEXT boolean_p IN status_results_seq_p;
            IF boolean_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            boolean_p^ := jmv$kjl_p^ [kjl_index].job_deferred_by_operator;

          = jmc$job_deferred_by_user =
            NEXT boolean_p IN status_results_seq_p;
            IF boolean_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            boolean_p^ := jmv$kjl_p^ [kjl_index].job_deferred_by_user;

          = jmc$job_destination_usage =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kjl_p^ [kjl_index].destination_usage;

          = jmc$job_initiation_time =
            NEXT job_initiation_time_p IN status_results_seq_p;
            IF job_initiation_time_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF (job_state IN $jmt$job_state_set [jmc$initiated_job, jmc$terminating_job]) AND
                  ve_job (kjl_index) THEN
              job_initiation_time_p^.date_time := jmv$kjlx_p^ [kjl_index].job_initiation_time;
              job_initiation_time_p^.specified := TRUE;
            ELSE
              job_initiation_time_p^.specified := FALSE;
            IFEND;

          = jmc$job_mode =
            NEXT job_mode_p IN status_results_seq_p;
            IF job_mode_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            job_mode_p^ := jmv$kjlx_p^ [kjl_index].job_mode;

          = jmc$job_state =
            NEXT job_state_p IN status_results_seq_p;
            IF job_state_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            job_state_p^ := job_state;

          = jmc$login_family =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kjlx_p^ [kjl_index].login_user_identification.family;

          = jmc$login_user =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kjlx_p^ [kjl_index].login_user_identification.user;

          = jmc$null_attribute =
            ;

          = jmc$operator_action_posted =
            NEXT operator_action_posted_p IN status_results_seq_p;
            IF operator_action_posted_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;

          /get_job_tape_mounts_active/
            FOR job_tape_mount_attempts := 1 TO max_job_tape_mount_attempts DO
              job_tape_mounts_active := FALSE;
              iop$job_tape_mounts_active (jmv$kjl_p^ [kjl_index].system_job_name, job_tape_mounts_active,
                    local_status);
              IF NOT local_status.normal AND (local_status.condition = dme$unable_to_lock_tape_table) THEN
                pmp$delay (one_second, ignore_status);
              ELSE
                EXIT /get_job_tape_mounts_active/;
              IFEND;
            FOREND;

            IF ((ofp$job_operator_msgs_active (jmv$kjl_p^ [kjl_index].system_job_name)) OR
                  (ofp$job_operator_menus_active (jmv$kjl_p^ [kjl_index].system_job_name)) OR
                  job_tape_mounts_active) THEN
              operator_action_posted_p^ := TRUE;
            ELSE
              operator_action_posted_p^ := FALSE;
            IFEND;

          = jmc$page_faults =
            NEXT page_faults_p IN status_results_seq_p;
            IF page_faults_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF (job_state IN $jmt$job_state_set [jmc$initiated_job, jmc$terminating_job]) AND
                  ve_job (kjl_index) THEN
              jmp$get_ijle_p (jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal, ijl_entry_p);
              page_faults_p^.pages_reclaimed_from_memory := ijl_entry_p^.statistics.paging_statistics.
                    pages_reclaimed_from_queue;
              page_faults_p^.pages_read_from_disk := ijl_entry_p^.statistics.paging_statistics.page_in_count;
              page_faults_p^.new_pages_assigned := ijl_entry_p^.statistics.paging_statistics.
                    new_pages_assigned;
            ELSE
              page_faults_p^.pages_reclaimed_from_memory := 0;
              page_faults_p^.pages_read_from_disk := 0;
              page_faults_p^.new_pages_assigned := 0;
            IFEND;

          = jmc$server_mainframe_id =
            NEXT mainframe_id_p IN status_results_seq_p;
            IF mainframe_id_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            IF jmv$kjl_p^ [kjl_index].server_index > jmc$kjl_server_undefined THEN
              pmp$convert_binary_mainframe_id (jmv$known_job_list.server_data.
                    state_data [jmv$kjl_p^ [kjl_index].server_index].mainframe_id, mainframe_id_p^,
                    { ignore } local_status);
            ELSE
              pmp$get_mainframe_id (mainframe_id_p^, { ignore } local_status);
            IFEND;

          = jmc$system_job_name =
            NEXT system_job_name_p IN status_results_seq_p;
            IF system_job_name_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            system_job_name_p^ := jmv$kjl_p^ [kjl_index].system_job_name;

          = jmc$user_job_name =
            NEXT name_value_p IN status_results_seq_p;
            IF name_value_p = NIL THEN
              status_results_seq_full := TRUE;
              EXIT /fill_in_each_status_result/;
            IFEND;
            name_value_p^ := jmv$kjl_p^ [kjl_index].user_job_name;

          ELSE
          CASEND;
        FOREND /fill_in_each_status_result/;
      IFEND;
    PROCEND add_job_to_status_results_seq;
?? OLDTITLE ??
?? NEWTITLE := 'handle_core_condition', EJECT ??

    PROCEDURE handle_core_condition
      (    monitor_fault: ost$monitor_fault;
           minimum_save_area_p: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        lock_status: ost$signature_lock_status;

      osp$test_sig_lock (qfv$kjl_lock, lock_status);
      IF lock_status = osc$sls_locked_by_current_task THEN
        osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      IFEND;
      syp$continue_to_cause (monitor_fault, minimum_save_area_p, syc$condition_processed, continue);
      osp$monitor_fault_to_status (monitor_fault, minimum_save_area_p, status);
      EXIT qfp$get_job_status;
    PROCEND handle_core_condition;
?? OLDTITLE ??
?? EJECT ??
    syp$establish_condition_handler (^handle_core_condition);
    status.normal := TRUE;
    number_of_jobs_found := 0;
    status_results_seq_full := status_results_seq_p = NIL;

    job_state_set := -$jmt$job_state_set [];
    IF status_options <> NIL THEN
      FOR option_index := 1 TO UPPERBOUND (status_options^) DO
        IF status_options^ [option_index].key = jmc$job_state_set THEN
          job_state_set := status_options^ [option_index].job_state_set;
        IFEND;
      FOREND;
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

  /search_each_entry_kind/
    FOR job_state := LOWERVALUE (job_state) TO UPPERVALUE (job_state) DO

      IF job_state IN job_state_set THEN
        convert_state_to_entry_kind (job_state, kjl_entry_kind, status);
        IF NOT status.normal THEN
          EXIT /search_each_entry_kind/;
        IFEND;
        kjl_index := jmv$known_job_list.state_data [kjl_entry_kind].first_entry;

      /search_each_entry/
        WHILE kjl_index <> jmc$kjl_undefined_index DO
          IF (jmv$kjlx_p^ [kjl_index].login_user_identification = user_identification) OR
                (jmv$kjlx_p^ [kjl_index].job_controller = user_identification) OR privileged_job OR
                (jmv$kjlx_p^ [kjl_index].originating_ssn = caller_ssn) THEN

            qualified_entry_found := TRUE;
            IF status_options <> NIL THEN

            /status_option_check/
              FOR option_index := 1 TO UPPERBOUND (status_options^) DO
                CASE status_options^ [option_index].key OF

                = jmc$control_family =
                  IF status_options^ [option_index].control_family <>
                        jmv$kjlx_p^ [kjl_index].job_controller.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$control_user =
                  IF status_options^ [option_index].control_user <>
                        jmv$kjlx_p^ [kjl_index].job_controller.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$include_the_system_job =

{ The default is to include the status of the system job if the caller is privileged to see it.
{ The caller must specify this option if it does not want information about the system job.  Note
{ that if the default were not to include the system job, checking for the status options would
{ have to be done independently of the status options check.

                  IF NOT status_options^ [option_index].include_the_system_job THEN
                    IF jmv$kjl_p^ [kjl_index].system_job_name = jmv$system_job_ssn THEN
                      qualified_entry_found := FALSE;
                      EXIT /status_option_check/;
                    IFEND;
                  IFEND;

                = jmc$job_deferred_by_operator =
                  IF jmv$kjl_p^ [kjl_index].job_deferred_by_operator <>
                        status_options^ [option_index].job_deferred_by_operator THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$job_deferred_by_user =
                  IF jmv$kjl_p^ [kjl_index].job_deferred_by_user <>
                        status_options^ [option_index].job_deferred_by_user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$job_mode_set =
                  IF NOT (jmv$kjlx_p^ [kjl_index].job_mode IN status_options^ [option_index].job_mode_set)
                        THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$job_state_set =
                  ;

                = jmc$login_family =
                  IF status_options^ [option_index].login_family <>
                        jmv$kjlx_p^ [kjl_index].login_user_identification.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$login_user =
                  IF status_options^ [option_index].login_user <>
                        jmv$kjlx_p^ [kjl_index].login_user_identification.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/;
                  IFEND;

                = jmc$name_list =
                  IF status_options^ [option_index].name_list <> NIL THEN
                    qualified_entry_found := FALSE;

                  /search_for_name/
                    FOR name_index := 1 TO UPPERBOUND (status_options^ [option_index].name_list^) DO
                      CASE status_options^ [option_index].name_list^ [name_index].kind OF
                      = jmc$system_supplied_name =
                        IF status_options^ [option_index].name_list^ [name_index].system_supplied_name =
                              jmv$kjl_p^ [kjl_index].system_job_name THEN
                          qualified_entry_found := TRUE;
                          EXIT /search_for_name/;
                        IFEND;

                      = jmc$user_supplied_name =
                        IF status_options^ [option_index].name_list^ [name_index].user_supplied_name =
                              jmv$kjl_p^ [kjl_index].user_job_name THEN
                          qualified_entry_found := TRUE;
                          EXIT /search_for_name/;
                        IFEND;

                      ELSE
                        ; { Nothing
                      CASEND;
                    FOREND /search_for_name/;
                    IF NOT qualified_entry_found THEN
                      EXIT /status_option_check/;
                    IFEND;
                  IFEND;

                = jmc$null_attribute =
                  ;

                ELSE
                CASEND;
              FOREND /status_option_check/;
            IFEND;

{ Only return status of jobs that are on their client mainframe.  So if the job
{ is assigned to another client do not return the job's status.

            IF jmv$kjl_p^ [kjl_index].client_index > jmc$kjl_client_this_mainframe THEN
              qualified_entry_found := FALSE;
            IFEND;

            IF qualified_entry_found THEN
              IF (NOT status_results_seq_full) THEN
                add_job_to_status_results_seq (status_results_keys_p, status_results_seq_p,
                      status_results_seq_full);
              IFEND;
              number_of_jobs_found := number_of_jobs_found + 1;
            IFEND; { qualified_entry_found
          IFEND;

          kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
        WHILEND /search_each_entry/;
      IFEND;
    FOREND /search_each_entry_kind/;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
    syp$disestablish_cond_handler;
  PROCEND qfp$get_job_status;
?? TITLE := 'kjl_search', EJECT ??

{ PURPOSE:
{   The purpose of this request is to search the Known Job List for the specified system job name.
{   and return the job's kjl_index.  The kjl_index of jmc$kjl_undefined_index is returned if the
{   job is not found.

  PROCEDURE kjl_search
    (    system_job_name: jmt$system_supplied_name;
         entry_kind_set: jmt$kjl_entry_kind_set;
     VAR kjl_index: jmt$kjl_index);

    VAR
      kjl_entry_kind: jmt$kjl_entry_kind;

    kjl_index := jmc$kjl_undefined_index;

  /kjl_search_each_entry_kind/
    FOR kjl_entry_kind := SUCC (LOWERVALUE (kjl_entry_kind)) TO UPPERVALUE (kjl_entry_kind) DO
      IF kjl_entry_kind IN entry_kind_set THEN
        kjl_index := jmv$known_job_list.state_data [kjl_entry_kind].first_entry;

        WHILE kjl_index <> jmc$kjl_undefined_index DO
          IF (jmv$kjl_p^ [kjl_index].system_job_name = system_job_name) THEN
            EXIT /kjl_search_each_entry_kind/;
          IFEND;
          kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
        WHILEND;
      IFEND;
    FOREND /kjl_search_each_entry_kind/;
  PROCEND kjl_search;
?? TITLE := '[XDCL, #GATE] qfp$job_requests_restart: boolean', EJECT ??
*copy qfh$job_requests_restart

  FUNCTION [XDCL, #GATE] qfp$job_requests_restart: boolean;

    VAR
      ijl_entry_p: ^jmt$initiated_job_list_entry;

    jmp$get_ijle_p (jmv$kjl_p^ [jmv$jcb.job_id].initiated_job_list_ordinal, ijl_entry_p);
    qfp$job_requests_restart := ijl_entry_p^.queue_file_information.job_abort_disposition =
          jmc$restart_on_abort;
  FUNCEND qfp$job_requests_restart;
?? TITLE := '[XDCL, #GATE] qfp$list_jobs_via_mode', EJECT ??
*copy qfh$list_jobs_via_mode

  PROCEDURE [XDCL, #GATE] qfp$list_jobs_via_mode
    (    job_mode: jmt$job_mode;
     VAR system_job_names: array [1 .. * ] of jmt$system_supplied_name;
     VAR number_of_jobs_returned: integer;
     VAR status: ost$status);

    VAR
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;
    number_of_jobs_returned := 0;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);
    kjl_index := jmv$known_job_list.state_data [jmc$kjl_initiated_entry].first_entry;

    WHILE kjl_index <> jmc$kjl_undefined_index DO
      IF jmv$kjlx_p^ [kjl_index].job_mode = job_mode THEN
        IF number_of_jobs_returned < UPPERBOUND (system_job_names) THEN
          number_of_jobs_returned := number_of_jobs_returned + 1;
          system_job_names [number_of_jobs_returned] := jmv$kjl_p^ [kjl_index].system_job_name;
        IFEND;
      IFEND;

      kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
    WHILEND;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$list_jobs_via_mode;
?? TITLE := '[XDCL, #GATE] qfp$move_input_q_to_unassigned', EJECT ??
*copy qfh$move_input_q_to_unassigned

  PROCEDURE [XDCL, #GATE] qfp$move_input_q_to_unassigned
    (    job_class_index: jmt$job_class;
     VAR number_of_jobs_moved: jmt$job_count_range;
     VAR status: ost$status);

    VAR
      job_not_moved: boolean,
      kjl_index: jmt$kjl_index,
      next_kjl_index: jmt$kjl_index;

    status.normal := TRUE;
    number_of_jobs_moved := 0;
    job_not_moved := FALSE;

    IF (job_class_index = jmc$unassigned_job_class) THEN
      RETURN;
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

{ Scan the given job class thread for input jobs and move them to the UNASSIGNED
{ job class.

    kjl_index := jmv$known_job_list.queued_class_entries [job_class_index].first_queued_class_entry;
    WHILE kjl_index <> jmc$kjl_undefined_index DO
      next_kjl_index := jmv$kjl_p^ [kjl_index].class_forward_link;
      IF jmv$kjl_p^ [kjl_index].application_state = jmc$kjl_application_new THEN
        qfp$relink_kjl_entry (kjl_index, jmc$unassigned_job_class, jmc$kjl_queued_entry);
        number_of_jobs_moved := number_of_jobs_moved + 1;
      ELSE
        job_not_moved := TRUE;
      IFEND;
      kjl_index := next_kjl_index;
    WHILEND;

{ Scan the deferred thread for input jobs in the UNASSIGNED job class which
{ have are VE jobs.

    kjl_index := jmv$known_job_list.state_data [jmc$kjl_deferred_entry].first_entry;
    WHILE kjl_index <> jmc$kjl_undefined_index DO
      next_kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
      IF jmv$kjl_p^ [kjl_index].job_class = job_class_index THEN
        IF ve_job (kjl_index) THEN
          jmv$kjl_p^ [kjl_index].job_class := jmc$unassigned_job_class;
          number_of_jobs_moved := number_of_jobs_moved + 1;
        IFEND;
      IFEND;
      kjl_index := next_kjl_index;
    WHILEND;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);

    IF job_not_moved THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$not_all_jobs_were_moved,
            jmv$job_class_table_p^ [job_class_index].name, status);
    IFEND;

  PROCEND qfp$move_input_q_to_unassigned;
?? TITLE := '[XDCL, #GATE] qfp$ready_deferred_job', EJECT ??
*copy qfh$ready_deferred_job

  PROCEDURE [XDCL, #GATE] qfp$ready_deferred_job;

    VAR
      application_index: jmt$input_application_index,
      current_clock_time: jmt$clock_time,
      kjl_index: jmt$kjl_index,
      next_kjl_index: jmt$kjl_index;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    kjl_index := jmv$known_job_list.state_data [jmc$kjl_deferred_entry].first_entry;
    jmv$time_to_ready_deferred_job := jmc$latest_clock_time;
    current_clock_time := #FREE_RUNNING_CLOCK (0);

    WHILE kjl_index <> jmc$kjl_undefined_index DO
      next_kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
      IF (NOT (jmv$kjl_p^ [kjl_index].job_deferred_by_operator OR jmv$kjl_p^ [kjl_index].
            job_deferred_by_user)) AND jmv$kjl_p^ [kjl_index].login_family_available THEN
        IF jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate >= current_clock_time THEN
          IF jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate < jmv$time_to_ready_deferred_job THEN
            jmv$time_to_ready_deferred_job := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate;
          IFEND;
        ELSE

{ This job has become a potential candidate for initiation.

          find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);
          qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_queued_entry);
          qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_new);
          notify_input_application (application_index, kjl_index);
        IFEND;
      IFEND;
      kjl_index := next_kjl_index;
    WHILEND;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$ready_deferred_job;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$rebuild_executing_job', EJECT ??
*copy qfh$rebuild_executing_job

{ NOTES:
{   A recovered job uses the same kjl_index it had when it failed.
{   The KJL is expanded in SYM$JOB_RECOVERY_R3 before this request is issued.

  PROCEDURE [XDCL, #GATE] qfp$rebuild_executing_job
    (    current_clock_time: jmt$clock_time;
         system_job_name: jmt$system_supplied_name;
         job_control_block: jmt$job_control_block);

    VAR
      application_index: jmt$input_application_index,
      kjl_index: jmt$kjl_index,
      kjl_server_index: jmt$kjl_server_index;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    kjl_index := job_control_block.job_id;

    jmv$kjl_p^ [kjl_index].system_job_name := system_job_name;
    jmv$kjl_p^ [kjl_index].user_job_name := job_control_block.jobname;
    jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal := job_control_block.ijl_ordinal;
    jmv$kjl_p^ [kjl_index].job_submission_time := current_clock_time;
    jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate := jmc$earliest_clock_time;
    jmv$kjl_p^ [kjl_index].job_class := job_control_block.ijle_p^.job_scheduler_data.job_class;

{ JSE: The job categories for a job must be updated for active job recovery - when they exist.

    jmv$kjl_p^ [kjl_index].job_category_set := $jmt$job_category_set [];
    jmv$kjl_p^ [kjl_index].job_priority := 0;
    jmv$kjl_p^ [kjl_index].job_deferred_by_operator := FALSE;
    jmv$kjl_p^ [kjl_index].job_deferred_by_user := FALSE;
    jmv$kjl_p^ [kjl_index].login_family_available := TRUE;
    jmv$kjl_p^ [kjl_index].destination_usage := jmc$ve_usage;
    jmv$kjl_p^ [kjl_index].next_destination_usage := jmc$ve_usage;
    jmv$kjl_p^ [kjl_index].application_state := jmc$kjl_application_unused;
    jmv$kjl_p^ [kjl_index].class_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [kjl_index].class_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [kjl_index].client_index := jmc$kjl_client_undefined;
    jmv$kjl_p^ [kjl_index].client_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [kjl_index].client_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [kjl_index].server_index := jmc$kjl_server_undefined;
    jmv$kjl_p^ [kjl_index].server_forward_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [kjl_index].server_reverse_link := jmc$kjl_undefined_index;
    jmv$kjl_p^ [kjl_index].server_kjl_index := kjl_index;
    jmv$kjlx_p^ [kjl_index].login_user_identification := job_control_block.user_id;

{ The job controller, originating ssn, output disposition key and timesharing job are initialized to their
{ correct values in jmp$record_job_attributes.

    jmv$kjlx_p^ [kjl_index].job_controller := job_control_block.user_id;
    jmv$kjlx_p^ [kjl_index].originating_ssn := system_job_name;
    jmv$kjlx_p^ [kjl_index].latest_clock_time_to_initiate := jmc$latest_clock_time;
    jmv$kjlx_p^ [kjl_index].job_mode := job_control_block.ijle_p^.job_mode;
    jmv$kjlx_p^ [kjl_index].job_monitor_global_task_id := job_control_block.job_monitor_id;
    jmv$kjlx_p^ [kjl_index].output_disposition_key := jmc$normal_output_disposition;
    jmv$kjlx_p^ [kjl_index].input_file_location := job_control_block.ijle_p^.queue_file_information.
          input_file_location;
    jmv$kjlx_p^ [kjl_index].valid_mainframe_set := $jmt$valid_mainframe_set [jmc$kjl_server_this_mainframe];
    jmv$kjlx_p^ [kjl_index].timesharing_job := FALSE;
    jmv$kjlx_p^ [kjl_index].restart_job := FALSE;
    jmv$kjlx_p^ [kjl_index].system_label_p := NIL;
    jmv$kjlx_p^ [kjl_index].terminal_name := '';

{ The attribute job_initiation_time is restored by jmp$record_job_attributes
{ The value being stored here is just in case recovery gets tied into knots and
{ the job can't terminate, that job status will return a valid job initiation time.

    jmv$kjlx_p^ [kjl_index].job_initiation_time := jmv$null_date_time;

    find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);

{ Find the server mainframe index in the KJL.

    find_server_mainframe_id (job_control_block.server_mainframe_id, kjl_server_index);

    qfp$relink_kjl_server (kjl_index, kjl_server_index);
    qfp$relink_kjl_client (kjl_index, jmc$kjl_client_this_mainframe);
    qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_initiated_entry);
    qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_initiated);

{ Increment the job counts for initiated jobs.

    jmv$job_counts.initiated_jobs := jmv$job_counts.initiated_jobs + 1;
    jmv$job_counts.job_class_counts [jmv$kjl_p^ [kjl_index].job_class].initiated_jobs :=
          jmv$job_counts.job_class_counts [jmv$kjl_p^ [kjl_index].job_class].initiated_jobs + 1;
    IF jmv$kjlx_p^ [kjl_index].job_mode <> jmc$batch THEN
      jmv$job_counts.interactive_jobs := jmv$job_counts.interactive_jobs + 1;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$rebuild_executing_job;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$rebuild_input_queue', EJECT ??
*copy qfh$rebuild_input_queue

  PROCEDURE [XDCL, #GATE] qfp$rebuild_input_queue
    (    system_label: jmt$job_system_label;
         earliest_clock_time_to_initiate: jmt$clock_time;
         latest_clock_time_to_initiate: jmt$clock_time;
         current_clock_time: jmt$clock_time;
         job_submission_time: jmt$clock_time;
         job_class: jmt$job_class;
         input_file_location: jmt$input_file_location;
         login_family_available: boolean;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      client_mainframe_id: pmt$binary_mainframe_id,
      client_mainframe_id_in_kjl: boolean,
      kjl_client_index: jmt$kjl_client_index,
      kjl_index: jmt$kjl_index,
      time_deferred_job: boolean;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

{ Search for a job with the same name in the KJL.

    kjl_search (system_label.system_job_name, -$jmt$kjl_entry_kind_set [], kjl_index);
    IF kjl_index <> jmc$kjl_undefined_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$duplicate_name, system_label.system_job_name,
            status);
    ELSE

{ If the KJL is out of initialized entries it must be expanded.

      kjl_index := jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry;
      IF kjl_index = jmc$kjl_undefined_index THEN
        qfp$expand_kjl;
        kjl_index := jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry;
      IFEND;

      IF kjl_index = jmc$kjl_undefined_index THEN
        osp$set_status_condition (jme$maximum_jobs, status);

      ELSE
        jmv$kjl_p^ [kjl_index].system_job_name := system_label.system_job_name;
        jmv$kjl_p^ [kjl_index].user_job_name := system_label.user_job_name;
        jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal.block_number := LOWERVALUE (jmt$ijl_block_number);
        jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal.block_index := LOWERVALUE (jmt$ijl_block_index);
        jmv$kjl_p^ [kjl_index].job_submission_time := job_submission_time;
        jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate := earliest_clock_time_to_initiate;
        jmv$kjl_p^ [kjl_index].job_priority := 0;
        jmv$kjl_p^ [kjl_index].job_class := job_class;
        jmv$kjl_p^ [kjl_index].job_category_set := system_label.job_category_set;
        jmv$kjl_p^ [kjl_index].job_deferred_by_operator := system_label.job_deferred_by_operator;
        jmv$kjl_p^ [kjl_index].job_deferred_by_user := system_label.job_deferred_by_user;

{ Non-NOS/VE jobs cannot be deferred because their login family is not available.

        IF input_file_location <> jmc$ifl_store_and_forward_queue THEN
          jmv$kjl_p^ [kjl_index].login_family_available := login_family_available;
        ELSE
          jmv$kjl_p^ [kjl_index].login_family_available := TRUE;
        IFEND;
        jmv$kjl_p^ [kjl_index].destination_usage := system_label.job_destination_usage;
        jmv$kjl_p^ [kjl_index].next_destination_usage := system_label.job_destination_usage;
        jmv$kjl_p^ [kjl_index].application_state := jmc$kjl_application_unused;
        jmv$kjl_p^ [kjl_index].class_forward_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].class_reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].client_index := jmc$kjl_client_undefined;
        jmv$kjl_p^ [kjl_index].client_forward_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].client_reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].server_index := jmc$kjl_server_undefined;
        jmv$kjl_p^ [kjl_index].server_forward_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].server_reverse_link := jmc$kjl_undefined_index;
        jmv$kjl_p^ [kjl_index].server_kjl_index := kjl_index;

        jmv$kjlx_p^ [kjl_index].login_user_identification := system_label.login_user_identification;
        jmv$kjlx_p^ [kjl_index].job_controller := system_label.job_attributes.job_controller;
        jmv$kjlx_p^ [kjl_index].originating_ssn := system_label.job_attributes.originating_ssn;
        jmv$kjlx_p^ [kjl_index].latest_clock_time_to_initiate := latest_clock_time_to_initiate;
        jmv$kjlx_p^ [kjl_index].job_mode := system_label.job_mode;

{ The job monitor global task id is not set here - the job scheduler will set it when the job is initiated.

        jmv$kjlx_p^ [kjl_index].output_disposition_key := system_label.job_attributes.output_disposition_key;
        jmv$kjlx_p^ [kjl_index].input_file_location := input_file_location;
        jmv$kjlx_p^ [kjl_index].valid_mainframe_set := $jmt$valid_mainframe_set [];
        jmv$kjlx_p^ [kjl_index].timesharing_job := system_label.job_attributes.originating_application_name =
              osc$timesharing;
        jmv$kjlx_p^ [kjl_index].restart_job := TRUE;
        jmv$kjlx_p^ [kjl_index].system_label_p := NIL;
        jmv$kjlx_p^ [kjl_index].terminal_name := '';

{ Has the job been initiated on a client mainframe??

        IF system_label.job_initiation_location <> '' THEN

{ If the client does not fit in the KJL then the job cannot be recovered at this time.

          pmp$convert_mainframe_to_binary (system_label.job_initiation_location, client_mainframe_id, status);
          IF status.normal THEN
            find_client_mainframe_id (client_mainframe_id, client_mainframe_id_in_kjl, kjl_client_index);
            IF client_mainframe_id_in_kjl THEN
              qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_initiated_entry);
              qfp$relink_kjl_server (kjl_index, jmc$kjl_server_this_mainframe);
              qfp$relink_kjl_client (kjl_index, kjl_client_index);
            ELSE
              osp$set_status_condition (jme$maximum_jobs, status);
            IFEND;
          IFEND;
        ELSE

{ Is the job deferred?

          time_deferred_job := current_clock_time < earliest_clock_time_to_initiate;
          IF time_deferred_job OR system_label.job_deferred_by_operator OR
                system_label.job_deferred_by_user OR (NOT jmv$kjl_p^ [kjl_index].login_family_available) THEN
            IF time_deferred_job AND (earliest_clock_time_to_initiate < jmv$time_to_ready_deferred_job) THEN
              jmv$time_to_ready_deferred_job := earliest_clock_time_to_initiate;
            IFEND;
            qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_deferred_entry);
          ELSE
            qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_queued_entry);
            find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_new);
          IFEND;
          IF ve_job (kjl_index) THEN
            qfp$relink_kjl_server (kjl_index, jmc$kjl_server_this_mainframe);
          IFEND;
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$rebuild_input_queue;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$release_input_files', EJECT ??
*copy qfh$release_input_files

  PROCEDURE [XDCL, #GATE] qfp$release_input_files
    (    release_file_list: ^jmt$release_input_file_list;
     VAR release_file_count: jmt$job_count_range);

    VAR
      application_index: jmt$input_application_index,
      application_state: jmt$kjl_application_state,
      current_clock_time: jmt$clock_time,
      global_task_id: ost$global_task_id,
      job_class: jmt$job_class,
      kjl_index: jmt$kjl_index,
      next_kjl_index: jmt$kjl_index,
      previously_terminated: boolean,
      relink_application_index: jmt$input_application_index,
      release_list_limit: jmt$job_count_range,
      scheduler_has_a_job: boolean,
      time_deferred_job: boolean;

    pmp$get_executing_task_gtid (global_task_id);

    release_file_count := 0;
    IF release_file_list = NIL THEN
      release_list_limit := 0;
    ELSE
      release_list_limit := UPPERBOUND (release_file_list^);
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

{ Check for the job leveler task.


    IF jmv$known_job_list.application_table [jmc$ve_input_application_index].global_task_id =
          global_task_id THEN
      jmp$force_candidate_refresh ({ flush_candidate_queue } TRUE);

{ Discard every queued job whose server is another mainframe.
{ Theoretically, there should be none.

      kjl_index := jmv$known_job_list.state_data [jmc$kjl_queued_entry].first_entry;
      WHILE kjl_index <> jmc$kjl_undefined_index DO
        next_kjl_index := jmv$kjl_p^ [kjl_index].forward_link;
        IF (jmv$kjl_p^ [kjl_index].server_index > jmc$kjl_server_this_mainframe) THEN
          qfp$relink_kjl_server (kjl_index, jmc$kjl_server_undefined);
          qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_unused_entry);
        IFEND;
        kjl_index := next_kjl_index;
      WHILEND;

      FOR job_class := jmc$system_job_class TO jmv$maximum_job_class_in_use DO
        jmv$known_job_list.queued_class_entries [job_class].class_blocked_for_initiation := FALSE;
      FOREND;
      jmv$known_job_list.application_table [jmc$ve_input_application_index].global_task_id.index := 0;
      jmv$known_job_list.application_table [jmc$ve_input_application_index].global_task_id.seqno := 0;

      jmp$force_candidate_refresh ({ flush_candidate_queue } FALSE);
    IFEND;

{ Check to see if this task has input files registered.

  /search_all_applications/
    FOR application_index := jmc$ve_input_application_index + 1 TO
          UPPERBOUND (jmv$known_job_list.application_table) DO
      IF jmv$known_job_list.application_table [application_index].global_task_id = global_task_id THEN

      /search_all_application_states/
        FOR application_state := SUCC (jmc$kjl_application_unused) TO UPPERVALUE (application_state) DO
          kjl_index := jmv$known_job_list.application_table [application_index].
                state_data [application_state].first_entry;

        /release_entries_in_state/
          WHILE kjl_index <> jmc$kjl_undefined_index DO

{ Save the index of the next KJL entry.  When the entry is relinked, the links on the current entry
{ will no longer link to the next entry that needs to be managed.

            next_kjl_index := jmv$kjl_p^ [kjl_index].application_forward_link;
            previously_terminated := jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_terminated_entry;

{ If the file was terminated, add it to the release list so the caller knows to delete the file
{ and remove the file from the KJL.

            IF previously_terminated THEN
              release_file_count := release_file_count + 1;
              IF release_file_count <= release_list_limit THEN
                release_file_list^ [release_file_count].system_job_name :=
                      jmv$kjl_p^ [kjl_index].system_job_name;
                release_file_list^ [release_file_count].input_file_location :=
                      jmv$kjlx_p^ [kjl_index].input_file_location;
                release_file_list^ [release_file_count].login_family :=
                      jmv$kjlx_p^ [kjl_index].login_user_identification.family;
              IFEND;
              qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
              qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_unused_entry);
            ELSE

              current_clock_time := #FREE_RUNNING_CLOCK (0);
              time_deferred_job := (current_clock_time < jmv$kjl_p^ [kjl_index].
                    earliest_clock_time_to_initiate);
              IF time_deferred_job OR jmv$kjl_p^ [kjl_index].job_deferred_by_operator OR
                    jmv$kjl_p^ [kjl_index].job_deferred_by_user THEN
                IF time_deferred_job AND (jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate <
                      jmv$time_to_ready_deferred_job) THEN
                  jmv$time_to_ready_deferred_job := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate;
                IFEND;
                find_destination_usage (jmv$kjl_p^ [kjl_index].next_destination_usage,
                      relink_application_index);
                qfp$relink_kjl_application (kjl_index, relink_application_index, jmc$kjl_application_unused);
                jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
                qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_deferred_entry);
              ELSE

{ If the file's destination usage hasn't changed - relink it into the unassigned chain
{ If the destination_usage did change, then make it available to that application

                IF jmv$kjl_p^ [kjl_index].destination_usage = jmv$kjl_p^ [kjl_index].
                      next_destination_usage THEN
                  relink_application_index := jmc$unassigned_input_index;
                ELSE
                  find_destination_usage (jmv$kjl_p^ [kjl_index].next_destination_usage,
                        relink_application_index);
                IFEND;
                qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_queued_entry);
                qfp$relink_kjl_application (kjl_index, relink_application_index, jmc$kjl_application_new);
                jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
                notify_input_application (relink_application_index, kjl_index);
              IFEND;
            IFEND;

            kjl_index := next_kjl_index;
          WHILEND /release_entries_in_state/;
        FOREND /search_all_application_states/;

{ Zero out the entry in the application table

        jmv$known_job_list.application_table [application_index].application_name := osc$null_name;
        jmv$known_job_list.application_table [application_index].destination_usage := osc$null_name;
        jmv$known_job_list.application_table [application_index].global_task_id.index := 0;
        jmv$known_job_list.application_table [application_index].global_task_id.seqno := 0;
        jmv$known_job_list.application_table [application_index].queue_file_password := osc$null_name;

      IFEND;
    FOREND /search_all_applications/;

    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$release_input_files;
?? TITLE := '[XDCL, #GATE] qfp$register_input_application', EJECT ??
*copy qfh$register_input_application

  PROCEDURE [XDCL, #GATE] qfp$register_input_application
    (    application_name: ost$name;
         destination_usage: jmt$destination_usage;
         password: ost$name;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      first_available_index: jmt$input_application_index,
      kjl_index: jmt$kjl_index,
      next_forward_link: jmt$kjl_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    first_available_index := jmc$unassigned_input_index;

  /search_for_the_application/
    FOR application_index := 1 TO UPPERBOUND (jmv$known_job_list.application_table) DO
      IF jmv$known_job_list.application_table [application_index].application_name = osc$null_name THEN
        IF first_available_index = jmc$unassigned_input_index THEN
          first_available_index := application_index;
        IFEND;

      ELSE { does the destination_usage match ??
        IF jmv$known_job_list.application_table [application_index].destination_usage = destination_usage THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$destination_usage_in_use, destination_usage,
                status);
          EXIT /search_for_the_application/;
        IFEND;
      IFEND;
    FOREND /search_for_the_application/;

    IF status.normal THEN

{ The destination_usage is not already in the table.  Is there room in the table??

      IF first_available_index = jmc$unassigned_input_index THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$application_table_is_full, '', status);
      ELSE

{ Move all input files with this destination_usage from the unassigned thread to this application thread.

        kjl_index := jmv$known_job_list.application_table [jmc$unassigned_input_index].
              state_data [jmc$kjl_application_new].first_entry;
        WHILE kjl_index <> jmc$kjl_undefined_index DO
          next_forward_link := jmv$kjl_p^ [kjl_index].application_forward_link;
          IF jmv$kjl_p^ [kjl_index].destination_usage = destination_usage THEN
            qfp$relink_kjl_application (kjl_index, first_available_index, jmc$kjl_application_new);
          IFEND;
          kjl_index := next_forward_link;
        WHILEND;

{ Initialize the entry in the table.  All files must be relinked before the table is initialized otherwise
{ the relink procedure will get confused with the destination usages.

        jmv$known_job_list.application_table [first_available_index].application_name := application_name;
        jmv$known_job_list.application_table [first_available_index].destination_usage := destination_usage;
        jmv$known_job_list.application_table [first_available_index].queue_file_password := password;
        pmp$get_executing_task_gtid (jmv$known_job_list.application_table [first_available_index].
              global_task_id);
      IFEND;
    IFEND; { status.normal
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$register_input_application;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$remove_job_from_kjl', EJECT ??
*copy qfh$remove_job_from_kjl

  PROCEDURE [XDCL, #GATE] qfp$remove_job_from_kjl
    (    system_job_name: jmt$system_supplied_name);

    VAR
      kjl_index: jmt$kjl_index;

    kjl_search (system_job_name, $jmt$kjl_entry_kind_set [jmc$kjl_terminated_entry], kjl_index);
    IF kjl_index <> jmc$kjl_undefined_index THEN
      qfp$relink_kjl_client (kjl_index, jmc$kjl_client_undefined);
      qfp$relink_kjl_server (kjl_index, jmc$kjl_server_undefined);
      qfp$relink_kjl_application (kjl_index, jmc$ve_input_application_index, jmc$kjl_application_unused);
      qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_unused_entry);
    IFEND;
  PROCEND qfp$remove_job_from_kjl;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_family_unavailable', EJECT ??
*copy qfh$set_family_unavailable

  PROCEDURE [XDCL, #GATE] qfp$set_family_unavailable;

    jmv$kjl_p^ [jmv$jcb.job_id].login_family_available := FALSE;
  PROCEND qfp$set_family_unavailable;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_input_completed', EJECT ??
*copy qfh$set_input_completed

  PROCEDURE [XDCL, #GATE] qfp$set_input_completed
    (    input_destination_usage: jmt$destination_usage;
         system_job_name: jmt$system_supplied_name;
         completed_successfully: boolean;
     VAR delete_input_file: boolean;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      current_clock_time: jmt$clock_time,
      time_deferred_job: boolean,
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    validate_application_access (input_destination_usage, application_index, status);
    IF status.normal THEN
      find_job_by_application (system_job_name, application_index, kjl_index);

      IF kjl_index <> jmc$kjl_undefined_index THEN
        delete_input_file := (jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_terminated_entry) OR
              completed_successfully;
        IF delete_input_file THEN
          qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
          qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_unused_entry);
        ELSE
          current_clock_time := #FREE_RUNNING_CLOCK (0);
          time_deferred_job := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate > current_clock_time;
          IF time_deferred_job OR jmv$kjl_p^ [kjl_index].job_deferred_by_operator OR
                jmv$kjl_p^ [kjl_index].job_deferred_by_user THEN
            IF time_deferred_job AND (jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate <
                  jmv$time_to_ready_deferred_job) THEN
              jmv$time_to_ready_deferred_job := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate;
            IFEND;
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
            jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
            qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_deferred_entry);
          ELSE

            find_destination_usage (jmv$kjl_p^ [kjl_index].next_destination_usage, application_index);
            qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_queued_entry);
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_new);
            jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
            notify_input_application (application_index, kjl_index);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$set_input_completed;
?? TITLE := '[XDCL, #GATE] qfp$set_input_initiated', EJECT ??
*copy qfh$set_input_initiated

  PROCEDURE [XDCL, #GATE] qfp$set_input_initiated
    (    input_destination_usage: jmt$destination_usage;
         system_job_name: jmt$system_supplied_name;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    validate_application_access (input_destination_usage, application_index, status);
    IF status.normal THEN

      find_job_by_application (system_job_name, application_index, kjl_index);
      IF kjl_index <> jmc$kjl_undefined_index THEN
        IF (jmv$kjl_p^ [kjl_index].application_state = jmc$kjl_application_modified) OR
              (jmv$kjl_p^ [kjl_index].application_state = jmc$kjl_application_terminated) OR
              (jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_terminated_entry) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$input_cannot_initiate, '', status);
        ELSE

          qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_initiated);
          qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_initiated_entry);
        IFEND;
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$set_input_initiated;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_interactive_jrd_jad', EJECT ??
*copy qfh$set_interactive_jrd_jad

  PROCEDURE [XDCL, #GATE] qfp$set_interactive_jrd_jad;

    IF jmv$jcb.ijle_p^.job_mode <> jmc$batch THEN
      jmv$jcb.ijle_p^.queue_file_information.job_abort_disposition :=
            jmv$kjlx_p^ [jmv$jcb.job_id].system_label_p^.job_abort_disposition;
      jmv$jcb.ijle_p^.queue_file_information.job_recovery_disposition :=
            jmv$kjlx_p^ [jmv$jcb.job_id].system_label_p^.job_recovery_disposition;
    IFEND;
  PROCEND qfp$set_interactive_jrd_jad;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_job_class_limits', EJECT ??
*copy qfh$set_job_class_limits

  PROCEDURE [XDCL, #GATE] qfp$set_job_class_limits
    (    job_class_set: jmt$job_class_set;
         class_limit_value: jmt$job_count_range);

    VAR
      job_class: jmt$job_class;

    FOR job_class := jmc$system_job_class TO jmv$maximum_job_class_in_use DO
      IF job_class IN job_class_set THEN
        jmv$job_class_table_p^ [job_class].initiation_level.preferred := class_limit_value;
      IFEND;
    FOREND;
    jmv$refresh_job_candidates := TRUE;
    jmp$set_event_and_ready_sched (jmc$examine_input_queue);
  PROCEND qfp$set_job_class_limits;
?? TITLE := '[XDCL, #GATE] qfp$set_job_restart', EJECT ??
*copyc qfh$set_job_restart

  PROCEDURE [XDCL, #GATE] qfp$set_job_restart;

    jmv$kjlx_p^ [jmv$jcb.job_id].restart_job := TRUE;
  PROCEND qfp$set_job_restart;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_terminal_name', EJECT ??
*copy qfh$set_terminal_name

  PROCEDURE [XDCL, #GATE] qfp$set_terminal_name
    (    terminal_name: ift$terminal_name);

    jmv$kjlx_p^ [jmv$jcb.job_id].terminal_name := terminal_name;
  PROCEND qfp$set_terminal_name;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$submit_job', EJECT ??
*copy qfh$submit_job

  PROCEDURE [XDCL, #GATE] qfp$submit_job
    (    system_label: jmt$job_system_label;
         job_class: jmt$job_class;
         earliest_clock_time_to_initiate: jmt$clock_time;
         latest_clock_time_to_initiate: jmt$clock_time;
         current_clock_time: jmt$clock_time;
         job_submission_time: jmt$clock_time;
         immediate_initiation_candidate: boolean;
         input_file_location: jmt$input_file_location;
         valid_mainframe_set: jmt$valid_mainframe_set;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      class_requirements_violated: boolean,
      ignore_status_p: ^ost$status,
      immediate_initiation_required: boolean,
      initiation_categories_violated: boolean,
      kjl_index: jmt$kjl_index,
      profile_mismatch: boolean,
      time_deferred_job: boolean;

    status.normal := TRUE;
    IF input_file_location <> jmc$ifl_store_and_forward_queue THEN
      immediate_initiation_required := (immediate_initiation_candidate OR
            jmv$job_class_table_p^ [job_class].immediate_initiation_candidate);
    ELSE

{ Remote jobs can never require immediate initiation.

      immediate_initiation_required := FALSE;
    IFEND;

    class_requirements_violated := FALSE;
    initiation_categories_violated := FALSE;
    IF immediate_initiation_required THEN

{ If the job requires immediate initiation and is deferred by operator request
{ then reject the request.

      IF system_label.job_deferred_by_operator THEN
        osp$set_status_condition (jme$maximum_jobs, status);
        RETURN;
      IFEND;

      class_requirements_violated := (NOT jmv$job_class_table_p^ [job_class].enable_class_initiation) OR
            ((jmv$job_counts.job_class_counts [job_class].queued_jobs + jmv$job_counts.
            job_class_counts [job_class].initiated_jobs) >= jmv$job_class_table_p^ [job_class].
            initiation_level.preferred);
      initiation_categories_violated := (system_label.job_category_set *
            jmv$job_scheduler_table.initiation_required_categories <>
            jmv$job_scheduler_table.initiation_required_categories) OR
            (system_label.job_category_set * jmv$job_scheduler_table.initiation_excluded_categories <>
            $jmt$job_category_set []);
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    IF jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry = jmc$kjl_undefined_index THEN
      qfp$expand_kjl;
    IFEND;

{ Check for room in the Known Job List (KJL).  The distribution of entries in
{ the KJL is defined as follows:
{
{    #available = MAXIMUM - qfv$current_kjl_limit + #initialized_unused_entries
{    #used_entries = MAXIMUM - #available = qfv$current_kjl_limit - #initialized_unused_entries
{
{ If the #used_entries >= jmv$maxiumum_known_jobs (logical bound) then the job cannot be
{ placed in the KJL.

    IF (qfv$current_kjl_limit - jmv$known_job_list.state_data [jmc$kjl_unused_entry].number_of_entries >=
          jmv$maximum_known_jobs) THEN
      osp$set_status_condition (jme$maximum_jobs, status);
      PUSH ignore_status_p;
      dpp$put_critical_message (jmc$input_queue_full_message, ignore_status_p^);
    ELSE

{ If the job requires immediate initiation, it must not violate the class requirements or
{ initiation categories.

      IF immediate_initiation_required AND (class_requirements_violated OR initiation_categories_violated)
            THEN
        osp$set_status_condition (jme$maximum_jobs, status);
        qfp$check_for_profile_mismatch (system_label.active_profile_version, profile_mismatch);
        IF profile_mismatch OR jmv$sched_profile_is_loading THEN
          osp$set_status_condition (jme$scheduling_profile_changed, status);
        IFEND;
      ELSE
        kjl_search (system_label.system_job_name, -$jmt$kjl_entry_kind_set [], kjl_index);
        IF kjl_index <> jmc$kjl_undefined_index THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$duplicate_name, system_label.system_job_name,
                status);
        ELSE

          kjl_index := jmv$known_job_list.state_data [jmc$kjl_unused_entry].first_entry;

          jmv$kjl_p^ [kjl_index].system_job_name := system_label.system_job_name;
          jmv$kjl_p^ [kjl_index].user_job_name := system_label.user_job_name;
          jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal.block_number := LOWERVALUE (jmt$ijl_block_number);
          jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal.block_index := LOWERVALUE (jmt$ijl_block_index);
          jmv$kjl_p^ [kjl_index].job_submission_time := job_submission_time;
          jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate := earliest_clock_time_to_initiate;
          jmv$kjl_p^ [kjl_index].job_class := job_class;
          jmv$kjl_p^ [kjl_index].job_category_set := system_label.job_category_set;
          jmv$kjl_p^ [kjl_index].job_priority := 0;
          jmv$kjl_p^ [kjl_index].job_deferred_by_operator := system_label.job_deferred_by_operator;
          jmv$kjl_p^ [kjl_index].job_deferred_by_user := system_label.job_deferred_by_user;
          jmv$kjl_p^ [kjl_index].priority_bias := 0;
          jmv$kjl_p^ [kjl_index].login_family_available := TRUE;
          jmv$kjl_p^ [kjl_index].destination_usage := system_label.job_destination_usage;
          jmv$kjl_p^ [kjl_index].next_destination_usage := system_label.job_destination_usage;
          jmv$kjl_p^ [kjl_index].application_state := jmc$kjl_application_unused;
          jmv$kjl_p^ [kjl_index].class_forward_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].class_reverse_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].client_index := jmc$kjl_client_undefined;
          jmv$kjl_p^ [kjl_index].client_forward_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].client_reverse_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].server_index := jmc$kjl_server_undefined;
          jmv$kjl_p^ [kjl_index].server_forward_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].server_reverse_link := jmc$kjl_undefined_index;
          jmv$kjl_p^ [kjl_index].server_kjl_index := kjl_index;

          jmv$kjlx_p^ [kjl_index].login_user_identification := system_label.login_user_identification;
          jmv$kjlx_p^ [kjl_index].job_controller := system_label.job_attributes.job_controller;
          jmv$kjlx_p^ [kjl_index].originating_ssn := system_label.job_attributes.originating_ssn;
          jmv$kjlx_p^ [kjl_index].latest_clock_time_to_initiate := latest_clock_time_to_initiate;
          jmv$kjlx_p^ [kjl_index].job_mode := system_label.job_mode;

{ The job monitor global task id is not set here - the job scheduler will set it when the job initiates.

          jmv$kjlx_p^ [kjl_index].output_disposition_key := system_label.job_attributes.
                output_disposition_key;
          jmv$kjlx_p^ [kjl_index].input_file_location := input_file_location;
          jmv$kjlx_p^ [kjl_index].valid_mainframe_set := valid_mainframe_set;
          jmv$kjlx_p^ [kjl_index].timesharing_job := system_label.job_attributes.
                originating_application_name = osc$timesharing;
          jmv$kjlx_p^ [kjl_index].restart_job := FALSE;
          jmv$kjlx_p^ [kjl_index].terminal_name := '';

{ Check if the scheduling profile structure has changed since the job class was selected.

          qfp$check_for_profile_mismatch (system_label.active_profile_version, profile_mismatch);
          IF profile_mismatch OR jmv$sched_profile_is_loading THEN
            osp$set_status_abnormal (jmc$job_management_id, jme$scheduling_profile_changed, '', status);
          ELSE

{ Save an interactive job's system label.

            IF system_label.job_mode = jmc$interactive_connected THEN
              ALLOCATE jmv$kjlx_p^ [kjl_index].system_label_p IN osv$mainframe_pageable_heap^;
              jmv$kjlx_p^ [kjl_index].system_label_p^ := system_label;
            ELSE
              jmv$kjlx_p^ [kjl_index].system_label_p := NIL;
            IFEND;

{ Is the job a deferred job??

            time_deferred_job := current_clock_time < earliest_clock_time_to_initiate;
            IF time_deferred_job OR system_label.job_deferred_by_operator OR
                  system_label.job_deferred_by_user THEN
              IF time_deferred_job AND (earliest_clock_time_to_initiate < jmv$time_to_ready_deferred_job) THEN
                jmv$time_to_ready_deferred_job := earliest_clock_time_to_initiate;
              IFEND;
              qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_deferred_entry);

            ELSE
              qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_queued_entry);
              find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);
              qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_new);
              notify_input_application (application_index, kjl_index);
            IFEND;

            IF input_file_location <> jmc$ifl_store_and_forward_queue THEN
              qfp$relink_kjl_server (kjl_index, jmc$kjl_server_this_mainframe);
            IFEND;

          IFEND;
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$submit_job;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$terminate_acquired_input', EJECT ??
*copy qfh$terminate_acquired_input

  PROCEDURE [XDCL, #GATE] qfp$terminate_acquired_input
    (    input_destination_usage: jmt$destination_usage;
     VAR system_job_name: jmt$system_supplied_name;
     VAR delete_input_file: boolean;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      current_clock_time: jmt$clock_time,
      kjl_index: jmt$kjl_index,
      time_deferred_job: boolean;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    validate_application_access (input_destination_usage, application_index, status);
    IF status.normal THEN

      kjl_index := jmv$known_job_list.application_table [application_index].
            state_data [jmc$kjl_application_terminated].first_entry;
      IF kjl_index <> jmc$kjl_undefined_index THEN
        system_job_name := jmv$kjl_p^ [kjl_index].system_job_name;
        delete_input_file := jmv$kjl_p^ [kjl_index].entry_kind = jmc$kjl_terminated_entry;
        IF delete_input_file THEN
          qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
          qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_unused_entry);
        ELSE
          current_clock_time := #FREE_RUNNING_CLOCK (0);
          time_deferred_job := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate > current_clock_time;
          IF time_deferred_job OR jmv$kjl_p^ [kjl_index].job_deferred_by_operator OR
                jmv$kjl_p^ [kjl_index].job_deferred_by_user THEN
            IF time_deferred_job AND (jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate <
                  jmv$time_to_ready_deferred_job) THEN
              jmv$time_to_ready_deferred_job := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate;
            IFEND;
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
            jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
            qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_deferred_entry);
          ELSE
            find_destination_usage (jmv$kjl_p^ [kjl_index].next_destination_usage, application_index);
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_new);
            jmv$kjl_p^ [kjl_index].destination_usage := jmv$kjl_p^ [kjl_index].next_destination_usage;
            notify_input_application (application_index, kjl_index);
          IFEND;
        IFEND;

      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$input_queue_is_empty, '', status);
      IFEND;

    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$terminate_acquired_input;
?? TITLE := '[XDCL, #GATE] qfp$terminate_job', EJECT ??
*copy qfh$terminate_job

  PROCEDURE [XDCL, #GATE] qfp$terminate_job
    (    system_job_name: jmt$system_supplied_name;
         job_state_set: jmt$job_state_set;
         output_disposition_key_known: boolean;
         output_disposition_key: jmt$output_disposition_keys;
         operator_job: boolean;
     VAR family_name: ost$name;
     VAR delete_input_file: boolean;
     VAR input_file_location: jmt$input_file_location;
     VAR job_assigned_to_client: boolean;
     VAR client_mainframe_id: pmt$mainframe_id;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      ignore_status: ost$status,
      earliest_clock_time_to_initiate: jmt$clock_time,
      ijle_p: ^jmt$initiated_job_list_entry,
      job_executing: boolean,
      job_name_has_changed: boolean,
      kjl_index: jmt$kjl_index,
      kjl_entry_kind_set: jmt$kjl_entry_kind_set;

    status.normal := TRUE;
    ignore_status.normal := TRUE;
    job_executing := FALSE;

    kjl_entry_kind_set := $jmt$kjl_entry_kind_set [jmc$kjl_assigned_entry];
    IF jmc$deferred_job IN job_state_set THEN
      kjl_entry_kind_set := kjl_entry_kind_set + $jmt$kjl_entry_kind_set [jmc$kjl_deferred_entry];
    IFEND;
    IF jmc$queued_job IN job_state_set THEN
      kjl_entry_kind_set := kjl_entry_kind_set + $jmt$kjl_entry_kind_set [jmc$kjl_queued_entry];
    IFEND;
    IF jmc$initiated_job IN job_state_set THEN
      kjl_entry_kind_set := kjl_entry_kind_set + $jmt$kjl_entry_kind_set [jmc$kjl_initiated_entry];
    IFEND;
    IF jmc$terminating_job IN job_state_set THEN
      kjl_entry_kind_set := kjl_entry_kind_set + $jmt$kjl_entry_kind_set [jmc$kjl_terminated_entry];
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);

    kjl_search (system_job_name, kjl_entry_kind_set, kjl_index);
    IF kjl_index = jmc$kjl_undefined_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      RETURN;
    IFEND;

    get_job_from_scheduler (kjl_index, jmc$kjl_application_terminated, job_name_has_changed);
    IF job_name_has_changed THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);
      RETURN;
    IFEND;

    job_executing := (jmv$kjl_p^ [kjl_index].entry_kind IN $jmt$kjl_entry_kind_set
          [jmc$kjl_initiated_entry, jmc$kjl_terminated_entry]) AND ve_job (kjl_index);
    delete_input_file := jmv$kjl_p^ [kjl_index].entry_kind < jmc$kjl_initiated_entry;
    earliest_clock_time_to_initiate := jmv$kjl_p^ [kjl_index].earliest_clock_time_to_initiate;
    find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);
    family_name := jmv$kjlx_p^ [kjl_index].login_user_identification.family;
    input_file_location := jmv$kjlx_p^ [kjl_index].input_file_location;
    job_assigned_to_client := jmv$kjl_p^ [kjl_index].client_index > jmc$kjl_client_this_mainframe;
    IF job_assigned_to_client THEN
      pmp$convert_binary_mainframe_id (jmv$known_job_list.client_data.
            state_data [jmv$kjl_p^ [kjl_index].client_index].mainframe_id, client_mainframe_id,
            { ignore } status);
      status.normal := TRUE;
      qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_terminated_entry);
      osp$clear_mainframe_sig_lock (qfv$kjl_lock);

    ELSE { IF NOT job_assigned_to_client THEN
      IF job_executing THEN
        IF (jmc$tja_user_kill_enabled IN qfv$terminate_job_action_set) OR
              (operator_job AND (jmc$tja_operator_kill_enabled IN qfv$terminate_job_action_set)) THEN
          pmp$set_system_flag (jmc$kill_job_flag, jmv$kjlx_p^ [kjl_index].job_monitor_global_task_id, status);
        ELSE
          pmp$set_system_flag (jmc$terminate_job_flag, jmv$kjlx_p^ [kjl_index].job_monitor_global_task_id,
                status);
        IFEND;
        qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_terminated_entry);
        qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_terminated);
        jmp$get_ijle_p (jmv$kjl_p^ [kjl_index].initiated_job_list_ordinal, ijle_p);
        IF output_disposition_key_known THEN
          jmv$kjlx_p^ [kjl_index].output_disposition_key := output_disposition_key;
        IFEND;

{ If the job is in a state that it cannot terminate, notify the requestor.
{ NOTE: The system flag is still set so should the state of the job change, it
{       will be terminated.  The following should all be "Warning" errors.

        IF (ijle_p^.entry_status = jmc$ies_system_force_out) OR
              (ijle_p^.entry_status = jmc$ies_operator_force_out) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$job_forced_out_of_memory, system_job_name,
                status);
        ELSEIF ijle_p^.entry_status = jmc$ies_job_damaged THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$job_damaged_during_recovery, system_job_name,
                status);
        ELSEIF ijle_p^.hung_task_in_job THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$job_has_a_hung_task, system_job_name, status);
        IFEND;
        osp$clear_mainframe_sig_lock (qfv$kjl_lock);

      ELSE { the job was not executing
        qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_terminated_entry);
        IF delete_input_file THEN
          find_destination_usage (jmv$kjl_p^ [kjl_index].destination_usage, application_index);
          IF jmv$kjl_p^ [kjl_index].application_state > jmc$kjl_application_new THEN
            delete_input_file := FALSE;
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_terminated);
            notify_input_application (application_index, kjl_index);
          ELSE
            IF ve_job (kjl_index) THEN
              qfp$relink_kjl_server (kjl_index, jmc$kjl_server_undefined);
            IFEND;
            qfp$relink_kjl_application (kjl_index, application_index, jmc$kjl_application_unused);
            qfp$relink_kjl_entry (kjl_index, jmv$kjl_p^ [kjl_index].job_class, jmc$kjl_unused_entry);
          IFEND;
        IFEND;
        osp$clear_mainframe_sig_lock (qfv$kjl_lock);

{ This request may reset the time_to_ready_deferred_job

        IF earliest_clock_time_to_initiate = jmv$time_to_ready_deferred_job THEN
          qfp$ready_deferred_job;
        IFEND;
      IFEND;
    IFEND;
  PROCEND qfp$terminate_job;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$validate_input_file_access', EJECT ??
*copy qfh$validate_input_file_access

  PROCEDURE [XDCL, #GATE] qfp$validate_input_file_access
    (    system_job_name: jmt$system_supplied_name;
         input_destination_usage: jmt$destination_usage;
         queue_file_password: jmt$queue_file_password;
     VAR family_name: ost$name;
     VAR status: ost$status);

    VAR
      application_index: jmt$input_application_index,
      kjl_index: jmt$kjl_index;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kjl_lock);
    find_destination_usage (input_destination_usage, application_index);
    IF application_index = jmc$unassigned_input_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$destination_usage_incorrect,
            input_destination_usage, status);
    ELSE

{ Do the passwords match??

      IF queue_file_password <> jmv$known_job_list.application_table [application_index].
            queue_file_password THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$application_not_permitted,
              input_destination_usage, status);
      ELSE

{ Search for the file in the applications initiated thread - If it isn't there, don't permit access
{ to the file.

        kjl_index := jmv$known_job_list.application_table [application_index].
              state_data [jmc$kjl_application_initiated].first_entry;
        WHILE (kjl_index <> jmc$kjl_undefined_index) AND (jmv$kjl_p^ [kjl_index].system_job_name <>
              system_job_name) DO
          kjl_index := jmv$kjl_p^ [kjl_index].application_forward_link;
        WHILEND;
        IF (kjl_index = jmc$kjl_undefined_index) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_job_name, status);
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kjl_lock);
  PROCEND qfp$validate_input_file_access;
?? OLDTITLE ??
MODEND qfm$queue_file_job_manager;
