?? NEWTITLE := 'NOS/VE Job Management : Interactive Load Leveling' ??
MODULE jmm$select_interactive_job_dest;

{ PURPOSE:
{   This module contains a procedure that chooses a mainframe from a list
{   of mainframes in a cluster, that an interactive job will be submitted to
{   for execution.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc jmc$maximum_mainframes
*copyc jmt$interactive_job_info
*copyc jmt$scheduling_attr_results
*copyc jmt$scheduling_results_keys
*copyc jmt$mainframe_leveling_data
*copyc pmt$mainframe_id
?? POP ??
*copyc jmp$cluster_get_leveling_data
*copyc mmp$create_scratch_segment
*copyc mmp$delete_scratch_segment
?? OLDTITLE ??
?? NEWTITLE := '[XDCL] jmp$select_interactive_job_dest', EJECT ??
*copy jmh$select_interactive_job_dest

  PROCEDURE [XDCL] jmp$select_interactive_job_dest
    (    valid_mainframe_list: array [1 .. * ] of pmt$mainframe_id;
         interactive_job_info: jmt$interactive_job_info;
     VAR selected_mainframe: pmt$mainframe_id;
     VAR status: ost$status);

    VAR
      data: ^SEQ ( * ),
      ignore_status: ost$status,
      job_class_name_p: ^ost$name,
      leveling_data_size: ost$segment_length,
      mainframe_index: 1 .. jmc$maximum_mainframes,
      mainframe_leveling_data_p: ^jmt$mainframe_leveling_data,
      mainframes_processed: jmt$rpc_mainframes_processed,
      max_room_in_class: real,
      number_of_data_packets: ost$non_negative_integers,
      number_of_keys_p: ^ost$non_negative_integers,
      room_in_class: real,
      send_data_p: ^SEQ ( * ),
      send_data_size: ost$segment_length,
      scheduling_attr_results_p: ^jmt$scheduling_attr_results,
      scheduling_results_keys_p: ^jmt$scheduling_results_keys,
      segment: amt$segment_pointer,
      target_mainframe_id: pmt$mainframe_id,
      valid_mainframe_index: 1 .. jmc$maximum_mainframes;


    status.normal := TRUE;

    mmp$create_scratch_segment (amc$sequence_pointer, mmc$as_sequential,
          segment, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    RESET segment.sequence_pointer;

    send_data_size := #SIZE (ost$name) + #SIZE (ost$non_negative_integers) +
          (5 * #SIZE (jmt$scheduling_attribute_keys));
    PUSH send_data_p: [[REP send_data_size OF cell]];

    RESET send_data_p;
    NEXT job_class_name_p IN send_data_p;
    job_class_name_p^ := interactive_job_info.assigned_job_class;
    NEXT number_of_keys_p IN send_data_p;
    number_of_keys_p^ := 5;
    NEXT scheduling_results_keys_p: [1 .. 5] IN send_data_p;
    scheduling_results_keys_p^ [1] := jmc$sak_active_jobs;
    scheduling_results_keys_p^ [2] := jmc$sak_enable_job_leveling;
    scheduling_results_keys_p^ [3] := jmc$sak_maximum_active_jobs;
    scheduling_results_keys_p^ [4] := jmc$sak_queued_jobs;
    scheduling_results_keys_p^ [5] := jmc$sak_swapped_jobs;

    leveling_data_size := #SIZE (jmt$mainframe_leveling_data) +
          (UPPERBOUND (scheduling_results_keys_p^) *
          #SIZE (jmt$scheduling_attr_result));

{ Call all mainframes in the cluster.

    target_mainframe_id := pmc$null_mainframe_id;

    jmp$cluster_get_leveling_data (target_mainframe_id, send_data_p,
          leveling_data_size, segment.sequence_pointer, mainframes_processed,
          number_of_data_packets, status);
    IF status.normal THEN
      max_room_in_class := 0.0;
      selected_mainframe := pmc$null_mainframe_id;

      RESET segment.sequence_pointer;
      FOR mainframe_index := 1 TO number_of_data_packets DO
        NEXT mainframe_leveling_data_p IN segment.sequence_pointer;
        NEXT data: [[REP mainframe_leveling_data_p^.mainframe_data_size OF
              cell]] IN segment.sequence_pointer;
        RESET data;
        NEXT scheduling_attr_results_p: [1 .. 5] IN data;

      /find_mainframe_in_list/
        FOR valid_mainframe_index := 1 TO UPPERBOUND (valid_mainframe_list) DO
          IF valid_mainframe_list [valid_mainframe_index] =
                mainframe_leveling_data_p^.mainframe_id THEN
            IF scheduling_attr_results_p^ [2].enable_job_leveling THEN

              room_in_class := $REAL (scheduling_attr_results_p^ [3].
                    maximum_active_jobs - scheduling_attr_results_p^ [1].
                    active_jobs - scheduling_attr_results_p^ [4].queued_jobs -
                    scheduling_attr_results_p^ [5].swapped_jobs) /
                    $REAL (scheduling_attr_results_p^ [3].maximum_active_jobs);

              IF room_in_class > max_room_in_class THEN
                max_room_in_class := room_in_class;
                selected_mainframe := valid_mainframe_list
                      [valid_mainframe_index];
              IFEND;
            IFEND;
            EXIT /find_mainframe_in_list/;
          IFEND;
        FOREND /find_mainframe_in_list/;
      FOREND;
    IFEND;

    mmp$delete_scratch_segment (segment, ignore_status);

  PROCEND jmp$select_interactive_job_dest;
?? OLDTITLE ??

MODEND jmm$select_interactive_job_dest;
