?? RIGHT := 110 ??
MODULE rmm$tape_services_223;

?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    one_second = 1000 {milliseconds};

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dme$tape_errors
*copyc dmt$tape_assignment_operation
*copyc fst$path_handle_name
*copyc gft$system_file_identifier
*copyc iot$robotic_server_entry
*copyc ost$name
*copyc ost$status
*copyc rme$condition_codes
?? POP ??
*copyc dmv$tape_job_lun_table_p
*copyc ifp$invoke_pause_utility
*copyc iop$extend_volume_list_in_rvl
*copyc osp$begin_subsystem_activity
*copyc osp$clear_job_signature_lock
*copyc osp$disestablish_cond_handler
*copyc osp$end_subsystem_activity
*copyc osp$establish_condition_handler
*copyc osp$set_job_signature_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc osp$test_signature_lock
*copyc pmp$continue_to_cause
*copyc pmp$long_term_wait
*copyc osv$job_pageable_heap
*copyc osv$lower_to_upper
*copyc rmp$log_debug_message
*copyc rmv$job_tape_table_lock
*copyc rmv$job_tape_table_p
?? OLDTITLE ??
?? NEWTITLE := 'dmp$convert_sfid_to_lun', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$convert_sfid_to_lun
    (    sfid: gft$system_file_identifier;
     VAR lun: iot$logical_unit;
     VAR status: ost$status);

*copy rmi$block_exit_handler
?? EJECT ??

    VAR
      lock_status: ost$signature_lock_status;

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

    osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
    IF lock_status = osc$sls_not_locked THEN
      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);
    IFEND;
    IF (dmv$tape_job_lun_table_p <> NIL) AND dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].
          slot_in_use THEN
      IF NOT dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].job_recovery_active THEN
        IF dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].lun <> 0 THEN
          lun := dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].lun;
        ELSE
          osp$set_status_abnormal (rmc$resource_management_id, dme$no_volume_mounted, '', status);
        IFEND;
      ELSE
        osp$set_status_abnormal (rmc$resource_management_id, dme$tape_file_needs_job_rec, '', status);
      IFEND;
    ELSE
      osp$set_status_abnormal (rmc$resource_management_id, dme$tape_not_assigned,
            'determine logical unit number', status);
    IFEND;

    IF lock_status = osc$sls_not_locked THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND dmp$convert_sfid_to_lun;
?? OLDTITLE ??
?? NEWTITLE := 'dmp$get_tape_volume_information', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$get_tape_volume_information
    (    sfid: gft$system_file_identifier;
     VAR number_of_volumes: amt$volume_number;
     VAR current_volume_number: amt$volume_number;
     VAR current_vsns: rmt$volume_descriptor;
     VAR density: rmt$density;
     VAR write_ring: rmt$write_ring;
     VAR requested_volume_attributes: iot$requested_volume_attributes;
     VAR volume_overflow_allowed: boolean;
     VAR label_type: amt$label_type;
     VAR status: ost$status);

*copy rmi$block_exit_handler
?? EJECT ??

    VAR
      lock_status: ost$signature_lock_status,
      lun_table_entry: ^dmt$tape_lun_table_entry;

    status.normal := TRUE;
    osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
    IF lock_status = osc$sls_not_locked THEN
      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);
    IFEND;

    IF (dmv$tape_job_lun_table_p <> NIL) AND (dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].
          slot_in_use) THEN
      lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];
      number_of_volumes := lun_table_entry^.number_of_vsns;
      current_volume_number := lun_table_entry^.current_vsn_index;
      current_vsns := lun_table_entry^.volume_list^ [lun_table_entry^.current_vsn_index];
      density := lun_table_entry^.density;
      write_ring := lun_table_entry^.write_ring;
      volume_overflow_allowed := lun_table_entry^.volume_overflow_allowed;
      requested_volume_attributes := lun_table_entry^.requested_volume_attributes;
      label_type := lun_table_entry^.label_type;
    ELSE
      osp$set_status_abnormal (rmc$resource_management_id, dme$tape_not_assigned, 'obtain tape volume list',
            status);
    IFEND;

    IF lock_status = osc$sls_not_locked THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND dmp$get_tape_volume_information;
?? OLDTITLE ??
?? NEWTITLE := 'dmp$get_tape_volume_list', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$get_tape_volume_list
    (    sfid: gft$system_file_identifier;
         volume_list: ^rmt$volume_list;
     VAR status: ost$status);

*copy rmi$block_exit_handler
?? EJECT ??

    VAR
      i: amt$volume_number,
      lock_status: ost$signature_lock_status;

    status.normal := TRUE;
    osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
    IF lock_status = osc$sls_not_locked THEN
      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);
    IFEND;

    IF (dmv$tape_job_lun_table_p <> NIL) AND (dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].
          slot_in_use) THEN
      IF volume_list <> NIL THEN
        FOR i := 1 TO UPPERBOUND (volume_list^) DO
          volume_list^ [i] := dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].volume_list^ [i];
        FOREND;
      IFEND;
    ELSE
      osp$set_status_abnormal (rmc$resource_management_id, dme$tape_not_assigned,
            'obtain tape volume information', status);
    IFEND;

    IF lock_status = osc$sls_not_locked THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND dmp$get_tape_volume_list;
?? OLDTITLE ??
?? NEWTITLE := 'dmp$replace_tape_vsn_list', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$replace_tape_vsn_list
    (    sfid: gft$system_file_identifier;
         p_volume_list: {input} ^rmt$volume_list;
         volume_overflow_allowed: boolean;
     VAR status: ost$status);

*copy rmi$block_exit_handler
?? EJECT ??
    VAR
      lock_status: ost$signature_lock_status;

    status.normal := TRUE;
    osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
    IF lock_status = osc$sls_not_locked THEN
      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);
    IFEND;

    dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].volume_overflow_allowed :=
          volume_overflow_allowed;
    IF p_volume_list <> NIL THEN
      dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].current_vsn_index := 1;
      dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].
            number_of_vsns := UPPERBOUND (p_volume_list^);
      FREE dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].volume_list IN osv$job_pageable_heap^;
      ALLOCATE dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].volume_list:
            [1 .. UPPERBOUND (p_volume_list^)] IN osv$job_pageable_heap^;
      dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index].volume_list^ := p_volume_list^;
    IFEND;

    IF lock_status = osc$sls_not_locked THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND dmp$replace_tape_vsn_list;

?? OLDTITLE ??
?? NEWTITLE := 'dmp$update_tape_vsn_list', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$update_tape_vsn_list
    (    sfid: gft$system_file_identifier;
         file: fst$path_handle_name;
         volume_descriptor: rmt$volume_descriptor;
         requested_volume_attributes: iot$requested_volume_attributes;
         source_pool: ost$name;
         source_pool_location: ost$name;
         tape_assignment_operation: dmt$tape_assignment_operation;
     VAR status: ost$status);

*copy rmi$block_exit_handler

?? NEWTITLE := '  update_tape_vsn_list_handler  ', EJECT ??

    PROCEDURE update_tape_vsn_list_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,
        ignore_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_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$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 dmp$update_tape_vsn_list;
        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 update_tape_vsn_list_handler;

?? OLDTITLE ??
    VAR
      debug_message_logged: boolean,
      lun_table_entry: ^dmt$tape_lun_table_entry,
      lock_status: ost$signature_lock_status,
      vol_descriptor: rmt$volume_descriptor;

    status.normal := TRUE;
    osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
    IF lock_status = osc$sls_not_locked THEN
      osp$establish_condition_handler (^update_tape_vsn_list_handler, {handle block exit} TRUE);
      osp$begin_subsystem_activity;
      osp$set_job_signature_lock (rmv$job_tape_table_lock);
    IFEND;

    lun_table_entry := ^dmv$tape_job_lun_table_p^.tape_file^ [sfid.file_entry_index];
    #TRANSLATE (osv$lower_to_upper, volume_descriptor.external_vsn, vol_descriptor.external_vsn);
    #TRANSLATE (osv$lower_to_upper, volume_descriptor.recorded_vsn, vol_descriptor.recorded_vsn);

    CASE tape_assignment_operation OF
    = dmc$advance_to_next_tape_volume =
      lun_table_entry^.volume_list^ [lun_table_entry^.current_vsn_index + 1].recorded_vsn :=
            vol_descriptor.recorded_vsn;
      lun_table_entry^.volume_list^ [lun_table_entry^.current_vsn_index + 1].external_vsn :=
            vol_descriptor.external_vsn;
      lun_table_entry^.requested_volume_attributes := requested_volume_attributes;
      lun_table_entry^.source_pool := source_pool;
      lun_table_entry^.source_pool_location := source_pool_location;

      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, vol_descriptor.external_vsn, vol_descriptor.recorded_vsn,
              requested_volume_attributes, lun_table_entry^.current_vsn_index + 1, 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);

    = dmc$assign_initial_tape_volume =
      lun_table_entry^.current_vsn_index := 1;
      lun_table_entry^.volume_list^ [1].recorded_vsn := vol_descriptor.recorded_vsn;
      lun_table_entry^.volume_list^ [1].external_vsn := vol_descriptor.external_vsn;
      lun_table_entry^.requested_volume_attributes := requested_volume_attributes;

      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, vol_descriptor.external_vsn, vol_descriptor.recorded_vsn,
              requested_volume_attributes, 1, 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);

    = dmc$reset_tape_volume_list =
      lun_table_entry^.volume_list^ [1].recorded_vsn := vol_descriptor.recorded_vsn;
      lun_table_entry^.volume_list^ [1].external_vsn := vol_descriptor.external_vsn;
      lun_table_entry^.requested_volume_attributes := requested_volume_attributes;

      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, vol_descriptor.external_vsn, vol_descriptor.recorded_vsn,
              requested_volume_attributes, 1, 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);

    = dmc$extend_tape_volume_list =
      rmp$extend_volume_list (lun_table_entry, status);
      lun_table_entry^.volume_list^ [lun_table_entry^.current_vsn_index + 1].recorded_vsn :=
            vol_descriptor.recorded_vsn;
      lun_table_entry^.volume_list^ [lun_table_entry^.current_vsn_index + 1].external_vsn :=
            vol_descriptor.external_vsn;
      lun_table_entry^.requested_volume_attributes := requested_volume_attributes;

      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, vol_descriptor.external_vsn, vol_descriptor.recorded_vsn,
              requested_volume_attributes, lun_table_entry^.current_vsn_index + 1, 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);

    ELSE
    CASEND;

    IF lock_status = osc$sls_not_locked THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND dmp$update_tape_vsn_list;
?? OLDTITLE ??
?? NEWTITLE := 'rmp$extend_volume_list', EJECT ??

  PROCEDURE [XDCL] rmp$extend_volume_list
    (    lun_table_entry: ^dmt$tape_lun_table_entry;
     VAR status: ost$status);

*copy rmi$block_exit_handler
?? EJECT ??
    VAR
      free_vsn_list: ^rmt$volume_list,
      lock_status: ost$signature_lock_status,
      vsn_list_index: integer,
      new_vsn_list: ^rmt$volume_list;

    status.normal := TRUE;
    osp$test_signature_lock (rmv$job_tape_table_lock, lock_status);
    IF lock_status = osc$sls_not_locked THEN
      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);
    IFEND;

    ALLOCATE new_vsn_list: [1 .. lun_table_entry^.number_of_vsns + 1] IN osv$job_pageable_heap^;
    FOR vsn_list_index := 1 TO lun_table_entry^.number_of_vsns DO
      new_vsn_list^ [vsn_list_index].external_vsn := lun_table_entry^.volume_list^ [vsn_list_index].
            external_vsn;
      new_vsn_list^ [vsn_list_index].recorded_vsn := lun_table_entry^.volume_list^ [vsn_list_index].
            recorded_vsn;
    FOREND;
    new_vsn_list^ [lun_table_entry^.number_of_vsns + 1].external_vsn := ' ';
    new_vsn_list^ [lun_table_entry^.number_of_vsns + 1].recorded_vsn := ' ';

    free_vsn_list := lun_table_entry^.volume_list;
    lun_table_entry^.volume_list := new_vsn_list;
    FREE free_vsn_list IN osv$job_pageable_heap^;

    lun_table_entry^.number_of_vsns := lun_table_entry^.number_of_vsns + 1;

    IF lock_status = osc$sls_not_locked THEN
      osp$clear_job_signature_lock (rmv$job_tape_table_lock);
      osp$end_subsystem_activity;
      osp$disestablish_cond_handler;
    IFEND;

  PROCEND rmp$extend_volume_list;
?? OLDTITLE ??
MODEND rmm$tape_services_223;
