?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Resource Management : Mount a tape volume and assign element to the job' ??
MODULE rmm$manage_client_volumes_223;

?? NEWTITLE := 'Global Variables Declared by This Module', EJECT ??

  CONST
    expected_tape_scan_time = 2 {seconds},
    five_minutes = 5 * one_minute,
    five_seconds = 5 * one_second,
    microseconds_per_millisecond = 1000,
    microseconds_per_second = 1000 * microseconds_per_millisecond,
    one_minute = 60 * one_second,
    one_second = 1000 {milliseconds};

  TYPE
    retry_status_info = record
      case retry_in_progress: boolean of
      = TRUE =
        next_request {after limit exceeded} : rmt$rbt_request_type,
        retry_count: ost$positive_integers,
        retry_delay_interval: ost$non_negative_integers,
        retry_limit: ost$positive_integers,
        server_event_code: ost$non_negative_integers,
      = FALSE =
        ,
      casend,
    recend;

  VAR
    requested_density: rmt$density,
    requested_evsn: rmt$external_vsn,
    request_submitted: boolean;

?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cme$manage_interface_tables
*copyc cmt$element_states
*copyc dme$tape_errors
*copyc dmt$job_tape_table
*copyc dmt$resrel_tape_request
*copyc dmt$tape_job_lun_table
*copyc iot$logical_unit
*copyc iot$operator_assignment_type
*copyc osd$integer_limits
*copyc oss$job_pageable
*copyc oss$job_paged_literal
*copyc rmc$extend_labeled_vol_list
*copyc rmc$extend_unlabeled_vol_list
*copyc rmc$robotic_element_monopoly
*copyc rme$condition_codes
*copyc rmt$density
?? POP ??
*copyc clp$evaluate_sub_parameters
*copyc clp$get_date_time_string
*copyc clp$get_value
*copyc clp$pop_parameters
*copyc clp$push_parameters
*copyc clp$scan_parameter_list
*copyc clp$trimmed_string_size
*copyc cmv$logical_unit_table
*copyc dmv$initialize_tape_volume
*copyc rmp$clear_explicit_reserve
*copyc rmp$set_explicit_reserve
*copyc rmv$job_tape_table_lock
*copyc rmv$job_tape_table_p
*copyc dmv$tape_job_lun_table_p
*copyc ifp$invoke_pause_utility
*copyc iop$client_cancel_request
*copyc iop$client_delete_request
*copyc iop$client_get_response
*copyc iop$client_put_request
*copyc iop$extend_volume_list_in_rvl
*copyc iop$get_server_entry
*copyc iop$queue_volume_assignment
*copyc iop$record_robotic_assignment
*copyc iop$recovery_rel_assign_in_rvl
*copyc iop$release_assignment_in_rvl
*copyc iop$request_assignment_in_rvl
*copyc iop$select_best_element
*copyc iop$validate_candidate_element
*copyc ofp$clear_operator_message
*copyc ofp$display_status_message
*copyc ofp$format_operator_menu
*copyc ofp$format_operator_message
*copyc ofp$process_operator_menu
*copyc ofp$send_formatted_operator_msg
*copyc osp$append_status_parameter
*copyc osp$begin_subsystem_activity
*copyc osp$clear_job_signature_lock
*copyc osp$clear_wait_message
*copyc osp$copy_local_status_to_status
*copyc osp$disestablish_cond_handler
*copyc osp$end_subsystem_activity
*copyc osp$establish_condition_handler
*copyc osp$format_message
*copyc osp$get_current_display_message
*copyc osp$set_job_signature_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$status_message_text
*copyc osp$test_signature_lock
*copyc osp$translate_bytes
*copyc osv$lower_to_upper
*copyc pmp$continue_to_cause
*copyc pmp$get_job_names
*copyc pmp$long_term_wait
*copyc pmp$wait
*copyc rmp$assign_tape_unit
*copyc rmp$emit_operator_message
*copyc rmp$get_selected_element
*copyc rmp$log_debug_integer
*copyc rmp$log_debug_message
*copyc rmp$log_debug_status
*copyc rmp$put_job_status_display
*copyc rmp$release_tape_unit
*copyc rmp$validate_ansi_string
*copyc rmv$densities
*copyc tmp$ready_system_task1

?? OLDTITLE ??
?? NEWTITLE := 'rmp$activate_volume', EJECT ??

{ PURPOSE:
{    The purpose of this procedure is to mount a magnetic tape volume on a tape element
{    and to assign the tape element to the requesting job.
{ DESIGN:
{    It is not known ahead of time whether or not the volume must be mounted manually
{    by an operator or may be robotically mounted.  Therefore, we first determine
{    if it can be mounted robotically.  Failing that, we announce the tape mount
{    request to the Removable Media Operator.
{
{    If the volume is robotically mounted, we know exactly which tape element it was
{    mounted on.  If it must be manually mounted, we must wait for the operator to
{    place the reel on the tape unit (mount it) and then the tape element must be
{    discovered by automatic volume recognition (labeled volume only) or it must be
{    identified explicitly by an operator (via the ASSIGN_DEVICE command).  While the
{    ASSIGN_DEVICE command is usually used for unlabeled volumes, it may also be
{    required for a labeled volume in the situation where the system finds two
{    requests identifying the same RECORDED_VSN and different EXTERNAL_VSNs.  In this
{    latter case, we ask the operator to sort this out via ASSIGN_DEVICE.  This case
{    is detected within this procedure.
{
{    It is possible to recover an active job that has yet to assign a tape element to
{    itself.  When job recovery is detected we need to start all over, i.e. get the
{    volume mounted again and proceed to assign the element to the job.  The block
{    exit condition handler is responsible for cleanup (i.e. rolling back whatever
{    may have been accomplished within this procedure).
{

  PROCEDURE [XDCL] rmp$activate_volume
    (    sfid: gft$system_file_identifier;
         acceptable_states: cmt$element_states;
         last_choice_element: cmt$element_name;
         required_element: cmt$element_name;
     VAR status: ost$status);

    VAR
      assigned_count_incremented: boolean,
      current_date_time_string: ost$string,
      element_assigned: boolean,
      message_parameters: array [1 .. 2] of ^ost$message_parameter,
      original_message: oft$display_message;

?? OLDTITLE ??
?? NEWTITLE := '  activate_volume_handler', EJECT ??

    PROCEDURE activate_volume_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR condition_status: ost$status);

      VAR
        clear_implicit_reserve: boolean,
        density: rmt$supported_tape_densities,
        debug_status: ost$status,
        ignore_status: ost$status,
        lock_status: ost$signature_lock_status,
        reservation: rmt$tape_reservation,
        wait_message_displayed: boolean;

      rmp$log_debug_message (' Entering activate_volume_handler');
      osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, debug_status,
            ignore_status);
      rmp$log_debug_status (debug_status);
      CASE condition.selector OF

      = pmc$block_exit_processing =

        wait_message_displayed := TRUE;
        ofp$clear_operator_message (ofc$removable_media_operator, ignore_status);
        osp$clear_wait_message (original_message, wait_message_displayed);

        osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
        IF lock_status = osc$sls_locked_by_current_task THEN
          osp$end_subsystem_activity;
          osp$clear_job_signature_lock (rmv$job_tape_table_lock);
        IFEND;
        IF element_assigned THEN
          rmp$deactivate_volume (sfid, {delete_request_from_vsn_queue} TRUE, ignore_status);
        ELSEIF assigned_count_incremented THEN
          IF rmv$job_tape_table_p <> NIL THEN
            IF lock_status <> osc$sls_locked_by_another_task THEN
              osp$begin_subsystem_activity;
              osp$set_job_signature_lock (rmv$job_tape_table_lock);
              IF rmv$job_tape_table_p^.assigned_unit_count [requested_density] > 0 THEN
                rmv$job_tape_table_p^.assigned_unit_count [requested_density] :=
                      rmv$job_tape_table_p^.assigned_unit_count [requested_density] - 1;
              IFEND;
              osp$clear_job_signature_lock (rmv$job_tape_table_lock);
              osp$end_subsystem_activity;
            IFEND;
          IFEND;
        IFEND;

      = ifc$interactive_condition =
        CASE condition.interactive_condition OF
        = ifc$terminate_break =
          osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                ignore_status);
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          EXIT rmp$activate_volume;
        = ifc$pause_break, ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;

      = pmc$user_defined_condition =

        IF condition.user_condition_name = osc$job_recovery_condition_name THEN
          IF NOT dmv$initialize_tape_volume.in_progress THEN
            IF (rmv$job_tape_table_p <> NIL) AND rmv$job_tape_table_p^.job_recovery_active THEN
              osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
              IF lock_status = osc$sls_locked_by_current_task THEN
                osp$end_subsystem_activity;
                osp$clear_job_signature_lock (rmv$job_tape_table_lock);
              IFEND;
              IF rmv$job_tape_table_p^.explicit_reservation THEN
                { Must reclaim explicit reserves
                FOR density := rmc$800 TO rmc$maximum_density DO
                  reservation [density] := rmv$job_tape_table_p^.reserved_unit_count [density];
                FOREND;
                rmp$set_explicit_reserve (reservation, status);
              IFEND;
              osp$begin_subsystem_activity;
              osp$set_job_signature_lock (rmv$job_tape_table_lock);
              rmv$job_tape_table_p^.job_recovery_active := FALSE;
              osp$clear_job_signature_lock (rmv$job_tape_table_lock);
              osp$end_subsystem_activity;
            IFEND;
          IFEND;
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          osp$set_status_condition (dme$operator_reassign, status);
          EXIT rmp$activate_volume;
        IFEND;
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);

      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;
      rmp$log_debug_message (' Exiting activate_volume_handler');

    PROCEND activate_volume_handler;

?? OLDTITLE ??
?? NEWTITLE := '  attempt_manual_mount', EJECT ??

    PROCEDURE attempt_manual_mount
      (    sfid: gft$system_file_identifier;
       VAR selected_element: cmt$element_name;
       VAR volume_mounted: boolean;
       VAR status: ost$status);

?? NEWTITLE := '    manual_condition_handler', EJECT ??

      PROCEDURE manual_condition_handler
        (    condition: pmt$condition;
             p_condition_info: ^pmt$condition_information;
             save_area: ^ost$stack_frame_save_area;
         VAR condition_status: ost$status);

        VAR
          debug_status: ost$status,
          release_status: ost$status;

        rmp$log_debug_message (' Entering manual_condition_handler');
        osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, debug_status,
              ignore_status);
        rmp$log_debug_status (debug_status);
        CASE condition.selector OF
        = pmc$block_exit_processing =
          IF assigned_in_rvl THEN
            debug_message_logged := FALSE;
            REPEAT
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Calling iop$release_assignment_in_rvl');
              IFEND;
              iop$release_assignment_in_rvl (sfid, release_status);
              IF NOT release_status.normal AND (release_status.condition = dme$unable_to_lock_tape_table) THEN
                IF NOT debug_message_logged THEN
                  rmp$log_debug_message (' Waiting for tape table lock');
                  debug_message_logged := TRUE;
                IFEND;
                pmp$wait (one_second, one_second);
              IFEND;
            UNTIL release_status.normal OR (release_status.condition <> dme$unable_to_lock_tape_table);
            assigned_in_rvl := NOT release_status.normal;
            #SPOIL (assigned_in_rvl);
          IFEND;

        = ifc$interactive_condition =
          CASE condition.interactive_condition OF
          = ifc$pause_break, ifc$job_reconnect =
            ifp$invoke_pause_utility (ignore_status);
          = ifc$terminate_break =
            pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
            osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                  ignore_status);
            EXIT attempt_manual_mount;
          ELSE
            pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          CASEND;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;
        rmp$log_debug_message (' Exiting manual_condition_handler');

      PROCEND manual_condition_handler;
?? OLDTITLE ??
?? EJECT ??

      VAR
        assigned_in_rvl: boolean,
        ignore_status: ost$status,
        job_lun_table_entry: ^dmt$tape_lun_table_entry,
        message_name: clt$parameter_name,
        tape_unit_available: boolean,
        release_status: ost$status,
        requested_evsn: rmt$external_vsn,
        requested_rvsn: rmt$recorded_vsn;

      rmp$log_debug_message (' Entering attempt_manual_mount');
      job_lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry^.
            volume_list^ [job_lun_table_entry^.current_vsn_index].external_vsn, requested_evsn);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry^.
            volume_list^ [job_lun_table_entry^.current_vsn_index].recorded_vsn, requested_rvsn);
      requested_density := job_lun_table_entry^.density;
      assigned_in_rvl := FALSE;
      #SPOIL (assigned_in_rvl);

      osp$establish_condition_handler (^manual_condition_handler, {handle_block_exit} TRUE);
      rmp$log_debug_message (' Calling rmp$get_selected_element - 1st try');
      rmp$get_selected_element (sfid, requested_evsn, requested_rvsn, requested_density, selected_element,
            status);
      rmp$log_debug_status (status);
      IF status.normal THEN
        volume_mounted := status.normal;
      ELSEIF (status.condition = rme$volume_not_mounted) OR
            (status.condition = rme$tape_unit_available) THEN
        rmp$log_debug_message (' Readying scanner');
        tmp$ready_system_task (tmc$stid_tape_scanner, ignore_status);
        wait (expected_tape_scan_time * one_second);
        rmp$get_selected_element (sfid, requested_evsn, requested_rvsn, requested_density, selected_element,
              status);
        rmp$log_debug_status (status);
        IF status.normal THEN
          rmp$log_debug_message (' Scanner found volume');
          volume_mounted := status.normal;
        ELSEIF (status.condition = rme$volume_not_mounted) OR
              (status.condition = rme$tape_unit_available) THEN
          debug_message_logged := FALSE;
          tape_unit_available := NOT (status.condition = rme$tape_unit_available);
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$request_assignment_in_rvl');
            IFEND;
            iop$request_assignment_in_rvl (sfid, requested_density, requested_evsn, requested_rvsn, status);
            IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              pmp$long_term_wait (one_second, one_second);
            IFEND;
          UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          rmp$log_debug_status (status);
          assigned_in_rvl := status.normal;
          #SPOIL (assigned_in_rvl);
          IF status.normal THEN
            tmp$ready_system_task (tmc$stid_tape_scanner, ignore_status);
            IF tape_unit_available THEN
              message_name := 'WAIT_MANUAL_MOUNT';
            ELSE
              message_name := 'WAIT_TAPE_UNIT';
            IFEND;
            message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
            message_parameters [2] := ^requested_evsn;
            rmp$put_job_status_display (message_name, ^message_parameters);
            rmp$log_debug_message (' Waiting for operator action or robotic server definition');
            wait (five_minutes); {Wait for ASSD, TERTA, scanner, or robotic server definition to ready task}
            rmp$log_debug_message (' Calling rmp$get_selected_element - after wait');
            rmp$get_selected_element (sfid, requested_evsn, requested_rvsn, requested_density,
                  selected_element, status);
            rmp$log_debug_status (status);
            volume_mounted := status.normal;
            IF (NOT status.normal) AND ((status.condition = rme$volume_not_mounted) OR
                  (status.condition = rme$tape_unit_available)) THEN
              status.normal := TRUE;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      IF (NOT status.normal) THEN
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling iop$release_assignment_in_rvl');
          IFEND;
          iop$release_assignment_in_rvl (sfid, release_status);
          IF NOT release_status.normal AND (release_status.condition = dme$unable_to_lock_tape_table) THEN
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Waiting for tape table lock');
              debug_message_logged := TRUE;
            IFEND;
            pmp$wait (one_second, one_second);
          IFEND;
        UNTIL release_status.normal OR (release_status.condition <> dme$unable_to_lock_tape_table);
        rmp$log_debug_status (release_status);
        assigned_in_rvl := NOT release_status.normal;
        #SPOIL (assigned_in_rvl);
      IFEND;
      osp$disestablish_cond_handler;
    PROCEND attempt_manual_mount;
?? OLDTITLE ??
?? NEWTITLE := '  attempt_robotic_mount ', EJECT ??

    PROCEDURE attempt_robotic_mount
      (    sfid: gft$system_file_identifier;
           acceptable_states: cmt$element_states;
           last_choice_element: cmt$element_name;
           required_element: cmt$element_name;
       VAR assigned_mainframe_lun: iot$logical_unit;
       VAR selected_element: cmt$element_name;
       VAR status: ost$status);

      VAR
        server_name: ost$name;

?? NEWTITLE := '    robotic_mount_handler', EJECT ??

      PROCEDURE robotic_mount_handler
        (    condition: pmt$condition;
             p_condition_info: ^pmt$condition_information;
             save_area: ^ost$stack_frame_save_area;
         VAR condition_status: ost$status);

        VAR
          cancel_status: ost$status,
          debug_status: ost$status,
          ignore_status: ost$status;

?? NEWTITLE := '  robotic_mount_lock_handler  ', EJECT ??

      PROCEDURE robotic_mount_lock_handler
        (    condition: pmt$condition;
             p_condition_info: ^pmt$condition_information;
             save_area: ^ost$stack_frame_save_area;
         VAR condition_status: ost$status);

        VAR
          ignore_status: ost$status;

        CASE condition.selector OF
        = ifc$interactive_condition =
          CASE condition.interactive_condition OF
          = ifc$pause_break, ifc$job_reconnect =
            ifp$invoke_pause_utility (ignore_status);
          = ifc$terminate_break =
            pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
            osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                  ignore_status);
            EXIT attempt_robotic_mount;
          ELSE
            pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          CASEND;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;

      PROCEND robotic_mount_lock_handler;
?? OLDTITLE ??

        rmp$log_debug_message (' Entering robotic_mount_handler');
        osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, debug_status,
              ignore_status);
        rmp$log_debug_status (debug_status);

        CASE condition.selector OF
        = pmc$block_exit_processing =

          IF request_submitted THEN
            debug_message_logged := FALSE;
            REPEAT
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Calling iop$client_cancel_request');
              IFEND;
              iop$client_cancel_request (server_name, sfid, cancel_status);
              IF NOT cancel_status.normal AND (cancel_status.condition = dme$unable_to_lock_tape_table) THEN
                IF NOT debug_message_logged THEN
                  rmp$log_debug_message (' Waiting for tape table lock');
                  debug_message_logged := TRUE;
                IFEND;
                osp$establish_condition_handler (^robotic_mount_lock_handler, {handle block exit} FALSE);
                pmp$long_term_wait (one_second, one_second);
                osp$disestablish_cond_handler;
              IFEND;
            UNTIL cancel_status.normal OR (cancel_status.condition <> dme$unable_to_lock_tape_table);
            rmp$log_debug_message ('Called iop$client_cancel_request');
            rmp$log_debug_status (cancel_status);
          IFEND;

          release_element_from_job (sfid, {delete_request_from_vsn_queue} FALSE, assigned_mainframe_lun,
                ignore_status);

        = ifc$interactive_condition =
          CASE condition.interactive_condition OF
          = ifc$terminate_break =
            pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
            osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                  ignore_status);
            EXIT attempt_robotic_mount;
          = ifc$pause_break, ifc$job_reconnect =
            ifp$invoke_pause_utility (ignore_status);
          ELSE
            pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          CASEND;

        = pmc$user_defined_condition =
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          IF condition.user_condition_name = osc$job_recovery_condition_name THEN
            EXIT attempt_robotic_mount;
          IFEND;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;
        rmp$log_debug_message (' Exiting robotic_mount_handler');

      PROCEND robotic_mount_handler;
?? OLDTITLE ??
?? EJECT ??

      VAR
        elapsed_time: integer,
        element: cmt$element_name,
        external_vsn: rmt$external_vsn,
        ignore_assigned_mainframe_lun: iot$logical_unit,
        ignored_element: cmt$element_name,
        ignore_status: ost$status,
        initial_tasks: rmt$rbt_supported_requests,
        job_lun_table_entry: ^dmt$tape_lun_table_entry,
        last_sync_error: rmt$rbt_supported_requests,
        message_name: clt$parameter_name,
        remaining_tasks: rmt$rbt_supported_requests,
        request: rmt$rbt_request,
        required_requests: rmt$rbt_supported_requests,
        retry_status: retry_status_info,
        server_entry: iot$robotic_server_entry,
        server_index: iot$robotic_server_index,
        start_time: integer,
        valid_request_transitions: rmt$rbt_supported_requests;

      start_time := #FREE_RUNNING_CLOCK (0);
      assigned_mainframe_lun := 0;

      initial_tasks := $rmt$rbt_supported_requests [rmc$rbt_query, rmc$rbt_mount];

      job_lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];

      last_sync_error := $rmt$rbt_supported_requests [];

      remaining_tasks := initial_tasks;

      request_submitted := FALSE;

      requested_density := job_lun_table_entry^.density;

      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry^.
            volume_list^ [job_lun_table_entry^.current_vsn_index].external_vsn, requested_evsn);

      required_requests := $rmt$rbt_supported_requests [rmc$rbt_force_dismount, rmc$rbt_dismount,
            rmc$rbt_mount, rmc$rbt_query];

      retry_status.retry_in_progress := FALSE;

      valid_request_transitions := $rmt$rbt_supported_requests
            [rmc$rbt_force_dismount, rmc$rbt_mount, rmc$rbt_query];

?? EJECT ??
      #SPOIL (assigned_mainframe_lun, request_submitted);
      osp$establish_condition_handler (^robotic_mount_handler, {handle block exit} TRUE);
      osp$set_job_signature_lock (rmv$job_tape_table_lock);
      osp$begin_subsystem_activity;

    /robotic_mount/
      BEGIN

      /locate_server/
        FOR server_index := 1 TO ioc$max_server_index DO
          debug_message_logged := FALSE;
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$get_server_entry');
            IFEND;
            iop$get_server_entry (server_index, server_entry, status);
            IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              pmp$long_term_wait (one_second, one_second);
            IFEND;
          UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IF status.normal AND (required_requests <= server_entry.server_attributes.supported_requests) AND
                (requested_density IN server_entry.managed_densities) THEN
            server_name := server_entry.server_name;
            #SPOIL (server_name);
            REPEAT
              IF status.normal AND (remaining_tasks = $rmt$rbt_supported_requests []) THEN
                EXIT /robotic_mount/;
              ELSEIF rmc$rbt_force_dismount IN remaining_tasks THEN
                IF assigned_mainframe_lun <> 0 THEN
                  request.request_type := rmc$rbt_force_dismount;
                  request.force_dismount.element := selected_element;
                  message_name := 'WAIT_FOR_FORCE';
                  message_parameters [1] := ^selected_element;
                  rmp$log_debug_message (' Issuing force dismount');
                  process_request ({ignore acceptable_states} $cmt$element_states [], initial_tasks,
                        {last_choice_element} osc$null_name, message_name, current_date_time_string, request,
                        {required_element} osc$null_name, server_name, server_entry.server_attributes.timeout,
                        sfid, valid_request_transitions, message_parameters, ignore_assigned_mainframe_lun,
                        remaining_tasks, retry_status, ignored_element, status);
                  IF status.normal THEN
                    rmp$log_debug_message (' Calling cmp$release_tape_unit after force_dismount');
                    release_element_from_job (sfid, {delete_request_from_vsn_queue} FALSE,
                          assigned_mainframe_lun, ignore_status);
                    remaining_tasks := remaining_tasks + $rmt$rbt_supported_requests [rmc$rbt_query];
                  IFEND;
                  check_synchronization (request.request_type, last_sync_error, status);
                ELSE {unit that is object of force dismount is not assigned to the job}
                  remaining_tasks := remaining_tasks - $rmt$rbt_supported_requests [rmc$rbt_force_dismount];
                IFEND;
              ELSEIF rmc$rbt_query IN remaining_tasks THEN
                release_element_from_job (sfid, {delete_request_from_vsn_queue} FALSE, assigned_mainframe_lun,
                      ignore_status);
                rmp$log_debug_message (' Issuing query');
                request.request_type := rmc$rbt_query;
                request.query.external_vsn := requested_evsn;
                message_name := 'WAIT_FOR_QUERY';
                message_parameters [1] := ^requested_evsn;
                process_request (acceptable_states, initial_tasks, last_choice_element, message_name,
                      current_date_time_string, request, required_element, server_name,
                      server_entry.server_attributes.timeout, sfid, valid_request_transitions,
                      message_parameters, assigned_mainframe_lun, remaining_tasks, retry_status,
                      selected_element, status);
                check_synchronization (request.request_type, last_sync_error, status);
              ELSEIF rmc$rbt_mount IN remaining_tasks THEN
                IF assigned_mainframe_lun = 0 THEN
                  rmp$log_debug_message (' Selecting element in mount without preceding query');
                  select_element (acceptable_states, sfid, last_choice_element,
                        server_entry.managed_elements_p, {remaining_candidates} NIL, required_element,
                        current_date_time_string, message_parameters, assigned_mainframe_lun,
                        selected_element, status);
                IFEND;
                IF status.normal THEN
                  request.request_type := rmc$rbt_mount;
                  request.mount.element := selected_element;
                  request.mount.external_vsn := requested_evsn;
                  message_name := 'WAIT_FOR_MOUNT';
                  message_parameters [1] := ^requested_evsn;
                  message_parameters [2] := ^selected_element;
                  rmp$log_debug_message (' Issuing mount');
                  process_request ({ignore acceptable_states} $cmt$element_states [], initial_tasks,
                        {last_choice_element} osc$null_name, message_name, current_date_time_string, request,
                        {required_element} osc$null_name, server_name, server_entry.server_attributes.timeout,
                        sfid, valid_request_transitions, message_parameters, ignore_assigned_mainframe_lun,
                        remaining_tasks, retry_status, ignored_element, status);
                  check_synchronization (request.request_type, last_sync_error, status);
                IFEND;
              IFEND;
            UNTIL NOT status.normal;
          IFEND;
          IF (NOT status.normal) THEN
            CASE status.condition OF
            = dme$tape_unit_down, dme$tape_unit_off, dme$unit_assigned, rme$element_not_available =
              IF (required_element <> osc$null_name) THEN
                EXIT /robotic_mount/;
              IFEND;
            = rme$invalid_server_index =
              EXIT /locate_server/;
            = rme$volume_not_mounted, rme$synchronization_error, rme$server_not_defined =
              {try next server} ;
            ELSE
              EXIT /robotic_mount/;
            CASEND;
          IFEND;
        FOREND /locate_server/;
        osp$set_status_condition (rme$volume_not_mounted, status);
      END /robotic_mount/;

      IF status.normal THEN
        job_lun_table_entry^.robotic_mount_info.volume_robotically_mounted := TRUE;
        job_lun_table_entry^.robotic_mount_info.element := selected_element;
        job_lun_table_entry^.robotic_mount_info.server_name := server_name;
        rmp$log_debug_message (' Exiting attempt_robotic_mount with normal status');
        elapsed_time := #FREE_RUNNING_CLOCK (0) - start_time;
        rmp$log_debug_integer (' MOUNT COMPLETE; ELAPSED TIME (secs) = ',
              elapsed_time DIV microseconds_per_second);
      ELSE
        release_element_from_job (sfid, {delete_request_from_vsn_queue} FALSE, assigned_mainframe_lun,
              ignore_status);
        rmp$log_debug_message (' Exiting attempt_robotic_mount with abnormal status');
        rmp$log_debug_status (status);
      IFEND;
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;

    PROCEND attempt_robotic_mount;

?? OLDTITLE ??
?? NEWTITLE := '  select_volume', EJECT ??

    PROCEDURE select_volume
      (    sfid: gft$system_file_identifier;
       VAR job_lun_table_entry {input/output} : dmt$tape_lun_table_entry;
       VAR requested_evsn: rmt$external_vsn;
       VAR requested_rvsn: rmt$recorded_vsn;
       VAR requested_volume_attributes: iot$requested_volume_attributes;
       VAR status: ost$status);

?? NEWTITLE := '    operator_menu_for_scratch_tape', EJECT ??

      PROCEDURE operator_menu_for_scratch_tape
        (    label_type: amt$label_type;
             requested_volume_attributes: iot$requested_volume_attributes;
             density: rmt$density;
             previous_evsn: rmt$external_vsn;
             previous_rvsn: rmt$external_vsn;
         VAR evsn: rmt$external_vsn;
         VAR rvsn: rmt$recorded_vsn;
         VAR status: ost$status);

{  PROCEDURE scratch_menu (
{    external_vsn, evsn: any of
{        name 1..6
{        string 1..6
{      anyend = $optional
{    recorded_vsn, rvsn: any of
{        name 1..6
{        string 1..6
{      anyend = $optional
{    )

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 4] of clt$pdt_parameter_name,
      parameters: array [1 .. 2] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$union_type_qualifier,
        type_size_1: clt$type_specification_size,
        element_type_spec_1: record
          header: clt$type_specification_header,
          qualifier: clt$name_type_qualifier,
        recend,
        type_size_2: clt$type_specification_size,
        element_type_spec_2: record
          header: clt$type_specification_header,
          qualifier: clt$string_type_qualifier,
        recend,
      recend,
      type2: record
        header: clt$type_specification_header,
        qualifier: clt$union_type_qualifier,
        type_size_1: clt$type_specification_size,
        element_type_spec_1: record
          header: clt$type_specification_header,
          qualifier: clt$name_type_qualifier,
        recend,
        type_size_2: clt$type_specification_size,
        element_type_spec_2: record
          header: clt$type_specification_header,
          qualifier: clt$string_type_qualifier,
        recend,
      recend,
    recend := [
    [1,
    [90, 5, 10, 12, 36, 17, 884],
    clc$command, 4, 2, 0, 0, 0, 0, 0, ''], [
    ['EVSN                           ',clc$abbreviation_entry, 1],
    ['EXTERNAL_VSN                   ',clc$nominal_entry, 1],
    ['RECORDED_VSN                   ',clc$nominal_entry, 2],
    ['RVSN                           ',clc$abbreviation_entry, 2]],
    [
{ PARAMETER 1
    [2, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation,
  clc$standard_parameter_checking, 33, clc$optional_parameter, 0, 0],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation,
  clc$standard_parameter_checking, 33, clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$union_type], [[clc$name_type, clc$string_type],
    FALSE, 2],
    5, [[1, 0, clc$name_type], [1, 6]],
    8, [[1, 0, clc$string_type], [1, 6, FALSE]]
    ],
{ PARAMETER 2
    [[1, 0, clc$union_type], [[clc$name_type, clc$string_type],
    FALSE, 2],
    5, [[1, 0, clc$name_type], [1, 6]],
    8, [[1, 0, clc$string_type], [1, 6, FALSE]]
    ]];

?? FMT (FORMAT := ON) ??
?? POP ??

        CONST
          p$external_vsn = 1,
          p$recorded_vsn = 2;

        VAR
          pvt: array [1 .. 2] of clt$parameter_value;

        CONST
          number_of_choices = 2;

        VAR
          i: integer,
          ignore_length: integer,
          local_status: ost$status,
          message_parameters: array [1 .. 7] of ^ost$message_parameter,
          parameter_names: ^ost$parameter_help_names,
          reason: string (24),
          response: oft$number_of_choices,
          response_string: ost$string,
          seed_name: pmt$program_name,
          status_line: string (80),
          terminate_reason: string (osc$max_string_size),
          work_area: ^SEQ ( * ),
          work_area_size: ost$positive_integers;

        status.normal := TRUE;
        local_status.normal := TRUE;

        IF label_type = amc$labelled THEN
          seed_name := rmc$extend_labeled_vol_list;
        ELSE
          seed_name := rmc$extend_unlabeled_vol_list;
        IFEND;

        FOR i := 1 TO 7 DO
          message_parameters [i] := NIL;
        FOREND;

        IF requested_volume_attributes.removable_media_group <> osc$null_name THEN
          message_parameters [1] := ^requested_volume_attributes.removable_media_group;
        IFEND;

        IF requested_volume_attributes.removable_media_location <> osc$null_name THEN
          message_parameters [2] := ^requested_volume_attributes.removable_media_location;
        IFEND;

        message_parameters [3] := ^rmv$densities [density];
        message_parameters [4] := ^requested_volume_attributes.family;
        message_parameters [5] := ^requested_volume_attributes.user;
        message_parameters [6] := ^previous_evsn;
        message_parameters [7] := ^previous_rvsn;

        PUSH parameter_names: [1 .. number_of_choices];
        parameter_names^ [1] := 'CONTINUE_REQUEST';
        parameter_names^ [2] := 'TERMINATE_REQUEST';

        work_area := NIL;

      /display_menu/
        WHILE TRUE DO
          ofp$format_operator_menu (seed_name, parameter_names, ^message_parameters,
                number_of_choices, ofc$removable_media_operator, response, response_string, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;

          IF (response = 1) THEN { operator wants to mount a scratch volume. }

            IF work_area = NIL THEN
              work_area_size := 2 * (#SIZE (clt$data_value) + #SIZE (rmt$external_vsn));
              PUSH work_area: [[REP work_area_size OF cell]];
            ELSE
              RESET work_area;
            IFEND;

          /scl_environment/
            BEGIN
              clp$evaluate_sub_parameters (response_string.value (1, response_string.size), #SEQ (pdt),
                    work_area, ^pvt, status);
              IF NOT status.normal THEN
                reason := ' Improper expression  ';
                EXIT /scl_environment/;
              IFEND;

              IF pvt [p$external_vsn].specified THEN
                IF pvt [p$external_vsn].value^.kind = clc$name THEN
                  evsn := pvt [p$external_vsn].value^.name_value;
                ELSE { clc$string }
                  rmp$validate_ansi_string (pvt [p$external_vsn].value^.string_value^, evsn, status);
                  IF NOT status.normal THEN
                    reason := ' Illegal external_vsn ';
                    EXIT /scl_environment/;
                  IFEND;
                IFEND;

                IF NOT pvt [p$recorded_vsn].specified THEN
                  rvsn := evsn;
                IFEND;
              IFEND;

              IF pvt [p$recorded_vsn].specified THEN
                IF pvt [p$recorded_vsn].value^.kind = clc$name THEN
                  rvsn := pvt [p$recorded_vsn].value^.name_value;
                ELSE { clc$string }
                  rmp$validate_ansi_string (pvt [p$recorded_vsn].value^.string_value^, rvsn, status);
                  IF NOT status.normal THEN
                    reason := ' Illegal recorded_vsn ';
                    EXIT /scl_environment/;
                  IFEND;
                IFEND;

                IF NOT pvt [p$external_vsn].specified THEN
                  evsn := rvsn;
                IFEND;
              IFEND;

              IF pvt [p$external_vsn].specified OR pvt [p$recorded_vsn].specified THEN
                EXIT /display_menu/;
              ELSE
                reason := ' EVSN or RVSN required';
              IFEND;
            END /scl_environment/;
            status_line := ' ';
            STRINGREP (status_line, ignore_length, 'INVALID RESPONSE: ', response_string.
                  value (1, response_string.size), reason);
            message_parameters [3] := ^status_line;
            CYCLE /display_menu/;

          ELSEIF (response = 2) THEN { operator wants to terminate the scratch request. }
            IF response_string.size > 0 THEN
              terminate_reason := response_string.value (1, response_string.size);
            ELSE
              terminate_reason := 'scratch volume was not available';
            IFEND;
            osp$set_status_abnormal (rmc$resource_management_id, dme$operator_stop, terminate_reason, status);

          IFEND;

          EXIT /display_menu/;
        WHILEND /display_menu/;

      PROCEND operator_menu_for_scratch_tape;
?? OLDTITLE ??
?? EJECT ??

      VAR
        message_name: clt$parameter_name,
        previous_evsn: rmt$external_vsn,
        previous_rvsn: rmt$external_vsn,
        source_pool: ost$name,
        source_pool_location: ost$name;

{ Get value of previous evsn and rvsn.  If current_vsn_index is 1, there is no previous volume.

      IF job_lun_table_entry.current_vsn_index > 1 THEN
        #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.volume_list^
              [job_lun_table_entry.current_vsn_index-1].external_vsn, previous_evsn);
        #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.volume_list^
              [job_lun_table_entry.current_vsn_index-1].recorded_vsn, previous_rvsn);
      ELSE
        previous_evsn := 'None  ';
        previous_rvsn := 'None  ';
      IFEND;
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.volume_list^
            [job_lun_table_entry.current_vsn_index].external_vsn, requested_evsn);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.volume_list^
            [job_lun_table_entry.current_vsn_index].recorded_vsn, requested_rvsn);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            account, requested_volume_attributes.account);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            family, requested_volume_attributes.family);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            project, requested_volume_attributes.project);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            removable_media_group, requested_volume_attributes.removable_media_group);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            removable_media_location, requested_volume_attributes.removable_media_location);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            slot, requested_volume_attributes.slot);
      #TRANSLATE (osv$lower_to_upper, job_lun_table_entry.requested_volume_attributes.
            user, requested_volume_attributes.user);
      IF (requested_evsn = rmc$unspecified_vsn) THEN
        IF dmv$initialize_tape_volume.in_progress THEN
          IF (dmv$initialize_tape_volume.element_name = osc$null_name) THEN
            osp$set_status_condition (rme$volume_not_mounted, status);
          IFEND;
        ELSE
          osp$clear_job_signature_lock (rmv$job_tape_table_lock);
          osp$end_subsystem_activity;
          message_name := 'WAIT_SCRATCH_VOLUME';
          message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
          rmp$put_job_status_display (message_name, NIL {message_parameters} );
          operator_menu_for_scratch_tape (job_lun_table_entry.label_type,
                requested_volume_attributes, job_lun_table_entry.density,
                previous_evsn, previous_rvsn, requested_evsn, requested_rvsn, status);
          osp$set_job_signature_lock (rmv$job_tape_table_lock);
          osp$begin_subsystem_activity;
          IF status.normal THEN
            job_lun_table_entry.volume_list^ [job_lun_table_entry.current_vsn_index].external_vsn :=
                  requested_evsn;
            job_lun_table_entry.volume_list^ [job_lun_table_entry.current_vsn_index].recorded_vsn :=
                  requested_rvsn;
            debug_message_logged := FALSE;
            REPEAT
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Calling iop$extend_volume_list_in_rvl');
              IFEND;
              iop$extend_volume_list_in_rvl (sfid, requested_evsn, requested_rvsn,
                    requested_volume_attributes, job_lun_table_entry.current_vsn_index, status);
              IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
                IF NOT debug_message_logged THEN
                  rmp$log_debug_message (' Waiting for tape table lock');
                  debug_message_logged := TRUE;
                IFEND;
                pmp$long_term_wait (one_second, one_second);
              IFEND;
            UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IFEND;
        IFEND;
      IFEND;
    PROCEND select_volume;

?? OLDTITLE ??
?? EJECT ??

    VAR
      assigned_mainframe_lun: iot$logical_unit,
      assignment_type: iot$operator_assignment_type,
      debug_message_logged: boolean,
      first_in_queue: boolean,
      ignore_status: ost$status,
      job_lun_table_entry: ^dmt$tape_lun_table_entry,
      message_name: clt$parameter_name,
      requested_rvsn: rmt$recorded_vsn,
      requested_volume_attributes: iot$requested_volume_attributes,
      selected_element: ost$name,
      volume_mounted: boolean,
      wait_message_displayed: boolean;

    status.normal := TRUE;
{ Initialize state variables and SPOIL anything read by condition handler}
    assigned_count_incremented := FALSE;
    element_assigned := FALSE;

    osp$get_current_display_message (original_message);

    #SPOIL (assigned_count_incremented, element_assigned, original_message);

    osp$establish_condition_handler (^activate_volume_handler, TRUE);
    osp$begin_subsystem_activity;
    osp$set_job_signature_lock (rmv$job_tape_table_lock);

  /mount_and_assign/
    BEGIN

      job_lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];

{ Determine if volume currently active.
      IF job_lun_table_entry^.lun <> 0 THEN
        osp$set_status_abnormal (rmc$resource_management_id, dme$active_tape_volume, '', status);
        EXIT /mount_and_assign/;
      IFEND;

      requested_density := job_lun_table_entry^.density;
      #SPOIL (requested_density);
      IF NOT status.normal THEN
        EXIT /mount_and_assign/;
      IFEND;

      IF NOT dmv$initialize_tape_volume.in_progress THEN
        IF rmv$job_tape_table_p <> NIL THEN
{ Set tape assigned.  This must be done now, before waiting for the tape to be mounted
{ so other tasks in the same job cannot get tapes if the reserve count is exceeded.
          rmv$job_tape_table_p^.assigned_unit_count [requested_density] :=
                rmv$job_tape_table_p^.assigned_unit_count [requested_density] + 1;
          assigned_count_incremented := TRUE;
          #SPOIL (assigned_count_incremented);
        ELSE
          osp$set_status_condition (dme$reserve_not_effected, status);
          EXIT /mount_and_assign/;
        IFEND;
      IFEND;

      select_volume (sfid, job_lun_table_entry^, requested_evsn, requested_rvsn,
            requested_volume_attributes, status);
      IF NOT status.normal THEN
        EXIT /mount_and_assign/;
      IFEND;

      current_date_time_string.size := 0;
      current_date_time_string.value := '';
      clp$get_date_time_string ('' {get date/time in site defined form} , current_date_time_string,
            ignore_status);

      first_in_queue := FALSE;
      REPEAT
        debug_message_logged := FALSE;
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling iop$queue_volume_assignment');
          IFEND;
          iop$queue_volume_assignment (sfid, job_lun_table_entry^.label_type, requested_density,
                requested_evsn, requested_rvsn, requested_volume_attributes, first_in_queue, status);
          IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Waiting for tape table lock');
              debug_message_logged := TRUE;
            IFEND;
            pmp$long_term_wait (one_second, one_second);
          IFEND;
        UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
        rmp$log_debug_message (' Exiting iop$queue_volume_assignment');
        rmp$log_debug_status (status);
        IF status.normal THEN
          IF (NOT first_in_queue) AND (NOT dmv$initialize_tape_volume.in_progress) THEN
            message_name := 'WAIT_VSN_BUSY';
            message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
            message_parameters [2] := ^requested_evsn;
            rmp$put_job_status_display (message_name, ^message_parameters);
            rmp$log_debug_message (' Queueing on busy volume.');
            wait (five_minutes); {Wait until another job stops using the volume we're after.}
          IFEND;
        ELSE
          EXIT /mount_and_assign/;
        IFEND;
      UNTIL first_in_queue OR dmv$initialize_tape_volume.in_progress;

      IF dmv$initialize_tape_volume.in_progress AND (dmv$initialize_tape_volume.logical_unit > 0) THEN
        rmp$assign_tape_unit (sfid, dmv$initialize_tape_volume.element_name, $cmt$element_states [cmc$on],
              job_lun_table_entry^.label_type, assigned_mainframe_lun, status);
        #SPOIL (assigned_mainframe_lun);
        EXIT /mount_and_assign/;
      IFEND;

?? EJECT ??
      volume_mounted := FALSE;

      debug_message_logged := FALSE;
    /mount/
      REPEAT
        osp$clear_job_signature_lock (rmv$job_tape_table_lock);
        osp$end_subsystem_activity;
        rmp$log_debug_message (' Entering Attempt Robotic Mount');
        attempt_robotic_mount (sfid, acceptable_states, last_choice_element, required_element,
              assigned_mainframe_lun, selected_element, status);
        osp$set_job_signature_lock (rmv$job_tape_table_lock);
        osp$begin_subsystem_activity;
        IF status.normal THEN
          rmp$log_debug_message (' Attempt Robotic Mount returned normal status - volume mounted');
          volume_mounted := TRUE;
        ELSE
          CASE status.condition OF
          = dme$tape_unit_down, dme$tape_unit_off, dme$tape_unit_undefined, dme$unit_assigned =
            IF dmv$initialize_tape_volume.in_progress THEN
              osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available,
                    'INITIALIZE_TAPE_VOLUME ', status);
            IFEND;
          = rme$volume_not_mounted =
            rmp$log_debug_message (' Attempt Robotic Mount returned rme$volume_not_mounted');
            status.normal := NOT dmv$initialize_tape_volume.in_progress;
          ELSE
          CASEND;
        IFEND;
        IF status.normal AND (NOT volume_mounted) THEN
          attempt_manual_mount (sfid, selected_element, volume_mounted, status);
          IF status.normal AND volume_mounted THEN
            assign_element_to_job (sfid, acceptable_states, selected_element, assigned_mainframe_lun, status);
            IF NOT status.normal THEN
              volume_mounted := FALSE;
              CASE status.condition OF
              = dme$tape_unit_down, dme$tape_unit_off =
                REPEAT
                  IF NOT debug_message_logged THEN
                    rmp$log_debug_message (' Calling iop$release_assignment_in_rvl');
                  IFEND;
                  iop$release_assignment_in_rvl (sfid, status);
                  IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
                    IF NOT debug_message_logged THEN
                      rmp$log_debug_message (' Waiting for tape table lock');
                      debug_message_logged := TRUE;
                    IFEND;
                    pmp$wait (one_second, one_second);
                  IFEND;
                UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
              ELSE
                EXIT /mount_and_assign/;
              CASEND
            IFEND;
          IFEND;
        IFEND;
      UNTIL volume_mounted OR (NOT status.normal);

    END /mount_and_assign/;

    IF status.normal THEN
      job_lun_table_entry^.lun := assigned_mainframe_lun;
      job_lun_table_entry^.job_recovery_active := FALSE;
      element_assigned := TRUE;
      IF assigned_mainframe_lun <> 0 THEN
        rmp$log_debug_message (' Job_lun_table_entry now contains mainframe lun #');
        rmp$log_debug_message (' Tape unit assigned to job');
      ELSE
        rmp$log_debug_message (' ERROR - Stored zero mainframe lun in job_lun_table_entry');
      IFEND;
      #SPOIL (element_assigned);

      IF dmv$initialize_tape_volume.in_progress AND (dmv$initialize_tape_volume.element_name = osc$null_name)
            THEN
        dmv$initialize_tape_volume.element_name := selected_element;
      IFEND;
    ELSEIF assigned_count_incremented THEN
      IF rmv$job_tape_table_p^.assigned_unit_count [requested_density] > 0 THEN
        rmv$job_tape_table_p^.assigned_unit_count [requested_density] :=
              rmv$job_tape_table_p^.assigned_unit_count [requested_density] - 1;
      IFEND;
      assigned_count_incremented := FALSE;
      #SPOIL (assigned_count_incremented);
      rmp$log_debug_message (
            ' Decremented assignment count due to abnormal exit in rmp$activate_client_volume');
    IFEND;

    osp$clear_job_signature_lock (rmv$job_tape_table_lock);
    osp$end_subsystem_activity;
    osp$disestablish_cond_handler;
    ofp$clear_operator_message (ofc$removable_media_operator, ignore_status);
    wait_message_displayed := TRUE;
    osp$clear_wait_message (original_message, wait_message_displayed);
    rmp$log_debug_message (' Exiting rmp$activate_volume');

  PROCEND rmp$activate_volume;

?? OLDTITLE ??
?? NEWTITLE := 'rmp$deactivate_volume', EJECT ??

  PROCEDURE [XDCL] rmp$deactivate_volume
    (    sfid: gft$system_file_identifier;
         delete_request_from_vsn_queue: boolean;
     VAR status: ost$status);

    VAR
      assignment_count_decremented: boolean,
      element_released: boolean,
      original_message: oft$display_message,
      volume_dismounted: boolean;

?? NEWTITLE := '  deactivate_volume_handler', EJECT ??

    PROCEDURE deactivate_volume_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR condition_status: ost$status);

      VAR
        debug_status: ost$status,
        ignore_status: ost$status,
        lock_status: ost$signature_lock_status,
        wait_message_displayed: boolean;

      rmp$log_debug_message (' Entering deactivate_volume_handler');
      osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, debug_status,
            ignore_status);
      CASE condition.selector OF

      = pmc$block_exit_processing =

        wait_message_displayed := TRUE;
        osp$clear_wait_message (original_message, wait_message_displayed);

        osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
        IF lock_status = osc$sls_locked_by_current_task THEN
          osp$clear_job_signature_lock (rmv$job_tape_table_lock);
          osp$end_subsystem_activity;
        IFEND;

        release_tape_resources;

      = ifc$interactive_condition =

        CASE condition.interactive_condition OF
        = ifc$terminate_break =
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                ignore_status);
          EXIT rmp$deactivate_volume;
        = ifc$pause_break, ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;

      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;
      rmp$log_debug_message (' Exiting deactivate_volume_handler');

    PROCEND deactivate_volume_handler;

?? OLDTITLE ??
?? NEWTITLE := '  release_tape_resources', EJECT ??

    PROCEDURE release_tape_resources;

      VAR
        ignore_status: ost$status,
        local_status: ost$status,
        lun: iot$logical_unit,
        lun_table_entry: ^dmt$tape_lun_table_entry;

      osp$set_job_signature_lock (rmv$job_tape_table_lock);
      osp$begin_subsystem_activity;

      IF dmv$tape_job_lun_table_p <> NIL THEN
        lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];
        lun := lun_table_entry^.lun;
      ELSE
        lun := 0;
      IFEND;

      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;

      IF NOT volume_dismounted THEN
        rmp$log_debug_message (' Calling dismount_volume');
        volume_dismounted := TRUE;
        #SPOIL (volume_dismounted);
        dismount_volume (sfid, local_status);
        rmp$log_debug_message (' Exited dismount_volume');
        rmp$log_debug_status (local_status);
        osp$copy_local_status_to_status (local_status, status);
      IFEND;

      osp$set_job_signature_lock (rmv$job_tape_table_lock);
      osp$begin_subsystem_activity;

    /release/
      BEGIN
        IF lun = 0 THEN
          EXIT /release/;
        IFEND;

        IF NOT element_released THEN
          release_element_from_job (sfid, delete_request_from_vsn_queue, lun, status);
          element_released := TRUE;
          #SPOIL (element_released);
          IF NOT status.normal THEN
            rmp$log_debug_message (' Exiting with abnormal status:');
            rmp$log_debug_status (status);
            EXIT /release/;
          IFEND;
        IFEND;

        IF NOT dmv$initialize_tape_volume.in_progress THEN
          IF NOT assignment_count_decremented THEN
            requested_density := lun_table_entry^.density;
            IF rmv$job_tape_table_p <> NIL THEN
              IF rmv$job_tape_table_p^.assigned_unit_count [requested_density] > 0 THEN
                rmv$job_tape_table_p^.assigned_unit_count [requested_density] :=
                      rmv$job_tape_table_p^.assigned_unit_count [requested_density] - 1;
                assignment_count_decremented := TRUE;
                #SPOIL (assignment_count_decremented);
                rmp$log_debug_message (' Decremented assignment count');
              IFEND;
            IFEND;
          IFEND;
        IFEND;

{ Clear logical unit number to indicate no currently assigned volume.
        lun_table_entry^.lun := 0;

      END /release/;

      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;

    PROCEND release_tape_resources;

?? OLDTITLE ??
?? EJECT ??

    VAR
      elapsed_time: integer,
      start_time: integer,
      wait_message_displayed: boolean;

    rmp$log_debug_message (' Entering rmp$deactivate_volume');
    status.normal := TRUE;
    start_time := #FREE_RUNNING_CLOCK (0);
    assignment_count_decremented := FALSE;
    element_released := FALSE;
    volume_dismounted := FALSE;
    osp$get_current_display_message (original_message);
    #SPOIL (assignment_count_decremented, element_released, volume_dismounted, original_message);

    osp$establish_condition_handler (^deactivate_volume_handler, {handle block exit} TRUE);

    release_tape_resources;

    osp$disestablish_cond_handler;

    wait_message_displayed := TRUE;
    osp$clear_wait_message (original_message, wait_message_displayed);
    rmp$log_debug_message ('Exiting rmp$deactivate_volume.');
    elapsed_time := #FREE_RUNNING_CLOCK (0) - start_time;
    rmp$log_debug_integer (' DISMOUNT COMPLETE; ELAPSED TIME (secs) = ',
          elapsed_time DIV microseconds_per_second);

  PROCEND rmp$deactivate_volume;

?? OLDTITLE ??
?? NEWTITLE := 'assign_element_to_job', EJECT ??

  PROCEDURE assign_element_to_job
    (    sfid: gft$system_file_identifier;
         acceptable_states: cmt$element_states;
         selected_element: cmt$element_name;
     VAR assigned_mainframe_lun: iot$logical_unit;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      label_type: amt$label_type,
      local_mainframe_lun: iot$logical_unit;

    label_type := dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].label_type;
    log_debug_assignment ('Attempting to assign Element: ', selected_element);
    rmp$assign_tape_unit (sfid, selected_element, acceptable_states, label_type, local_mainframe_lun, status);
    rmp$log_debug_status (status);
    IF status.normal THEN
      log_debug_assignment ('Assigned Element: ', selected_element);
      assigned_mainframe_lun := local_mainframe_lun;
    ELSE
      assigned_mainframe_lun := 0;
    IFEND;
  PROCEND assign_element_to_job;
?? OLDTITLE ??
?? NEWTITLE := 'check_synchronization', EJECT ??

  PROCEDURE check_synchronization
    (    current_request: rmt$rbt_request_type;
     VAR last_sync_error: rmt$rbt_supported_requests;
     VAR {input, output} status: ost$status);

    VAR
      ignore_status: ost$status;

    IF status.normal THEN
      last_sync_error := $rmt$rbt_supported_requests [];
    ELSEIF status.condition = rme$synchronization_error THEN
      IF last_sync_error = $rmt$rbt_supported_requests [] THEN
        last_sync_error := $rmt$rbt_supported_requests [current_request];
        rmp$log_debug_message (' First sync error detected - retrying.');
        status.normal := TRUE;
      ELSEIF current_request IN last_sync_error THEN
        rmp$log_debug_message (' Second and final sync error.');
        last_sync_error := $rmt$rbt_supported_requests [];
      ELSE
        last_sync_error := $rmt$rbt_supported_requests [current_request];
        rmp$log_debug_message (' Consecutive sync errors on different requests.');
        status.normal := TRUE;
      IFEND;
    ELSE
      last_sync_error := $rmt$rbt_supported_requests [];
      rmp$log_debug_message (' ERROR - process_request returned unexpected abnormal status.');
      rmp$log_debug_status (status);
    IFEND;
  PROCEND check_synchronization;
?? OLDTITLE ??
?? NEWTITLE := 'client_emit_messages', EJECT ??

  PROCEDURE client_emit_messages
    (    retry_count: ost$non_negative_integers;
         server_messages: iot$robotic_server_messages;
     VAR status: ost$status);

    status.normal := TRUE;

    IF (ioc$job_log_message IN server_messages.requested_messages) AND
          (retry_count = server_messages.job_log.issue_prior_to_retry_attempt) THEN
      emit_log_message (pmc$job_log, server_messages.job_log.message, status);
    IFEND;

    IF (ioc$job_status_message IN server_messages.requested_messages) AND
          (retry_count >= server_messages.job_status_display.issue_prior_to_retry_attempt) THEN
      emit_job_status_message (server_messages.job_status_display.message, status);
    IFEND;

    IF (ioc$operator_action_message IN server_messages.requested_messages) AND
          (retry_count = server_messages.operator_action.issue_prior_to_retry_attempt) THEN
      emit_operator_action_message (server_messages.operator_action.message, status);
    IFEND;

    IF (ioc$system_log_message IN server_messages.requested_messages) AND
          (retry_count = server_messages.system_log.issue_prior_to_retry_attempt) THEN
      emit_log_message (pmc$system_log, server_messages.system_log.message, status);
    IFEND;

  PROCEND client_emit_messages;

?? OLDTITLE ??
?? NEWTITLE := 'dismount_volume', EJECT ??

  PROCEDURE dismount_volume
    (    sfid: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      server_name: ost$name;

?? NEWTITLE := '  robotic_dismount_handler', EJECT ??

    PROCEDURE robotic_dismount_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR condition_status: ost$status);

      VAR
        debug_status: ost$status,
        ignore_status: ost$status,
        local_status: ost$status,
        lock_status: ost$signature_lock_status;

      rmp$log_debug_message (' Entering robotic_dismount_handler');
      osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, debug_status,
            ignore_status);
      rmp$log_debug_status (debug_status);
      CASE condition.selector OF

      = pmc$block_exit_processing =

        IF request_submitted THEN
          debug_message_logged := FALSE;
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$client_cancel_request');
            IFEND;
            iop$client_cancel_request (server_name, sfid, local_status);
            IF NOT local_status.normal AND (local_status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              pmp$long_term_wait (one_second, one_second);
            IFEND;
          UNTIL local_status.normal OR (local_status.condition <> dme$unable_to_lock_tape_table);
          rmp$log_debug_message ('Called iop$client_cancel_request');
          rmp$log_debug_status (local_status);
        IFEND;
        osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
        IF lock_status = osc$sls_locked_by_current_task THEN
          osp$end_subsystem_activity;
          osp$clear_job_signature_lock (rmv$job_tape_table_lock);
        IFEND;

      = ifc$interactive_condition =

        CASE condition.interactive_condition OF
        = ifc$terminate_break =
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                ignore_status);
          EXIT dismount_volume;
        = ifc$pause_break, ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;

      = pmc$user_defined_condition =
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        IF condition.user_condition_name = osc$job_recovery_condition_name THEN
          status.normal := TRUE;
          EXIT dismount_volume;
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;
      rmp$log_debug_message (' Exiting robotic_dismount_handler');

    PROCEND robotic_dismount_handler;
?? OLDTITLE ??
?? EJECT ??

    VAR
      current_date_time_string: ost$string,
      debug_message_logged: boolean,
      element: cmt$element_name,
      external_vsn: rmt$external_vsn,
      ignored_element: cmt$element_name,
      ignore_assigned_mainframe_lun: iot$logical_unit,
      ignore_status: ost$status,
      initial_tasks: rmt$rbt_supported_requests,
      job_lun_table_entry: ^dmt$tape_lun_table_entry,
      last_sync_error: rmt$rbt_supported_requests,
      local_status: ost$status,
      message_name: clt$parameter_name,
      message_parameters: array [1 .. 2] of ^ost$message_parameter,
      remaining_tasks: rmt$rbt_supported_requests,
      request: rmt$rbt_request,
      required_requests: rmt$rbt_supported_requests,
      retry_status: retry_status_info,
      server_entry: iot$robotic_server_entry,
      server_index: iot$robotic_server_index,
      server_located: boolean,
      valid_request_transitions: rmt$rbt_supported_requests;

    current_date_time_string.size := 0;
    current_date_time_string.value := '';
    clp$get_date_time_string ('' {get date/time in site defined form} , current_date_time_string,
          ignore_status);

    initial_tasks := $rmt$rbt_supported_requests [rmc$rbt_dismount];

    last_sync_error := $rmt$rbt_supported_requests [];

    remaining_tasks := initial_tasks;

    request_submitted := FALSE;

    retry_status.retry_in_progress := FALSE;

    valid_request_transitions := $rmt$rbt_supported_requests [rmc$rbt_force_dismount, rmc$rbt_dismount];


?? EJECT ??
    status.normal := TRUE;
    #SPOIL (request_submitted);
    osp$establish_condition_handler (^robotic_dismount_handler, {handle block exit} TRUE);

  /robotic_dismount/
    BEGIN
      osp$set_job_signature_lock (rmv$job_tape_table_lock);
      osp$begin_subsystem_activity;

      job_lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];

      IF job_lun_table_entry^.robotic_mount_info.volume_robotically_mounted THEN
        element := job_lun_table_entry^.robotic_mount_info.element;

        external_vsn := job_lun_table_entry^.volume_list^ [job_lun_table_entry^.current_vsn_index].
              external_vsn;

        server_name := job_lun_table_entry^.robotic_mount_info.server_name;
        #SPOIL (server_name);

        server_located := FALSE;

      /locate_server/
        FOR server_index := 1 TO ioc$max_server_index DO
          debug_message_logged := FALSE;
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$get_server_entry');
            IFEND;
            iop$get_server_entry (server_index, server_entry, local_status);
            IF NOT local_status.normal AND (local_status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              wait (one_second);
            IFEND;
          UNTIL local_status.normal OR (local_status.condition <> dme$unable_to_lock_tape_table);
          IF local_status.normal THEN
            IF server_entry.server_name = server_name THEN
              server_located := TRUE;
              EXIT /locate_server/;
            IFEND;
          ELSEIF local_status.condition = rme$invalid_server_index THEN
            EXIT /locate_server/;
          IFEND;
        FOREND /locate_server/;

        IF server_located THEN

          REPEAT
            message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
            message_parameters [2] := NIL;
            IF status.normal AND (remaining_tasks = $rmt$rbt_supported_requests []) THEN
              EXIT /robotic_dismount/;
            ELSEIF rmc$rbt_force_dismount IN remaining_tasks THEN
              request.request_type := rmc$rbt_force_dismount;
              request.force_dismount.element := element;
              message_name := 'WAIT_FOR_FORCE';
              message_parameters [1] := ^element;
              rmp$log_debug_message (' Issuing force dismount');
              process_request ({ignore acceptable_states} $cmt$element_states [], initial_tasks,
                    {last_choice_element} osc$null_name, message_name, current_date_time_string, request,
                    {required_element} osc$null_name, server_name, server_entry.server_attributes.timeout,
                    sfid, valid_request_transitions, message_parameters, ignore_assigned_mainframe_lun,
                    remaining_tasks, retry_status, ignored_element, status);
              check_synchronization (request.request_type, last_sync_error, status);
            ELSEIF rmc$rbt_dismount IN remaining_tasks THEN
              request.request_type := rmc$rbt_dismount;
              request.dismount.element := element;
              request.dismount.external_vsn := external_vsn;
              message_name := 'WAIT_FOR_DISMOUNT';
              message_parameters [1] := ^external_vsn;
              message_parameters [2] := ^element;
              rmp$log_debug_message (' Issuing dismount');
              process_request ({ignore acceptable_states} $cmt$element_states [], initial_tasks,
                    {last_choice_element} osc$null_name, message_name, current_date_time_string, request,
                    {required_element} osc$null_name, server_name, server_entry.server_attributes.timeout,
                    sfid, valid_request_transitions, message_parameters, ignore_assigned_mainframe_lun,
                    remaining_tasks, retry_status, ignored_element, status);
              check_synchronization (request.request_type, last_sync_error, status);
            IFEND;
          UNTIL NOT status.normal;
        ELSE {do not wait for server to become defined}
          status.normal := TRUE;
        IFEND;
      IFEND;
    END /robotic_dismount/;

    job_lun_table_entry^.robotic_mount_info.volume_robotically_mounted := FALSE;
    osp$clear_job_signature_lock (rmv$job_tape_table_lock);
    osp$end_subsystem_activity;
    osp$disestablish_cond_handler;
    rmp$log_debug_message (' Exiting client dismount');

  PROCEND dismount_volume;
?? OLDTITLE ??
?? NEWTITLE := 'emit_job_status_message', EJECT ??

  PROCEDURE emit_job_status_message
    (    server_message: ost$status_message;
     VAR status: ost$status);

    VAR
      message_text: ^ost$status_message_line,
      message_text_size: ost$status_message_line_size;

    status.normal := TRUE;

    message_text := osp$status_message_text (^server_message);
    message_text_size := STRLENGTH (message_text^);
    IF message_text_size > ofc$max_display_message THEN
      message_text_size := ofc$max_display_message;
    IFEND;

    ofp$display_status_message (message_text^ (1, message_text_size), status);
    rmp$log_debug_message (message_text^ (1, message_text_size));

  PROCEND emit_job_status_message;
?? OLDTITLE ??
?? NEWTITLE := 'emit_log_message', EJECT ??

  PROCEDURE emit_log_message
    (    log_type: pmt$ascii_logs;
         server_message: ost$status_message;
     VAR status: ost$status);

    VAR
      message_text: ^ost$status_message_line,
      message_area: ^ost$status_message,
      message_line_count: ^ost$status_message_line_count,
      message_text_size: ^ost$status_message_line_size;

    VAR
      line: ost$status_message_line_count;

    status.normal := TRUE;

    message_area := ^server_message;
    RESET message_area;
    NEXT message_line_count IN message_area;
    FOR line := 1 TO message_line_count^ DO
      NEXT message_text_size IN message_area;
      NEXT message_text: [message_text_size^] IN message_area;
      pmp$log_ascii (message_text^ (2, * ), $pmt$ascii_logset [log_type], pmc$msg_origin_program, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    FOREND;

  PROCEND emit_log_message;
?? OLDTITLE ??
?? NEWTITLE := 'emit_operator_action_message', EJECT ??

  PROCEDURE emit_operator_action_message
    (    server_message: ost$status_message;
     VAR status: ost$status);

    VAR
      formatted_message: oft$formatted_operator_message,
      line_count: oft$number_of_displayable_lines;

    status.normal := TRUE;

    ofp$format_operator_message (server_message, 1, formatted_message, line_count);

    ofp$send_formatted_operator_msg (formatted_message, ofc$removable_media_operator,
          {acknowledgement_allowed} FALSE, status);

  PROCEND emit_operator_action_message;
?? OLDTITLE ??
?? NEWTITLE := 'log_debug_assignment', EJECT ??

  PROCEDURE log_debug_assignment
    (    explanation: string ( * );
         element: cmt$element_name);

    VAR
      line: string (80),
      length: integer;

    STRINGREP (line, length, explanation, element);
    rmp$log_debug_message (line (1, length));
  PROCEND log_debug_assignment;
?? OLDTITLE ??
?? NEWTITLE := 'log_debug_retry', EJECT ??

  PROCEDURE log_debug_retry
    (    response: iot$formatted_server_response);

    VAR
      line: string (80),
      length: integer,
      requests: [READ, oss$job_paged_literal] array [rmc$rbt_query .. rmc$rbt_force_dismount] of string (14)
            := ['Query         ', 'Mount          ', 'Dismount      ', 'Force_dismount'];

    STRINGREP (line, length, ' Request_id: ', response.request_id, ' Server_event_code:  ',
          response.server_event_code);
    rmp$log_debug_message (line (1, length));

    STRINGREP (line, length, ' Current_request: ', requests [response.current_request], ' Next_request:  ',
          requests [response.next_request]);
    rmp$log_debug_message (line (1, length));

    STRINGREP (line, length, ' Retry_delay_interval: ', response.retry_delay_interval, ' Retry_limit:  ',
          response.retry_limit);
    rmp$log_debug_message (line (1, length));

  PROCEND log_debug_retry;
?? OLDTITLE ??
?? NEWTITLE := 'process_request', EJECT ??

  PROCEDURE process_request
    (    acceptable_states: cmt$element_states;
         initial_tasks: rmt$rbt_supported_requests;
         last_choice_element: cmt$element_name;
         message_name: clt$parameter_name;
         current_date_time_string: ost$string;
         request: rmt$rbt_request;
         required_element: cmt$element_name;
         server_name: ost$name;
         server_timeout: ost$positive_integers;
         sfid: gft$system_file_identifier;
         valid_request_transitions: rmt$rbt_supported_requests;
     VAR message_parameters: array [1 .. 2] of ^ost$message_parameter;
     VAR assigned_mainframe_lun: iot$logical_unit;
     VAR remaining_tasks: rmt$rbt_supported_requests;
     VAR retry_status: retry_status_info;
     VAR selected_element: cmt$element_name;
     VAR status: ost$status);

    VAR
      current_time: integer,
      debug_message_logged: boolean,
      duration: integer,
      elapsed_time: integer,
      ignore_status: ost$status,
      local_status: ost$status,
      request_id: rmt$rbt_request_id,
      response: iot$formatted_server_response,
      submittal_time: integer;

?? OLDTITLE ??
?? NEWTITLE := '  process_request_handler  ', EJECT ??

    PROCEDURE process_request_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR condition_status: ost$status);

      VAR
        ignore_status: ost$status;

      CASE condition.selector OF
      = ifc$interactive_condition =
        CASE condition.interactive_condition OF
        = ifc$pause_break, ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        = ifc$terminate_break =
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                ignore_status);
          EXIT process_request;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;

    PROCEND process_request_handler;

?? NEWTITLE := '  process_response', EJECT ??

    PROCEDURE process_response
      (    acceptable_states: cmt$element_states;
           initial_tasks: rmt$rbt_supported_requests;
           last_choice_element: cmt$element_name;
           request: rmt$rbt_request;
           required_element: cmt$element_name;
           response: iot$formatted_server_response;
           server_name: ost$name;
           sfid: gft$system_file_identifier;
           valid_request_transitions: rmt$rbt_supported_requests;
       VAR assigned_mainframe_lun: iot$logical_unit;
       VAR retry_status: retry_status_info;
       VAR remaining_tasks: rmt$rbt_supported_requests;
       VAR selected_element: cmt$element_name;
       VAR status: ost$status);

      VAR
        ignore_status: ost$status;

?? NEWTITLE := '    process_query_response', EJECT ??

      PROCEDURE process_query_response
        (    acceptable_states: cmt$element_states;
             initial_tasks: rmt$rbt_supported_requests;
             last_choice_element: cmt$element_name;
             request: rmt$rbt_request;
             required_element: cmt$element_name;
             response: iot$formatted_server_response;
             server_name: ost$name;
             sfid: gft$system_file_identifier;
         VAR assigned_mainframe_lun: iot$logical_unit;
         VAR remaining_tasks {input/output} : rmt$rbt_supported_requests;
         VAR selected_element: cmt$element_name;
         VAR status: ost$status);

        VAR
          i: integer,
          ignore_status: ost$status,
          message_name: clt$parameter_name,
          preferred_candidates: ^array [1 .. * ] of cmt$element_name,
          remaining_candidates: ^array [1 .. * ] of cmt$element_name;

?? EJECT ??
        IF response.query.external_vsn = request.query.external_vsn THEN
          IF response.query.volume_located AND response.query.already_mounted THEN
            IF required_element <> osc$null_name THEN
              IF required_element = response.query.element THEN
                rmp$log_debug_message ('   Required element = already mounted element.');
                rmp$log_debug_message ('   Assigning required_element');
                assign_element_to_job (sfid, acceptable_states, required_element, assigned_mainframe_lun,
                      status);
                IF status.normal THEN
                  selected_element := required_element;
                  remaining_tasks := $rmt$rbt_supported_requests [];
                  rmp$log_debug_message (' Tape unit assigned to job');
                IFEND;
              ELSE {volume is not in the required drive}
                rmp$log_debug_message ('   Required_element-  Volume is not in correct drive.');
                rmp$log_debug_message ('   Attempting to assign the drive for purpose of force dismount');
                assign_element_to_job (sfid, acceptable_states, response.query.element,
                      assigned_mainframe_lun, status);
                IF status.normal THEN
                  remaining_tasks := remaining_tasks + $rmt$rbt_supported_requests [rmc$rbt_force_dismount];
                  selected_element := response.query.element;
                  rmp$log_debug_message (' Tape unit assigned to job');
                IFEND;
              IFEND;
            ELSE {volume already mounted and no required element}
              rmp$log_debug_message ('   Volume already mounted.');
              assign_element_to_job (sfid, acceptable_states, response.query.element, assigned_mainframe_lun,
                    status);
              IF status.normal THEN
                selected_element := response.query.element;
                remaining_tasks := $rmt$rbt_supported_requests [];
                rmp$log_debug_message (' Tape unit assigned to job');
              ELSE
                IF NOT dmv$initialize_tape_volume.in_progress THEN
                  CASE status.condition OF
                  = dme$tape_unit_down, dme$tape_unit_off =
                    message_name := 'WAIT_ROBOTIC_UNIT';
                    message_parameters [1] := ^current_date_time_string.value
                          (1, current_date_time_string.size);
                    message_parameters [2] := ^requested_evsn;
                    rmp$put_job_status_display (message_name, ^message_parameters);
                    message_name := 'ROBOTIC_UNIT_UNAVAILABLE';
                    message_parameters [1] := ^requested_evsn;
                    message_parameters [2] := ^response.query.element;
                    rmp$emit_operator_message (message_name, ^message_parameters,
                          {acknowledgement_allowed} FALSE, ignore_status);
                    wait (five_seconds);
                    status.normal := TRUE {retry query} ;
                  = dme$unit_assigned =
                    message_name := 'WAIT_VSN_BUSY';
                    message_parameters [1] := ^current_date_time_string.value
                          (1, current_date_time_string.size);
                    message_parameters [2] := ^requested_evsn;
                    rmp$put_job_status_display (message_name, ^message_parameters);
                    wait (five_minutes); {Wait for element to be released}
                    status.normal := TRUE {retry query} ;
                  CASEND
                IFEND;
              IFEND;
            IFEND;
          ELSEIF response.query.volume_located THEN
            IF response.query.preferred_candidates <> NIL THEN
              PUSH preferred_candidates: [LOWERBOUND (response.query.
                    preferred_candidates^) .. UPPERBOUND (response.query.preferred_candidates^)];
              FOR i := 1 TO UPPERBOUND (response.query.preferred_candidates^) DO
                preferred_candidates^ [i] := response.query.preferred_candidates^ [i];
              FOREND;
            ELSE
              preferred_candidates := NIL;
            IFEND;
            IF response.query.remaining_candidates <> NIL THEN
              PUSH remaining_candidates: [LOWERBOUND (response.query.
                    remaining_candidates^) .. UPPERBOUND (response.query.remaining_candidates^)];
              FOR i := 1 TO UPPERBOUND (response.query.remaining_candidates^) DO
                remaining_candidates^ [i] := response.query.remaining_candidates^ [i];
              FOREND;
            ELSE
              remaining_candidates := NIL;
            IFEND;
            select_element (acceptable_states, sfid, last_choice_element, preferred_candidates,
                  remaining_candidates, required_element, current_date_time_string, message_parameters,
                  assigned_mainframe_lun, selected_element, status);
            IF status.normal THEN
              remaining_tasks := remaining_tasks - $rmt$rbt_supported_requests [rmc$rbt_query];
            IFEND;
          ELSE
            rmp$log_debug_message (' Volume not in library.');
            osp$set_status_condition (rme$volume_not_mounted, status);
          IFEND;
        ELSE
          osp$set_status_condition (rme$synchronization_error, status);
        IFEND;
      PROCEND process_query_response;
?? OLDTITLE ??
?? NEWTITLE := '    process_request_retry', EJECT ??

      PROCEDURE process_request_retry
        (    initial_tasks: rmt$rbt_supported_requests;
             request: rmt$rbt_request;
             response: iot$formatted_server_response;
             valid_request_transitions: rmt$rbt_supported_requests;
         VAR remaining_tasks {input/output} : rmt$rbt_supported_requests;
         VAR retry_status {input/output} : retry_status_info;
         VAR status: ost$status);

        VAR
          ignore_status: ost$status,
          local_status: ost$status,
          message_name: clt$parameter_name;

        rmp$log_debug_message (' Entered Process Request Retry');
        log_debug_retry (response);
        IF request.request_type = response.current_request THEN
          IF retry_status.retry_in_progress THEN
            message_name := 'WAIT_SERVER_RETRY';
            message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
            message_parameters [2] := ^requested_evsn;
            rmp$put_job_status_display (message_name, ^message_parameters);

            IF retry_status.server_event_code = response.server_event_code THEN
              retry_status.retry_count := retry_status.retry_count + 1;
              client_emit_messages (retry_status.retry_count, response.server_messages^, ignore_status);
              IF retry_status.retry_count > retry_status.retry_limit THEN
                IF retry_status.next_request IN valid_request_transitions THEN
                  remaining_tasks := remaining_tasks +
                        $rmt$rbt_supported_requests [retry_status.next_request];
                ELSE {start over}
                  remaining_tasks := initial_tasks;
                IFEND;
                retry_status.retry_in_progress := FALSE;
                ofp$clear_operator_message (ofc$removable_media_operator, ignore_status);
              ELSE
                wait (retry_status.retry_delay_interval);
              IFEND;
            ELSE {new event encountered}
              ofp$clear_operator_message (ofc$removable_media_operator, ignore_status);

              retry_status.next_request := response.next_request;
              retry_status.retry_count := 1;
              retry_status.retry_delay_interval := response.retry_delay_interval;
              retry_status.retry_limit := response.retry_limit;
              retry_status.server_event_code := response.server_event_code;
              client_emit_messages (retry_status.retry_count, response.server_messages^, ignore_status);
              wait (retry_status.retry_delay_interval);
              retry_status.retry_in_progress := TRUE;
            IFEND;
          ELSE {retry not in progress}
            retry_status.next_request := response.next_request;
            retry_status.retry_count := 1;
            retry_status.retry_delay_interval := response.retry_delay_interval;
            retry_status.retry_limit := response.retry_limit;
            retry_status.server_event_code := response.server_event_code;
            client_emit_messages (retry_status.retry_count, response.server_messages^, ignore_status);
            wait (retry_status.retry_delay_interval);
            retry_status.retry_in_progress := TRUE;
          IFEND;
        ELSE
          osp$set_status_condition (rme$synchronization_error, status);
        IFEND;
      PROCEND process_request_retry;
?? OLDTITLE ??
?? EJECT ??
      status.normal := TRUE;
      IF response.request_processed THEN
        retry_status.retry_in_progress := FALSE;
        IF response.processed_request = request.request_type THEN
          CASE response.processed_request OF
          = rmc$rbt_force_dismount =
            IF response.force_dismount.element = request.force_dismount.element THEN
              remaining_tasks := remaining_tasks - $rmt$rbt_supported_requests
                    [rmc$rbt_dismount, rmc$rbt_force_dismount];
              rmp$log_debug_message (' Force Dismount processed');
            ELSE
              osp$set_status_condition (rme$synchronization_error, status);
            IFEND;
          = rmc$rbt_dismount =
            IF (response.dismount.element = request.dismount.element) AND
                  (response.dismount.external_vsn = request.dismount.external_vsn) THEN
              rmp$log_debug_message (' Dismount processed');
              remaining_tasks := remaining_tasks - $rmt$rbt_supported_requests [rmc$rbt_dismount];
            ELSE
              osp$set_status_condition (rme$synchronization_error, status);
            IFEND;
          = rmc$rbt_mount =
            IF (response.mount.element = request.mount.element) AND
                  (response.mount.external_vsn = request.mount.external_vsn) THEN
              remaining_tasks := remaining_tasks - $rmt$rbt_supported_requests [rmc$rbt_mount];
              rmp$log_debug_message (' Mount processed');
            ELSE
              osp$set_status_condition (rme$synchronization_error, status);
            IFEND;
          = rmc$rbt_query =
            process_query_response (acceptable_states, initial_tasks, last_choice_element, request,
                  required_element, response, server_name, sfid, assigned_mainframe_lun, remaining_tasks,
                  selected_element, status);
            rmp$log_debug_message (' Query processed');
          CASEND;
        ELSE
          osp$set_status_condition (rme$synchronization_error, status);
        IFEND;
      ELSE
        process_request_retry (initial_tasks, request, response, valid_request_transitions, remaining_tasks,
              retry_status, status);
      IFEND;
      rmp$log_debug_message (' Exiting Process Response');
    PROCEND process_response;
?? OLDTITLE ??
?? EJECT ??
    debug_message_logged := FALSE;
    REPEAT
      IF NOT debug_message_logged THEN
        rmp$log_debug_message (' Calling iop$client_put_request');
      IFEND;
      iop$client_put_request (server_name, sfid, request, request_id, status);
      IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
        IF NOT debug_message_logged THEN
          rmp$log_debug_message (' Waiting for tape table lock');
          debug_message_logged := TRUE;
        IFEND;
        osp$establish_condition_handler (^process_request_handler, {handle block exit} FALSE);
        pmp$long_term_wait (one_second, one_second);
        osp$disestablish_cond_handler;
      IFEND;
    UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
    IF status.normal THEN
      duration := server_timeout {in milliseconds} ;
      request_submitted := TRUE;
      #SPOIL (request_submitted);
      submittal_time := #FREE_RUNNING_CLOCK (0);

    /wait_loop/
      REPEAT
        rmp$put_job_status_display (message_name, ^message_parameters);
        wait (duration);
        debug_message_logged := FALSE;
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling iop$client_get_response');
          IFEND;
          iop$client_get_response (server_name, request_id, response, status);
          IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Waiting for tape table lock');
              debug_message_logged := TRUE;
            IFEND;
            osp$establish_condition_handler (^process_request_handler, {handle block exit} FALSE);
            pmp$long_term_wait (one_second, one_second);
            osp$disestablish_cond_handler;
          IFEND;
        UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
        IF status.normal THEN
          process_response (acceptable_states, initial_tasks, last_choice_element, request, required_element,
                response, server_name, sfid, valid_request_transitions, assigned_mainframe_lun, retry_status,
                remaining_tasks, selected_element, status);
          debug_message_logged := FALSE;
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$client_delete_request');
            IFEND;
            iop$client_delete_request (server_name, request_id, local_status);
            IF NOT local_status.normal AND (local_status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              osp$establish_condition_handler (^process_request_handler, {handle block exit} FALSE);
              pmp$long_term_wait (one_second, one_second);
              osp$disestablish_cond_handler;
            IFEND;
          UNTIL local_status.normal OR (local_status.condition <> dme$unable_to_lock_tape_table);
          request_submitted := FALSE;
          #SPOIL (request_submitted);
          EXIT /wait_loop/;
        ELSEIF status.condition = rme$response_unavailable THEN
          current_time := #FREE_RUNNING_CLOCK (0);
          elapsed_time := current_time - submittal_time;
          IF elapsed_time >= microseconds_per_millisecond THEN
            duration := server_timeout - (elapsed_time DIV microseconds_per_millisecond);
            IF duration > 0 THEN
              status.normal := TRUE;
              CYCLE /wait_loop/;
            ELSE
              rmp$log_debug_integer (' TIMEOUT - current_time   (Us): ', current_time);
              rmp$log_debug_integer (' TIMEOUT - submittal_time (Us): ', submittal_time);
              rmp$log_debug_integer (' TIMEOUT - elapsed_time   (Us): ', elapsed_time);
              osp$set_status_condition (rme$synchronization_error, status);
              debug_message_logged := FALSE;
              REPEAT
                IF NOT debug_message_logged THEN
                  rmp$log_debug_message (' Calling iop$client_cancel_request');
                IFEND;
                iop$client_cancel_request (server_name, sfid, local_status);
                IF NOT local_status.normal AND (local_status.condition = dme$unable_to_lock_tape_table) THEN
                  IF NOT debug_message_logged THEN
                    rmp$log_debug_message (' Waiting for tape table lock');
                    debug_message_logged := TRUE;
                  IFEND;
                  osp$establish_condition_handler (^process_request_handler, {handle block exit} FALSE);
                  pmp$long_term_wait (one_second, one_second);
                  osp$disestablish_cond_handler;
                IFEND;
              UNTIL local_status.normal OR (local_status.condition <> dme$unable_to_lock_tape_table);
              rmp$log_debug_message ('Called iop$client_cancel_request');
              rmp$log_debug_status (local_status);
            IFEND;
          ELSE
            status.normal := TRUE;
            CYCLE /wait_loop/;
          IFEND;
        ELSEIF status.condition = rme$request_not_found THEN
          osp$set_status_condition (rme$synchronization_error, status);
        IFEND;
      UNTIL NOT status.normal;
    ELSEIF status.condition = rme$client_request_active THEN
      debug_message_logged := FALSE;
      REPEAT
        IF NOT debug_message_logged THEN
          rmp$log_debug_message (' Calling iop$client_cancel_request');
        IFEND;
        iop$client_cancel_request (server_name, sfid, local_status);
        IF NOT local_status.normal AND (local_status.condition = dme$unable_to_lock_tape_table) THEN
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Waiting for tape table lock');
            debug_message_logged := TRUE;
          IFEND;
          osp$establish_condition_handler (^process_request_handler, {handle block exit} FALSE);
          pmp$long_term_wait (one_second, one_second);
          osp$disestablish_cond_handler;
        IFEND;
      UNTIL local_status.normal OR (local_status.condition <> dme$unable_to_lock_tape_table);
      rmp$log_debug_message ('Called iop$client_cancel_request');
      rmp$log_debug_status (local_status);
      osp$set_status_condition (rme$synchronization_error, status);
    IFEND;

  PROCEND process_request;?? OLDTITLE ??
?? NEWTITLE := 'release_element_from_job', EJECT ??

  PROCEDURE release_element_from_job
    (    sfid: gft$system_file_identifier;
         delete_request_from_vsn_queue: boolean;
     VAR assigned_mainframe_lun {input/output} : iot$logical_unit;
     VAR status: ost$status);

    VAR
      local_status: ost$status;

    status.normal := TRUE;
    IF assigned_mainframe_lun > 0 THEN
      rmp$log_debug_integer ('Attempting to release Logical Unit: ', assigned_mainframe_lun);
      rmp$release_tape_unit (sfid, assigned_mainframe_lun, delete_request_from_vsn_queue, status);
      rmp$log_debug_status (status);

      assigned_mainframe_lun := 0;
      #SPOIL (assigned_mainframe_lun);
    IFEND;
  PROCEND release_element_from_job;
?? OLDTITLE ??
?? NEWTITLE := 'select_element', EJECT ??

  PROCEDURE select_element
    (    acceptable_states: cmt$element_states;
         sfid: gft$system_file_identifier;
         last_choice_element: cmt$element_name;
         preferred_candidates: ^array [1 .. * ] of cmt$element_name;
         remaining_candidates: ^array [1 .. * ] of cmt$element_name;
         required_element: cmt$element_name;
         current_date_time_string: ost$string;
     VAR message_parameters: array [1 .. 2] of ^ost$message_parameter;
     VAR assigned_mainframe_lun: iot$logical_unit;
     VAR selected_element: cmt$element_name;
     VAR status: ost$status);

?? NEWTITLE := '  operator_menu_for_monopoly', EJECT ??

    PROCEDURE operator_menu_for_monopoly
      (    message_name: pmt$program_name;
           requested_evsn: rmt$external_vsn;
           requested_density: rmt$density;
       VAR status: ost$status);

      CONST
        number_of_choices = 2;

      VAR
        menu_parameters: array [1 .. 2] of ^string ( * ),
        parameter_names: ^ost$parameter_help_names,
        response: oft$number_of_choices,
        response_string: ost$string,
        terminate_reason: string (osc$max_string_size);

      status.normal := TRUE;

      menu_parameters [1] := ^rmv$densities [requested_density];
      menu_parameters [2] := ^requested_evsn;

      PUSH parameter_names: [1 .. number_of_choices];
      parameter_names^ [1] := 'CONTINUE_REQUEST';
      parameter_names^ [2] := 'TERMINATE_REQUEST';

      ofp$format_operator_menu (message_name, parameter_names, ^menu_parameters, number_of_choices,
            ofc$removable_media_operator, response, response_string, status);
      IF status.normal THEN
        CASE response OF
        = 1 = { operator wants to mount volume manually.}
          osp$set_status_condition (rme$volume_not_mounted, status);
        = 2 = { operator wants to terminate the  request. }
          IF response_string.size > 0 THEN
            terminate_reason := response_string.value (1, response_string.size);
          ELSE
            terminate_reason := 'your job required more robotic tape units ' CAT
                  'than are currently available.';
          IFEND;
          osp$set_status_abnormal (rmc$resource_management_id, dme$operator_stop, terminate_reason, status);
        ELSE
        CASEND;
      IFEND;

    PROCEND operator_menu_for_monopoly;

?? OLDTITLE ??
?? NEWTITLE := '  select_element_handler  ', EJECT ??

    PROCEDURE select_element_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR condition_status: ost$status);

      VAR
        ignore_status: ost$status;

      CASE condition.selector OF
      = ifc$interactive_condition =
        CASE condition.interactive_condition OF
        = ifc$pause_break, ifc$job_reconnect =
          ifp$invoke_pause_utility (ignore_status);
        = ifc$terminate_break =
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
          osp$set_status_from_condition (rmc$resource_management_id, condition, save_area, status,
                ignore_status);
          EXIT select_element;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
        CASEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;

    PROCEND select_element_handler;

?? OLDTITLE ??
?? NEWTITLE := '  validate_candidate', EJECT ??

    PROCEDURE validate_candidate
      (    acceptable_states: cmt$element_states;
           element: cmt$element_name;
           preferred_candidates: ^array [1 .. * ] of cmt$element_name,
           remaining_candidates: ^array [1 .. * ] of cmt$element_name;
       VAR status: ost$status);

      VAR
        i: integer;

      status.normal := TRUE;
      IF preferred_candidates <> NIL THEN
        FOR i := LOWERBOUND (preferred_candidates^) TO UPPERBOUND (preferred_candidates^) DO
          IF element = preferred_candidates^ [i] THEN
            debug_message_logged := FALSE;
            REPEAT
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Calling iop$validate_candidate_element');
              IFEND;
              iop$validate_candidate_element (element, acceptable_states, status);
              IF NOT status.normal THEN
                IF status.condition = dme$unable_to_lock_tape_table THEN
                  IF NOT debug_message_logged THEN
                    rmp$log_debug_message (' Waiting for tape table lock');
                    debug_message_logged := TRUE;
                  IFEND;
                  osp$establish_condition_handler (^select_element_handler, {handle block exit} FALSE);
                  pmp$long_term_wait (one_second, one_second);
                  osp$disestablish_cond_handler;
                IFEND;
              ELSE
                RETURN;
              IFEND;
            UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IFEND;
        FOREND;
      IFEND;

      IF remaining_candidates <> NIL THEN
        FOR i := LOWERBOUND (remaining_candidates^) TO UPPERBOUND (remaining_candidates^) DO
          IF element = remaining_candidates^ [i] THEN
            debug_message_logged := FALSE;
            REPEAT
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Calling iop$validate_candidate_element');
              IFEND;
              iop$validate_candidate_element (element, acceptable_states, status);
              IF NOT status.normal THEN
                IF status.condition = dme$unable_to_lock_tape_table THEN
                  IF NOT debug_message_logged THEN
                    rmp$log_debug_message (' Waiting for tape table lock');
                    debug_message_logged := TRUE;
                  IFEND;
                  osp$establish_condition_handler (^select_element_handler, {handle block exit} FALSE);
                  pmp$long_term_wait (one_second, one_second);
                  osp$disestablish_cond_handler;
                IFEND;
              ELSE
                RETURN;
              IFEND;
            UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IFEND;
        FOREND;
      IFEND;

      osp$set_status_abnormal (rmc$resource_management_id, rme$element_not_available, 'CLIENT_MOUNT_VOLUME',
            status);
    PROCEND validate_candidate;
?? OLDTITLE ??
?? EJECT ??

    VAR
      debug_message_logged: boolean,
      last_choice_encountered_once: boolean,
      message_name: clt$parameter_name;

    IF (preferred_candidates <> NIL) OR (remaining_candidates <> NIL) THEN
      IF required_element <> osc$null_name THEN
        validate_candidate (acceptable_states, required_element, preferred_candidates, remaining_candidates,
              status);
        IF status.normal THEN
          rmp$log_debug_message ('   Required_element-  volume not already mounted.');
          assign_element_to_job (sfid, acceptable_states, required_element, assigned_mainframe_lun, status);
          IF status.normal THEN
            selected_element := required_element;
          IFEND;
        IFEND;
      ELSE {select first available candidate}
        last_choice_encountered_once := FALSE;

      /select_loop/
        REPEAT
          debug_message_logged := FALSE;
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$select_best_element');
            IFEND;
            iop$select_best_element (preferred_candidates, remaining_candidates, selected_element, status);
            IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              osp$establish_condition_handler (^select_element_handler, {handle block exit} FALSE);
              pmp$long_term_wait (one_second, one_second);
              osp$disestablish_cond_handler;
            IFEND;
          UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          rmp$log_debug_message ('Called iop$select_best_element');
          rmp$log_debug_status (status);
          IF status.normal THEN
            IF selected_element = last_choice_element THEN
              IF NOT last_choice_encountered_once THEN
                last_choice_encountered_once := TRUE;
                message_name := 'WAIT_ROBOTIC_UNIT';
                message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
                message_parameters [2] := ^requested_evsn;
                rmp$put_job_status_display (message_name, ^message_parameters);
                wait (five_minutes);{Wait for another managed element to be returned.}
                CYCLE /select_loop/;
              IFEND;
            IFEND;
          ELSEIF status.condition = rme$robotic_element_monopoly THEN
            message_name := rmc$robotic_element_monopoly;
            operator_menu_for_monopoly (message_name, requested_evsn, requested_density, status);
            CYCLE /select_loop/;
          ELSEIF status.condition = rme$element_not_available THEN
            IF dmv$initialize_tape_volume.in_progress THEN
              EXIT /select_loop/;
            ELSE
              message_name := 'WAIT_ROBOTIC_UNIT';
              message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);
              message_parameters [2] := ^requested_evsn;
              rmp$put_job_status_display (message_name, ^message_parameters);
              wait (five_minutes) {Wait for robotic element availability} ;
              status.normal := TRUE;
              CYCLE /select_loop/;
            IFEND;
          ELSE
            EXIT /select_loop/;
          IFEND;
          rmp$log_debug_message ('   Selected candidate element.');
          assign_element_to_job (sfid, acceptable_states, selected_element, assigned_mainframe_lun, status);
          IF status.normal THEN
            EXIT /select_loop/;
          ELSE {we picked an unavailable element; try again}
            rmp$log_debug_message ('    Selected candidate became unavailable.');
            status.normal := TRUE;
          IFEND;
        UNTIL NOT status.normal;
      IFEND;
    ELSE
      osp$set_status_condition (rme$synchronization_error, status);
    IFEND;

  PROCEND select_element;
?? NEWTITLE := 'wait', EJECT ??

  PROCEDURE wait
    (    duration: 0 .. 0ffffffffffff(16));

    VAR
      ignore_status: ost$status;

    IF duration > 0 THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;

      rmp$log_debug_integer (' Entering wait for (msec) : ', duration);
      pmp$long_term_wait (duration, duration);
      rmp$log_debug_message (' Exiting wait');

      osp$set_job_signature_lock (rmv$job_tape_table_lock);
      osp$begin_subsystem_activity;
    IFEND;
  PROCEND wait;
?? OLDTITLE ??
MODEND rmm$manage_client_volumes_223;
