?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Resource Management : Reserve and release tape units to/from a job', EJECT ??
MODULE rmm$manage_reservations_223;

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmt$element_name
*copyc cmt$element_states
*copyc dme$tape_errors
*copyc gft$system_file_identifier
*copyc amt$label_type
*copyc oss$job_pageable
*copyc oss$job_paged_literal
*copyc oss$mainframe_paged_literal
*copyc ost$status
*copyc rmc$reserve_tape
*copyc rmd$tape_declarations
*copyc rme$condition_codes
*copyc rmt$density
*copyc rmt$external_vsn
*copyc rmt$job_tape_table
*copyc rmt$recorded_vsn
*copyc rmt$supported_tape_densities

?? POP ??
*copyc clp$convert_integer_to_string
*copyc clp$convert_string_to_integer
*copyc clp$get_date_time_string
*copyc dmp$acquire_tape_resource
*copyc dmp$return_tape_resource
*copyc ifp$invoke_pause_utility
*copyc iop$assign_tape_unit
*copyc iop$get_density_states
*copyc iop$get_selected_element
*copyc iop$release_tape_unit
*copyc ofp$display_status_message
*copyc ofp$format_operator_menu
*copyc osp$append_status_parameter
*copyc osp$begin_subsystem_activity
*copyc osp$clear_job_signature_lock
*copyc osp$clear_wait_message
*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$test_signature_lock
*copyc pmp$continue_to_cause
*copyc pmp$long_term_wait
*copyc pmp$wait
*copyc rmp$log_debug_message
*copyc rmp$log_debug_status
*copyc rmp$put_job_status_display
*copyc sfp$update_job_limit_accum
*copyc dmv$tape_job_lun_table_p
*copyc osv$job_pageable_heap
*copyc osv$lower_to_upper
?? OLDTITLE ??
?? NEWTITLE := 'Global Variables Declared by This Module', EJECT ??

  CONST
    one_second = 1000 {milliseconds},
    thirty_seconds = 30000 {milliseconds};

  VAR
    rmv$job_tape_table_default: [XDCL, READ, oss$mainframe_paged_literal] rmt$job_tape_table :=
          [FALSE, FALSE, [0, 0, 0, 0], [0, 0, 0, 0]],
    rmv$job_tape_table_lock: [XDCL, STATIC, oss$job_pageable] ost$signature_lock := [0],
    rmv$job_tape_table_p: [XDCL, STATIC, oss$job_pageable] ^rmt$job_tape_table := NIL,

?? FMT (FORMAT := OFF) ??
    implicit_reservation: [READ, oss$job_paged_literal] array [rmt$supported_tape_densities] of
          rmt$tape_reservation := [
          [{rmc$800} 1, {rmc$1600} 0, {rmc$6250} 0, {rmc$38000} 0],
          [{rmc$800} 0, {rmc$1600} 1, {rmc$6250} 0, {rmc$38000} 0],
          [{rmc$800} 0, {rmc$1600} 0, {rmc$6250} 1, {rmc$38000} 0],
          [{rmc$800} 0, {rmc$1600} 0, {rmc$6250} 0, {rmc$38000} 1]];
?? FMT (FORMAT := ON) ??
?? OLDTITLE ??
?? NEWTITLE := 'rmp$assign_tape_unit', EJECT ??

  PROCEDURE [XDCL, #GATE] rmp$assign_tape_unit
    (    sfid: gft$system_file_identifier;
         element_name: cmt$element_name;
         acceptable_states: cmt$element_states;
         label_type: amt$label_type;
     VAR logical_unit: iot$logical_unit;
     VAR status: ost$status);

    VAR
      debug_message_logged: boolean;

?? OLDTITLE ??
?? EJECT ??

  debug_message_logged := FALSE;
  REPEAT
    IF NOT debug_message_logged THEN
      rmp$log_debug_message (' Calling iop$assign_tape_unit');
    IFEND;
    iop$assign_tape_unit (sfid, element_name, acceptable_states, label_type, logical_unit, 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);
  rmp$log_debug_message (' Exiting rmp$assign_tape_unit');
  rmp$log_debug_status (status);
PROCEND rmp$assign_tape_unit;

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

PROCEDURE [XDCL, #GATE] rmp$clear_explicit_reserve
  (    reservation: rmt$tape_reservation;
   VAR status: ost$status);

?? NEWTITLE := '  clear_explicit_reserve_handler', EJECT ??
  PROCEDURE clear_explicit_reserve_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,
      lock_status: ost$signature_lock_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 rmp$clear_explicit_reserve;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
      CASEND;
    = pmc$block_exit_processing =
      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;
    ELSE
      pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
    CASEND;
  PROCEND clear_explicit_reserve_handler;
?? OLDTITLE ??

?? EJECT ??

*copy rmi$block_exit_handler
?? EJECT ??

  VAR
    count_of_units_released: integer,
    debug_message_logged: boolean,
    density: rmt$density,
    reserved_units: integer,
    released_reservation: rmt$tape_reservation;

{
{ NOTE - THIS PROCEDURE MUST NOT BE CALLED WHEN PERFORMING AN INITIALIZE_TAPE_VOLUME.
{

  status.normal := TRUE;

/job_tables_interlocked/
  BEGIN

    osp$establish_condition_handler (^clear_explicit_reserve_handler, {handle block exit} TRUE);
    osp$begin_subsystem_activity;
    osp$set_job_signature_lock (rmv$job_tape_table_lock);

    IF (rmv$job_tape_table_p <> NIL) AND (rmv$job_tape_table_p^.explicit_reservation) THEN
      FOR density := rmc$800 TO rmc$maximum_density DO
        IF reservation [density] <> UPPERVALUE (reservation [density]) THEN
          IF reservation [density] <= rmv$job_tape_table_p^.reserved_unit_count [density] THEN
            released_reservation [density] := reservation [density];
          ELSE
            osp$set_status_condition (dme$release_exceeds_reserve, status);
            EXIT /job_tables_interlocked/;
          IFEND;
        ELSE
          released_reservation [density] := rmv$job_tape_table_p^.reserved_unit_count [density];
        IFEND;
        IF released_reservation [density] > rmv$job_tape_table_p^.reserved_unit_count [density] -
              rmv$job_tape_table_p^.assigned_unit_count [density] THEN
          osp$set_status_condition (dme$release_active_tape, status);
          EXIT /job_tables_interlocked/;
        IFEND;

      FOREND;

      IF NOT rmv$job_tape_table_p^.job_recovery_active THEN
        debug_message_logged := FALSE;
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling dmp$return_tape_resource');
          IFEND;
          dmp$return_tape_resource (released_reservation, 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$clear_job_signature_lock (rmv$job_tape_table_lock);
            osp$end_subsystem_activity;
            pmp$long_term_wait (one_second, one_second);
            osp$begin_subsystem_activity;
            osp$set_job_signature_lock (rmv$job_tape_table_lock);
          IFEND;
        UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
      IFEND;

      reserved_units := 0;
      FOR density := rmc$800 TO rmc$maximum_density DO
        rmv$job_tape_table_p^.reserved_unit_count [density] :=
              rmv$job_tape_table_p^.reserved_unit_count [density] - released_reservation [density];
        reserved_units := reserved_units + rmv$job_tape_table_p^.reserved_unit_count [density];
      FOREND;
      IF reserved_units = 0 THEN
        FREE rmv$job_tape_table_p IN osv$job_pageable_heap^;
      IFEND;
{ Adjust magnetic tape job limit accumulator.

      count_of_units_released := -(released_reservation [rmc$800] + released_reservation [rmc$1600] +
            released_reservation [rmc$6250] + released_reservation [rmc$38000]);
      sfp$update_job_limit_accum (avc$magnetic_tape_limit_name, count_of_units_released,
            sfc$incremental_update, status);
    IFEND;

  END /job_tables_interlocked/;

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

PROCEND rmp$clear_explicit_reserve;
?? OLDTITLE ??
?? NEWTITLE := 'rmp$clear_implicit_reserve', EJECT ??

PROCEDURE [XDCL] rmp$clear_implicit_reserve
  (    density: rmt$density;
   VAR status: ost$status);

*copy rmi$block_exit_handler
{
{ NOTE - THIS PROCEDURE MUST NOT BE CALLED WHEN PERFORMING AN INITIALIZE_TAPE_VOLUME.
{
  status.normal := TRUE;
  osp$establish_condition_handler (^rmp$block_exit_handler, {handle block exit} TRUE);
  osp$begin_subsystem_activity;
  osp$set_job_signature_lock (rmv$job_tape_table_lock);

  IF (density >= rmc$800) AND (density <= rmc$38000) THEN
    IF (rmv$job_tape_table_p <> NIL) AND (NOT rmv$job_tape_table_p^.explicit_reservation) THEN
      IF rmv$job_tape_table_p^.assigned_unit_count [density] > 0 THEN
        osp$set_status_condition (dme$release_active_tape, status);
      ELSE
        sfp$update_job_limit_accum (avc$magnetic_tape_limit_name, {count_of_units_released} - 1,
              sfc$incremental_update, status);
        FREE rmv$job_tape_table_p IN osv$job_pageable_heap^;
      IFEND;
    IFEND;
  ELSE
    osp$set_status_condition (dme$density_not_supported, status);
  IFEND;

  IF status.normal THEN
    rmp$log_debug_message (' Implicit reserve cleared.');
  ELSE
    rmp$log_debug_message (' Implicit reserve not cleared.');
  IFEND;

PROCEND rmp$clear_implicit_reserve;
?? OLDTITLE ??
?? NEWTITLE := 'rmp$get_selected_element', EJECT ??

PROCEDURE [XDCL] rmp$get_selected_element
  (    sfid: gft$system_file_identifier;
       external_vsn: rmt$external_vsn;
       recorded_vsn: rmt$recorded_vsn;
       density: rmt$density;
   VAR element_name: cmt$element_name;
   VAR status: ost$status);

    VAR
      debug_message_logged: boolean;

?? NEWTITLE := '  get_selected_element_handler', EJECT ??

  PROCEDURE get_selected_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 rmp$get_selected_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 get_selected_element_handler;

?? OLDTITLE ??
?? EJECT ??

  debug_message_logged := FALSE;
  REPEAT
    IF NOT debug_message_logged THEN
      rmp$log_debug_message (' Calling iop$get_selected_element');
    IFEND;
    iop$get_selected_element (sfid, external_vsn, recorded_vsn, density, element_name, 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 (^get_selected_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);

PROCEND rmp$get_selected_element;

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

PROCEDURE [XDCL, #GATE] rmp$recover_job_tape_table
  (VAR job_has_tapes_assigned: boolean;
   VAR fatal_reserve_error: boolean);

  VAR
    count: integer,
    debug_message_logged: boolean,
    density: rmt$density,
    i: iot$no_of_tape_units,
    reserve_complete: boolean,
    reservation: rmt$tape_reservation,
    status: ost$status;

?? NEWTITLE := '  recover_job_tape_table_handler', EJECT ??

  PROCEDURE recover_job_tape_table_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 rmp$recover_job_tape_table;
      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 recover_job_tape_table_handler;

?? OLDTITLE ??
?? EJECT ??

  job_has_tapes_assigned := FALSE;
  fatal_reserve_error := FALSE;

  IF dmv$tape_job_lun_table_p <> NIL THEN { possible tapes assigned
    FOR i := 1 TO UPPERBOUND (dmv$tape_job_lun_table_p^.tape_file^) DO
      IF dmv$tape_job_lun_table_p^.tape_file^ [i].slot_in_use THEN
        IF dmv$tape_job_lun_table_p^.tape_file^ [i].lun <> 0 THEN { tape is mounted
          dmv$tape_job_lun_table_p^.tape_file^ [i].lun := 0; { invalidate logical unit number
          dmv$tape_job_lun_table_p^.tape_file^ [i].job_recovery_active := TRUE;
          job_has_tapes_assigned := TRUE;
        IFEND;
      IFEND;
    FOREND;
  IFEND;

  IF rmv$job_tape_table_p <> NIL THEN { job had tapes reserved
    rmv$job_tape_table_p^.job_recovery_active := TRUE;
    IF rmv$job_tape_table_p^.explicit_reservation THEN
      count := 0;
      FOR density := rmc$800 TO rmc$maximum_density DO
        reservation [density] := rmv$job_tape_table_p^.reserved_unit_count [density];
        count := count + reservation [density];
      FOREND;
      IF count > 0 THEN { job had explicit reserves - attempt to reclaim reserves
        debug_message_logged := FALSE;
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling dmp$acquire_tape_resource');
          IFEND;
          dmp$acquire_tape_resource (reservation, reserve_complete, 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 (^recover_job_tape_table_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 NOT reserve_complete OR NOT status.normal THEN

{ Reserve could not be done at this time.  This can be caused by one of the following:
{  1.  Tape units that were ON before the system failed are now OFF or DOWN.  The job will
{      still recover and attempt to reclaim the reserves when the first tape operation is
{      performed.  At that time, an operator menu will appear if the condition still exists.
{  2.  Waiting for tapes reserved by other jobs.  This condition should never occur here unless
{      the number of ON tape drives is less now that before the system failure.  The job will
{      still recover and attempt to reclaim the reserves when the first tape operation is
{      performed.  At that time, the job will wait for other jobs reserves to be released.
{  3.  There are physically less tape drives now that before the system failure.  In this case
{      the job will NOT recover since it can never reclaim the reserves and proceed.

          IF NOT status.normal THEN
            IF NOT (status.condition = dme$not_enough_in_on_state) THEN
              fatal_reserve_error := TRUE;
            IFEND;
          IFEND;
          RETURN;
        IFEND;
      IFEND;
    IFEND;
{ Reserves were successfully reclaimed or reserve was implicit.
{ Set job_tape_table flag to FALSE to indicate this.
    rmv$job_tape_table_p^.job_recovery_active := FALSE;
  IFEND;

PROCEND rmp$recover_job_tape_table;

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

PROCEDURE [XDCL, #GATE] rmp$release_tape_unit
  (    sfid: gft$system_file_identifier;
       logical_unit: iot$logical_unit;
       delete_request_from_vsn_queue: boolean;
   VAR status: ost$status);

    VAR
      debug_message_logged: boolean;

?? OLDTITLE ??
?? EJECT ??

  debug_message_logged := FALSE;
  REPEAT
    IF NOT debug_message_logged THEN
      rmp$log_debug_message (' Calling iop$release_tape_unit');
    IFEND;
    iop$release_tape_unit (sfid, logical_unit, delete_request_from_vsn_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$wait (one_second, one_second);
    IFEND;
  UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);

  rmp$log_debug_message (' Exiting rmp$release_tape_unit');
  rmp$log_debug_status (status);

PROCEND rmp$release_tape_unit;

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

PROCEDURE [XDCL, #GATE] rmp$set_explicit_reserve
  (    reservation: rmt$tape_reservation;
   VAR status: ost$status);

  VAR
    allocated_job_tape_table: boolean,
    original_message: oft$display_message,
    reserve_complete: boolean,
    updated_job_limits: boolean;

?? NEWTITLE := '  abnormal_cleanup', EJECT ??

  PROCEDURE abnormal_cleanup;

    VAR
      debug_message_logged: boolean,
      local_status: ost$status,
      wait_message_displayed: boolean;

?? OLDTITLE ??
?? NEWTITLE := '  abnormal_cleanup_handler', EJECT ??
  PROCEDURE abnormal_cleanup_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 rmp$set_explicit_reserve;
      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 abnormal_cleanup_handler;

    IF allocated_job_tape_table THEN
      FREE rmv$job_tape_table_p IN osv$job_pageable_heap^;
      allocated_job_tape_table := FALSE;
      #SPOIL (allocated_job_tape_table);
    IFEND;

    IF reserve_complete THEN
      debug_message_logged := FALSE;
      REPEAT
        IF NOT debug_message_logged THEN
          rmp$log_debug_message (' Calling dmp$return_tape_resource');
        IFEND;
        dmp$return_tape_resource (reservation, local_status);
        IF NOT local_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 (^abnormal_cleanup_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);
      reserve_complete := FALSE;
      #SPOIL (reserve_complete);
    IFEND;

    IF updated_job_limits THEN
      sfp$update_job_limit_accum (avc$magnetic_tape_limit_name, -count_of_units_requested,
            sfc$incremental_update, ignore_status);
      updated_job_limits := FALSE;
      #SPOIL (updated_job_limits);
    IFEND;

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

  PROCEND abnormal_cleanup;

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

  PROCEDURE operator_menu_for_tape_reserve
    (    required_resources: rmt$tape_reservation;
     VAR status: ost$status);

    CONST
      default_reserve_wait = 30,
      number_of_choices = 3,
      number_of_parameters = 8;

?? FMT (FORMAT := OFF) ??
        VAR
          density_strings: [READ, oss$job_paged_literal] array [rmc$800 .. rmc$maximum_density] OF record
            value: string (10),
            blanks_required: 0 .. 3,
          recend := [
                {} ['MT9$800   ', 3],
                {} ['MT9$1600  ', 2],
                {} ['MT9$6250  ', 2],
                {} ['MT18$38000', 0]];

?? FMT (FORMAT := ON) ??

    VAR
      counts_string: string (20),
      current_date_time_string: ost$string,
      debug_message_logged: boolean,
      density: rmt$density,
      density_states: array [rmc$800 .. rmc$maximum_density] of iot$density_states,
      duration: integer,
      ignore_status: ost$status,
      int: clt$integer,
      length: integer,
      local_status: ost$status,
      menu_parameters: array [1 .. number_of_parameters] of ^ost$message_parameter,
      message_parameters: array [1 .. 2] of ^ost$message_parameter,
      minutes_to_wait: integer,
      parameter_index: 1 .. number_of_parameters,
      parameter_names: ^ost$parameter_help_names,
      response: oft$number_of_choices,
      response_string: ost$string,
      start_time: integer,
      terminate_reason: string (ofc$max_send_message),
      wait_time: ost$string;

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

  PROCEDURE operator_menu_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 rmp$set_explicit_reserve;
      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 operator_menu_lock_handler;

    status.normal := TRUE;

    FOR parameter_index := 1 TO number_of_parameters DO
      menu_parameters [parameter_index] := NIL;
    FOREND;

    debug_message_logged := FALSE;
    REPEAT
      IF NOT debug_message_logged THEN
        rmp$log_debug_message (' Calling iop$get_density_states');
      IFEND;
      iop$get_density_states (density_states, 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 (^operator_menu_lock_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);

    parameter_index := 1;
    FOR density := rmc$800 TO rmc$maximum_density DO
      IF required_resources [density] > 0 THEN
        STRINGREP (counts_string, length, required_resources [density]:3, ' ':4,
              density_states [density].on_count:3, ' ':2, density_states [density].down_count:3, ' ':2,
              density_states [density].off_count:3);
        menu_parameters [parameter_index] := ^density_strings [density].value;
        parameter_index := parameter_index + 1;
        PUSH menu_parameters [parameter_index]: [length + density_strings [density].blanks_required];
        menu_parameters [parameter_index]^ := ' ';
        menu_parameters [parameter_index]^ (density_strings [density].blanks_required + 1, * ) :=
              counts_string (1, length);
        parameter_index := parameter_index + 1;
      IFEND;
    FOREND;

    PUSH parameter_names: [1 .. number_of_choices];
    parameter_names^ [1] := 'ALLOW_RESERVATION';
    parameter_names^ [2] := 'DISALLOW_RESERVATION';
    parameter_names^ [3] := 'WAIT_ON_RESERVATION';

    ofp$format_operator_menu (rmc$reserve_tape, parameter_names, ^menu_parameters, number_of_choices,
          ofc$removable_media_operator, response, response_string, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    CASE response OF
    = 1 =
      { Operator wants to retry reservation attempt}
    = 2 = { Terminate request}
      IF response_string.size > 0 THEN
        terminate_reason := response_string.value (1, response_string.size);
      ELSE
        terminate_reason := 'additional tape units cannot be turned ON'
      IFEND;
      osp$set_status_abnormal (rmc$resource_management_id, dme$operator_reserve_stop, terminate_reason,
            status);
    = 3 = { operator wants to wait for a specified time and then retry. }
      minutes_to_wait := default_reserve_wait;
      IF response_string.size > 0 THEN
        clp$convert_string_to_integer (response_string.value (1, response_string.size), int, local_status);
        IF local_status.normal THEN
          minutes_to_wait := int.value;
        IFEND;
      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);

      message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);

      clp$convert_integer_to_string (minutes_to_wait, {radix} 10,
            {include_radix_specifier} FALSE, wait_time, ignore_status);
      message_parameters [2] := ^wait_time.value (1, wait_time.size);
      message_name := 'WAIT_UNITS_UNAVAILABLE';
      rmp$put_job_status_display (message_name, ^message_parameters);
      start_time := #FREE_RUNNING_CLOCK (0);
      duration := minutes_to_wait * (60 * 1000);
      WHILE duration > 0 DO
        pmp$long_term_wait (duration, duration);
        duration := duration - (#FREE_RUNNING_CLOCK (0) - start_time);
      WHILEND;
      wait_message_displayed := TRUE;
      osp$clear_wait_message (original_message, wait_message_displayed);
    ELSE
    CASEND;

  PROCEND operator_menu_for_tape_reserve;

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

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

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

    CASE condition.selector OF

    = pmc$block_exit_processing =

      osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
      IF lock_status = osc$sls_not_locked THEN
        osp$begin_subsystem_activity;
        osp$set_job_signature_lock (rmv$job_tape_table_lock);
      IFEND;
      IF lock_status <> osc$sls_locked_by_another_task THEN
        abnormal_cleanup;
        osp$clear_job_signature_lock (rmv$job_tape_table_lock);
        osp$end_subsystem_activity;
      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 rmp$set_explicit_reserve;
      = 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
        osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
        IF lock_status = osc$sls_not_locked THEN
          osp$begin_subsystem_activity;
          osp$set_job_signature_lock (rmv$job_tape_table_lock);
        IFEND;
        IF lock_status <> osc$sls_locked_by_another_task THEN
          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);

    ELSE
      pmp$continue_to_cause (pmc$execute_standard_procedure, condition_status);
    CASEND;

  PROCEND explicit_reserve_handler;

  VAR
    count_of_units_requested: integer,
    current_date_time_string: ost$string,
    debug_message_logged: boolean,
    density: rmt$density,
    ignore_status: ost$status,
    message_name: clt$parameter_name,
    message_parameters: array [1 .. 1] of ^string ( * ),
    wait_message_displayed: boolean;

{
{ NOTE - THIS PROCEDURE MUST NOT BE CALLED WHEN PERFORMING AN
{ INITIALIZE_TAPE_VOLUME.
{
  status.normal := TRUE;

  osp$get_current_display_message (original_message);

  allocated_job_tape_table := FALSE;

  reserve_complete := FALSE;

  count_of_units_requested := 0;

  FOR density := rmc$800 TO rmc$maximum_density DO
    IF reservation [density] < 0 THEN
      osp$set_status_condition (dme$invalid_resrel_count, status);
      RETURN;
    ELSE
      count_of_units_requested := count_of_units_requested + reservation [density];
    IFEND;
  FOREND;

  updated_job_limits := FALSE;

  #SPOIL (allocated_job_tape_table, count_of_units_requested, original_message, reserve_complete,
        updated_job_limits);

  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);

  message_parameters [1] := ^current_date_time_string.value (1, current_date_time_string.size);

?? EJECT ??
  osp$establish_condition_handler (^explicit_reserve_handler, {handle block exit} TRUE);
  osp$begin_subsystem_activity;
  osp$set_job_signature_lock (rmv$job_tape_table_lock);

/job_tables_interlocked/
  BEGIN

{ Determine if job tape table exists

    IF (rmv$job_tape_table_p = NIL) THEN
      ALLOCATE rmv$job_tape_table_p IN osv$job_pageable_heap^;
      allocated_job_tape_table := TRUE;
      #SPOIL (allocated_job_tape_table);
      rmv$job_tape_table_p^ := rmv$job_tape_table_default;
    ELSE
      IF NOT (rmv$job_tape_table_p^.job_recovery_active) THEN
        osp$set_status_condition (dme$multiple_reserve, status);
        EXIT /job_tables_interlocked/;
      IFEND;
    IFEND;

{ Adjust magnetic tape job accumulator count and check limits.

    IF NOT rmv$job_tape_table_p^.job_recovery_active THEN
      sfp$update_job_limit_accum (avc$magnetic_tape_limit_name, count_of_units_requested,
            sfc$incremental_update, status);
      IF status.normal THEN
        updated_job_limits := TRUE;
        #SPOIL (updated_job_limits);
      ELSE
        EXIT /job_tables_interlocked/;
      IFEND;
    IFEND;

  /reserve_tape_resources/
    REPEAT
      debug_message_logged := FALSE;
      REPEAT
        IF NOT debug_message_logged THEN
          rmp$log_debug_message (' Calling dmp$acquire_tape_resource');
        IFEND;
        dmp$acquire_tape_resource (reservation, reserve_complete, 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$clear_job_signature_lock (rmv$job_tape_table_lock);
          osp$end_subsystem_activity;
          pmp$long_term_wait (one_second, one_second);
          osp$begin_subsystem_activity;
          osp$set_job_signature_lock (rmv$job_tape_table_lock);
        IFEND;
      UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
      #SPOIL (reserve_complete);
      IF status.normal THEN
        IF NOT reserve_complete THEN
          osp$clear_job_signature_lock (rmv$job_tape_table_lock);
          osp$end_subsystem_activity;
          message_name := 'WAIT_UNITS_BUSY';
          rmp$put_job_status_display (message_name, ^message_parameters);
          pmp$long_term_wait (thirty_seconds, thirty_seconds);
          osp$begin_subsystem_activity;
          osp$set_job_signature_lock (rmv$job_tape_table_lock);
        IFEND;
      ELSEIF status.condition = dme$not_enough_in_on_state THEN
        osp$clear_job_signature_lock (rmv$job_tape_table_lock);
        osp$end_subsystem_activity;
        operator_menu_for_tape_reserve (reservation, status);
        osp$begin_subsystem_activity;
        osp$set_job_signature_lock (rmv$job_tape_table_lock);
      IFEND;
    UNTIL (NOT status.normal) OR reserve_complete;

  END /job_tables_interlocked/;

  IF status.normal THEN
    FOR density := rmc$800 TO rmc$maximum_density DO
      rmv$job_tape_table_p^.reserved_unit_count [density] := reservation [density];
    FOREND;
    rmv$job_tape_table_p^.explicit_reservation := TRUE;
    wait_message_displayed := TRUE;
    osp$clear_wait_message (original_message, wait_message_displayed);
  ELSE
    abnormal_cleanup;
  IFEND;

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

PROCEND rmp$set_explicit_reserve;

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

PROCEDURE [XDCL] rmp$set_implicit_reserve
  (    sfid: gft$system_file_identifier;
       density: rmt$density;
   VAR status: ost$status);

*copy rmi$block_exit_handler
?? EJECT ??

  VAR
    counter: rmt$density;

  status.normal := TRUE;
  osp$establish_condition_handler (^rmp$block_exit_handler, {handle block exit} TRUE);
  osp$begin_subsystem_activity;
  osp$set_job_signature_lock (rmv$job_tape_table_lock);
  IF (density >= rmc$800) AND (density <= rmc$maximum_density) THEN
    IF (rmv$job_tape_table_p = NIL) THEN
      ALLOCATE rmv$job_tape_table_p IN osv$job_pageable_heap^;
      rmv$job_tape_table_p^ := rmv$job_tape_table_default;
      sfp$update_job_limit_accum (avc$magnetic_tape_limit_name, {count_of_units_requested} 1,
            sfc$incremental_update, status);
      IF status.normal THEN
        rmv$job_tape_table_p^.explicit_reservation := FALSE;
        FOR counter := rmc$800 TO rmc$maximum_density DO
          rmv$job_tape_table_p^.reserved_unit_count [counter] := implicit_reservation [density] [counter];
        FOREND;
      IFEND;
    ELSE
      IF NOT rmv$job_tape_table_p^.job_recovery_active THEN
        osp$set_status_condition (dme$multiple_reserve, status);
      IFEND;
    IFEND;
  ELSE
    osp$set_status_condition (dme$density_not_supported, status);
  IFEND;

  IF status.normal THEN
    rmp$log_debug_message (' Implicit reserve set.');
  ELSE
    rmp$log_debug_message (' Implicit reserve not set.');
  IFEND;
  osp$clear_job_signature_lock (rmv$job_tape_table_lock);
  osp$end_subsystem_activity;
  osp$disestablish_cond_handler;
PROCEND rmp$set_implicit_reserve;

MODEND rmm$manage_reservations_223;
