?? NEWTITLE := 'NOS/VE: Disk Fault Tolerance (2DD)' ??
MODULE osm$disk_fault_tolerance_2dd;
?? RIGHT := 110 ??

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ame$put_program_actions
*copyc bat$default_handler_params
*copyc dmt$subfile_index
*copyc fsc$wait_msg_module_name
*copyc fsc$wait_undefined_condition
*copyc fst$access_condition_entry
*copyc fst$file_access_conditions
*copyc fst$file_reference
*copyc fst$path
*copyc fst$path_size
*copyc fst$volume_condition_list
*copyc oft$display_message
*copyc osc$max_status_message_lines
*copyc osc$max_system_message_modules
*copyc osd$exception_policies
*copyc osd$integer_limits
*copyc osd$virtual_address
*copyc ose$disk_ft_exceptions
*copyc oss$job_paged_literal
*copyc ost$caller_identifier
*copyc ost$ecp_exception_context
*copyc ost$message_parameters
*copyc ost$message_template
*copyc ost$name
*copyc ost$status
*copyc ost$status_message
*copyc ost$status_message_line
*copyc ost$status_message_line_count
*copyc pfe$error_condition_codes
*copyc pft$move_object_info
*copyc rmc$unspecified_file_class
*copyc rmt$mass_storage_class
*copyc rmt$volume_list
?? POP ??
*copyc amp$return
*copyc clp$convert_cyc_ref_to_cyc_sel
*copyc clp$convert_date_time_to_string
*copyc clp$trimmed_string_size
*copyc cmp$get_element_state_via_lun
*copyc cmp$get_ms_status_via_lun
*copyc cmp$get_ms_volumes
*copyc cmp$get_ms_volume_info
*copyc dfp$check_job_recovery
*copyc fsp$evaluate_file_reference
*copyc fsv$file_access_conditions
*copyc ifp$invoke_pause_utility
*copyc jmp$system_job
*copyc ofp$display_status_message
*copyc osp$append_status_file
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$clear_wait_message
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$establish_condition_handler
*copyc osp$find_applicable_policy
*copyc osp$find_parameter_prompt
*copyc osp$file_access_condition
*copyc osp$format_help_message
*copyc osp$get_access_condition_entry
*copyc osp$get_current_display_message
*copyc osp$get_file_criteria
*copyc osp$get_installed_policies
*copyc osp$get_login_user_criteria
*copyc osp$log_executed_policy
*copyc osp$r3_get_applicable_policy
*copyc osp$set_status_condition
*copyc osp$set_status_from_condition
*copyc osp$wait_on_condition
*copyc oss$task_private
*copyc osv$system_message_modules
*copyc pfp$convert_fs_to_pft$path
*copyc pfp$get_volumes_in_set
*copyc pfp$purge
*copyc pfp$r3_change
*copyc pfp$r3_get_move_obj_device_info
*copyc pfp$r3_physically_move_catalog
*copyc pfp$r3_release_data
*copyc pmp$cause_task_condition
*copyc pmp$continue_to_cause
*copyc pmp$delay
*copyc pmp$get_compact_date_time
*copyc pmp$get_microsecond_clock
*copyc pmp$get_task_cp_time
*copyc pmp$long_term_wait
*copyc pmp$wait
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??
?? NEWTITLE := '[XDCL], osv$initial_exception_context' ??

?? FMT (FORMAT := OFF) ??
  VAR
    osv$initial_exception_context: [XDCL, #GATE, READ, oss$job_paged_literal] ost$ecp_exception_context := [
         [{when_handler_status.normal} TRUE,
          [{exception_status.normal} TRUE],
           {file_access_condition} fsc$null_file_access_condition,
           {object_name} osc$null_name,
           {file_segment_isolated} FALSE,
           {file_segment} 0
          ],
          {allowed_access_conditions} -$fst$file_access_conditions [],
          {caller_will_retrieve_file} FALSE,
          [
          {file} osc$ecp_file_reference,
          {file_reference} NIL
          ],
          {force_wait} FALSE,
          {initial_call} TRUE,
          {logging_allowed} TRUE,
          {password} osc$null_name,
          {catalog_move_count} 0,
          [{condition_status.normal} TRUE],
          {raised_conditions} $fst$file_access_conditions [],
          {wait} TRUE,
          {wait_time} fsc$longest_wait_time,
          {catalog_object} FALSE,
          {elapsed_wait_time} 0
          ];

?? FMT (FORMAT := ON) ??

  VAR
    enforce_except_policies_active: [oss$task_private] boolean := FALSE,
    exception_information: [oss$task_private] ost$condition_information;

?? OLDTITLE ??
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] osp$enforce_exception_policies', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$enforce_exception_policies
    (VAR context {input, output} : ost$ecp_exception_context);

    VAR
      access_condition_entry: fst$access_condition_entry,
      actions: ost$ecp_actions,
      applicable_poll_frequency: ost$ecp_polling_frequency,
      caller_id: ost$caller_identifier,
      criteria: ost$ecp_criteria,
      cycle_selector: clt$cycle_selector,
      evaluated_file_reference: fst$evaluated_file_reference,
      initial_status: ost$status,
      pf_path: ^pft$path,
      ring3_caller: boolean,
      volume_condition_list: ^fst$volume_condition_list;

?? NEWTITLE := '  enforce_exit_handler', EJECT ??

    PROCEDURE enforce_exit_handler
      (    ignore_condition: pmt$condition;
           ignore_information: ^pmt$condition_information;
           ignore_save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      {Recursion is only of concern in ring 3 or less
      IF ring3_caller THEN
        enforce_except_policies_active := FALSE;
      IFEND;

    PROCEND enforce_exit_handler;
?? OLDTITLE ??
?? NEWTITLE := '  execute_exception_policy', EJECT ??

    PROCEDURE execute_exception_policy;

      VAR
        data_released: boolean,
        external_info: ^ost$condition_information,
        ignore_entry_found: boolean,
        local_status: ost$status,
        p_release_data_info: ^pft$release_data_info,
        recovery_occurred: boolean;

?? NEWTITLE := 'remove_damage_condition', EJECT ??

      PROCEDURE remove_damage_condition;

        VAR
          delete_damage_conditions: ^array [1 .. 1] of pft$change_descriptor,
          ignore_status: ost$status;

        PUSH delete_damage_conditions;
        delete_damage_conditions^ [1].change_type := pfc$delete_damage_change;
        delete_damage_conditions^ [1].delete_damage_condition :=
              $fst$cycle_damage_symptoms [fsc$respf_modification_mismatch];

        pfp$r3_change (pf_path^, cycle_selector.value, context.password, delete_damage_conditions^,
              ignore_status);

      PROCEND remove_damage_condition;
?? OLDTITLE ??
?? NEWTITLE := '  report_delete', EJECT ??

      PROCEDURE report_delete;

        VAR
          log_status: ost$status;

        osp$set_status_condition (ose$log_deletion, log_status);

        report_context (log_status);

        osp$log_executed_policy (log_status);
        osp$log_executed_policy (initial_status);

      PROCEND report_delete;
?? OLDTITLE ??
?? NEWTITLE := '  report_exit', EJECT ??

      PROCEDURE report_exit;

        VAR
          log_status: ost$status;

        IF context.logging_allowed THEN
          osp$set_status_condition (ose$log_exit, log_status);

          report_context (log_status);

          osp$log_executed_policy (log_status);
          osp$log_executed_policy (initial_status);
        IFEND;

      PROCEND report_exit;
?? OLDTITLE ??
?? NEWTITLE := '  report_release', EJECT ??

      PROCEDURE report_release
        (    release_info: pft$release_data_info);

        VAR
          date_value: clt$date_time,
          date_string: ost$string,
          ignore_status: ost$status,
          log_status: ost$status;

        IF release_info.valid_archive_entry_found THEN
          osp$set_status_condition (ose$log_matching_release, log_status);
          report_context (log_status);
        ELSE
          osp$set_status_condition (ose$log_non_matching_release, log_status);

          report_context (log_status);

          date_value.date_specified := TRUE;
          date_value.time_specified := TRUE;

          date_string.size := 1;
          date_string.value := '';
          date_value.value := release_info.old_data_modification_date_time;
          clp$convert_date_time_to_string (date_value, 'ISOD.MILLISECOND', date_string, ignore_status);
          osp$append_status_parameter (osc$status_parameter_delimiter, date_string.
                value (1, date_string.size), log_status);

          date_string.size := 1;
          date_string.value := '';
          date_value.value := release_info.new_data_modification_date_time;
          clp$convert_date_time_to_string (date_value, 'ISOD.MILLISECOND', date_string, ignore_status);
          osp$append_status_parameter (osc$status_parameter_delimiter, date_string.
                value (1, date_string.size), log_status);
        IFEND;

        osp$log_executed_policy (log_status);
        osp$log_executed_policy (initial_status);

      PROCEND report_release;
?? OLDTITLE ??
?? NEWTITLE := '  report_wait', EJECT ??

      PROCEDURE report_wait;

        VAR
          log_status: ost$status;

        IF (access_condition_entry.file_access_condition IN -$fst$file_access_conditions
              [fsc$cycle_busy, fsc$data_retrieval_required]) AND context.logging_allowed THEN
          osp$set_status_condition (ose$log_wait, log_status);

          report_context (log_status);

          osp$append_status_integer (osc$status_parameter_delimiter, (context.wait_time DIV 1000), 10,
                {include_radix_specifier} FALSE, log_status);

          osp$log_executed_policy (log_status);
          osp$log_executed_policy (initial_status);
        IFEND;

      PROCEND report_wait;
?? OLDTITLE ??
?? NEWTITLE := '  wait_on_condition', EJECT ??

      PROCEDURE wait_on_condition;

        CONST
          msec_per_sec = 1000;

        VAR
          display_status: ost$status,
          file_path: fst$path,
          ignore_status: ost$status,
          poll_time: 0 .. fsc$longest_wait_time,
          wait_message: oft$display_message;

        VAR
          original_display_message: oft$display_message,
          wait_message_displayed: boolean;

?? NEWTITLE := '    wait_handler', EJECT ??

        PROCEDURE wait_handler
          (    condition: pmt$condition;
               condition_information: ^pmt$condition_information;
               save_area: ^ost$stack_frame_save_area;
           VAR handler_status: ost$status);

          VAR
            local_status: ost$status;

          CASE condition.selector OF
          = pmc$block_exit_processing =
            osp$clear_wait_message (original_display_message, wait_message_displayed);
            #SPOIL (wait_message_displayed);
            context.wait := FALSE;
          = ifc$interactive_condition =
            CASE condition.interactive_condition OF
            = ifc$terminate_break =
              osp$set_status_from_condition ('AM', condition, save_area, context.condition_status,
                    local_status);
              pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
              EXIT wait_on_condition; {----->
            = ifc$pause_break, ifc$job_reconnect =
              ifp$invoke_pause_utility (local_status);
            ELSE
              pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
            CASEND;
          ELSE
            pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
          CASEND;

        PROCEND wait_handler;
?? OLDTITLE ??
?? EJECT ??
        wait_message_displayed := FALSE;
        #SPOIL (wait_message_displayed);

        IF context.wait_time > 0 THEN
          IF applicable_poll_frequency.specified THEN
            poll_time := applicable_poll_frequency.value * msec_per_sec;
          ELSE
            poll_time := access_condition_entry.polling_interval;
          IFEND;

          IF poll_time > context.wait_time THEN
            poll_time := context.wait_time;
          IFEND;

          osp$get_current_display_message (original_display_message);
          osp$establish_condition_handler (^wait_handler, TRUE);

          file_path := criteria.file;
          IF criteria.file = osc$null_name THEN
            file_path := '<file not isolated>';
          IFEND;

          osp$format_wait_message (^access_condition_entry, ^file_path, criteria.mass_storage_class,
                volume_condition_list, criteria.volume_list, wait_message);

          ofp$display_status_message (wait_message.text (1, wait_message.size), display_status);
          IF display_status.normal THEN
            wait_message_displayed := TRUE;
            #SPOIL (wait_message_displayed);
          IFEND;

          IF ring3_caller AND NOT (access_condition_entry.file_access_condition IN
                $fst$file_access_conditions [fsc$cycle_busy, fsc$data_restoration_required,
                fsc$data_retrieval_required, fsc$file_server_inactive]) THEN
            pmp$delay (poll_time, ignore_status);
          ELSE

{ An extra wait is done to allow for the server case, where a previous ready
{ task has inhibited the subsequent wait.

            pmp$long_term_wait (1, 1);
            pmp$long_term_wait (poll_time, poll_time);
          IFEND;

          context.elapsed_wait_time := poll_time;
          context.wait_time := context.wait_time - poll_time;
          context.wait := context.wait_time > 0;

          osp$clear_wait_message (original_display_message, wait_message_displayed);
          #SPOIL (wait_message_displayed);
          osp$disestablish_cond_handler;
        IFEND;

      PROCEND wait_on_condition;
?? OLDTITLE ??
?? EJECT ??
      data_released := FALSE;
      recovery_occurred := FALSE;

      IF access_condition_entry.user_defined_condition = osc$volume_unavailable_cond THEN
        dfp$check_job_recovery (recovery_occurred);
      IFEND;

      IF context.initial_call AND (osc$ecp_enable_matching_image IN actions) OR
            (osc$ecp_enable_nonmatch_image IN actions) THEN
        IF (fsp$path_element (^evaluated_file_reference, 1) ^ <> fsc$local) THEN
          PUSH p_release_data_info;
          p_release_data_info^.perform_changes := TRUE;
          p_release_data_info^.release_attached_cycle_data := TRUE;
          p_release_data_info^.update_last_release_date_time := TRUE;
          p_release_data_info^.valid_archive_entry_required := NOT (osc$ecp_enable_nonmatch_image IN actions);
          pfp$r3_release_data (pf_path^, cycle_selector.value, context.password, p_release_data_info,
                local_status);
          data_released := local_status.normal AND (NOT p_release_data_info^.cycle_attached);
          IF data_released THEN
            report_release (p_release_data_info^);
            IF NOT p_release_data_info^.valid_archive_entry_found THEN
              IF NOT (osc$ecp_set_damage_condition IN actions) THEN
                remove_damage_condition;
              IFEND;
            IFEND;
            {
            { Return a different status than the one provided by the caller to encourage retrieval.
            {
            osp$set_status_condition (pfe$cycle_data_resides_offline, context.condition_status);
            osp$append_status_parameter (osc$status_parameter_delimiter, criteria.
                  file (1, clp$trimmed_string_size (criteria.file)), context.condition_status);
            osp$append_status_integer (osc$status_parameter_delimiter, cycle_selector.value.cycle_number,
                  {radix} 10, {include_radix_specifier} FALSE, context.condition_status);
            {
            { Update the access_condition_entry to reflect the new condition and avoid subsequent
            { modification of this status variable by someone confused about the current condition
            {
            osp$get_access_condition_entry (context.condition_status, access_condition_entry,
                  ignore_entry_found);
          IFEND;
        IFEND;
      IFEND;

      IF (osc$ecp_wait IN actions) AND (NOT data_released) THEN
        IF (access_condition_entry.file_access_condition IN context.allowed_access_conditions)
{     } AND (NOT recovery_occurred) AND context.wait THEN
          IF NOT (access_condition_entry.file_access_condition IN context.raised_conditions) THEN
            report_wait;
            context.raised_conditions := context.raised_conditions +
                  $fst$file_access_conditions [access_condition_entry.file_access_condition];
            IF ring3_caller THEN
              {The ring 3 stack is not readable in ring 11.  Therefore we must copy the information
              {into a pre-allocated task private variable.
              exception_information := context.externalized_info;
              pmp$cause_task_condition (access_condition_entry.user_defined_condition, ^exception_information,
                    {notify_scl=} TRUE, {notify_debug=} FALSE, {propate_to_parent=} TRUE,
                    {call_default_handler=} FALSE, local_status);
            ELSE
              pmp$cause_task_condition (access_condition_entry.user_defined_condition,
                    ^context.externalized_info, {notify_scl=} TRUE, {notify_debug=} FALSE,
                    {propate_to_parent=} TRUE, {call_default_handler=} FALSE, local_status);
            IFEND;
          IFEND;
          wait_on_condition;
        ELSE
          context.wait := FALSE;
        IFEND;
      ELSEIF (osc$ecp_exit IN actions) AND (NOT data_released) THEN
        IF context.wait THEN
          report_exit;
        IFEND;
        context.wait := FALSE;
      ELSEIF (osc$ecp_delete IN actions) AND (NOT data_released) THEN
        IF (pf_path^ [1] <> fsc$local) THEN
          pfp$purge (pf_path^, cycle_selector.value, context.password, local_status);
          IF local_status.normal THEN
            report_delete;
            osp$set_status_condition (ose$data_lost, context.condition_status);
            osp$append_status_file (osc$status_parameter_delimiter, criteria.file, context.condition_status);
            context.wait := FALSE;
          IFEND;
        ELSE {Temporary file}
          amp$return (criteria.file, local_status);
          IF local_status.normal THEN
            report_delete;
            osp$set_status_condition (ose$data_lost, context.condition_status);
            osp$append_status_file (osc$status_parameter_delimiter, criteria.file, context.condition_status);
            context.wait := FALSE;
          IFEND;
        IFEND;
      IFEND;

      IF context.wait AND (context.condition_status.condition = pfe$cycle_data_resides_offline) THEN
        {
        { The data_retrieval_required_condition is the only condition that requires the participation of
        { the affected job to resolve.  All other conditions are satisfied as a result of human intervention.
        { If the calling interface is incapable of initiating the file retrieval, there is no reason to have
        { the job wait.  Someone else must be informed that the file requires retrieval.
        {
        context.wait := context.caller_will_retrieve_file;
      IFEND;

      IF NOT (access_condition_entry.file_access_condition IN context.allowed_access_conditions) THEN
        context.wait := FALSE;
      IFEND;

    PROCEND execute_exception_policy;
?? OLDTITLE ??
?? NEWTITLE := '  move_catalog', EJECT ??

    PROCEDURE move_catalog
      (    path: pft$path;
           criteria: ost$ecp_criteria;
       VAR catalog_moved: boolean);

      VAR
        ch: 'A' .. 'Z',
        default_movement_statistics: pft$movement_statistics,
        dest_volume_count: integer,
        element_count: integer,
        evaluated_file_reference: fst$evaluated_file_reference,
        i: integer,
        j: integer,
        local_status: ost$status,
        log_status: ost$status,
        move_object_info_p: ^pft$move_object_info,
        number_of_volumes_in_set: integer,
        set_volume_list_p: ^pft$mo_volume_list,
        source_volume_count: integer,
        volume_list_p: ^pft$volume_list,
        volume_list_size: ost$positive_integers;

?? NEWTITLE := 'initialize_set_volume_list', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to initialize information in the
{   SET_VOLUME_LIST which is contained in the MOVE_OBJECT_INFO structure.
{

      PROCEDURE initialize_set_volume_list
        (    set_volume_list_p: ^pft$mo_volume_list;
         VAR local_status: ost$status);

        VAR
          element_status: iot$unit_status,
          found: boolean,
          i: integer,
          j: integer,
          ms_volume_count: integer,
          ms_volumes_p: ^array [1 .. * ] of cmt$mass_storage_volume,
          state: cmt$element_state;

        local_status.normal := TRUE;

        IF set_volume_list_p = NIL THEN
          RETURN; {----->
        IFEND;

        { Obtain the class membership of each volume in the configuration which is ON and ENABLED.

        cmp$get_ms_volumes (ms_volume_count);
        PUSH ms_volumes_p: [1 .. ms_volume_count];
        cmp$get_ms_volume_info (ms_volumes_p^);

      /process_volume/
        FOR i := 1 TO UPPERBOUND (set_volume_list_p^) DO
          found := FALSE;

          set_volume_list_p^ [i].available := FALSE;
          set_volume_list_p^ [i].bytes_moved_from := 0;
          set_volume_list_p^ [i].bytes_moved_to := 0;
          set_volume_list_p^ [i].bytes_released := 0;
          set_volume_list_p^ [i].catalogs_moved_from := 0;
          set_volume_list_p^ [i].catalogs_moved_to := 0;
          set_volume_list_p^ [i].cycles_moved_from := 0;
          set_volume_list_p^ [i].cycles_moved_to := 0;
          set_volume_list_p^ [i].cycles_released := 0;
          set_volume_list_p^ [i].logical_unit_number := 0;
          set_volume_list_p^ [i].mass_storage_available := 0;
          set_volume_list_p^ [i].mass_storage_before := 0;
          set_volume_list_p^ [i].mass_storage_capacity := 0;
          set_volume_list_p^ [i].move_bytes_threshold_exceeded := FALSE;
          set_volume_list_p^ [i].ms_class := $dmt$class [];
          set_volume_list_p^ [i].volume_type := pfc$unspecified_volume;

        /locate_volume/
          FOR j := 1 TO ms_volume_count DO
            IF set_volume_list_p^ [i].recorded_vsn = ms_volumes_p^ [j].recorded_vsn THEN
              found := TRUE;
              EXIT /locate_volume/; {----->
            IFEND;
          FOREND /locate_volume/;

          IF NOT found THEN
            CYCLE /process_volume/; {----->
          IFEND;

          cmp$get_element_state_via_lun (ms_volumes_p^ [j].lun, state);
          IF state <> cmc$on THEN
            CYCLE /process_volume/; {----->
          IFEND;

          cmp$get_ms_status_via_lun (ms_volumes_p^ [j].lun, element_status);
          IF element_status.disabled THEN
            CYCLE /process_volume/; {----->
          IFEND;

          set_volume_list_p^ [i].available := TRUE;
          set_volume_list_p^ [i].logical_unit_number := ms_volumes_p^ [j].lun;
          set_volume_list_p^ [i].ms_class := ms_volumes_p^ [j].class;

        FOREND /process_volume/;

      PROCEND initialize_set_volume_list;
?? OLDTITLE ??
?? NEWTITLE := 'report_move_status', EJECT ??

      PROCEDURE report_move_status
        (    move_status: pft$move_status);

        VAR
          log_status: ost$status;

        IF move_status.move_successful THEN
          osp$set_status_condition (ose$log_catalog_move, log_status);
          report_context (log_status);
          osp$append_status_parameter (osc$status_parameter_delimiter, criteria.volume_list^ [1].recorded_vsn,
                log_status);

          osp$append_status_integer (osc$status_parameter_delimiter, context.catalog_move_count, 10,
                {include_radix_specifier} FALSE, log_status);

          osp$log_executed_policy (log_status);
        ELSEIF context.initial_call THEN
          osp$set_status_condition (ose$log_catalog_move_failure, log_status);
          report_context (log_status);
          CASE move_status.reason_for_move_failure OF
          = pfc$cycle_busy =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'CYCLE_BUSY', log_status);
          = pfc$data_released =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'DATA RELEASED', log_status);
          = pfc$device_class_not_ms =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'DEVICE CLASS NOT MS', log_status);
          = pfc$insufficient_space =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'INSUFFICIENT SPACE', log_status);
          = pfc$io_error =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'IO ERROR', log_status);
          = pfc$no_available_space =
            osp$append_status_parameter (osc$status_parameter_delimiter, ' NO SPACE', log_status);
          = pfc$operator_skip =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'OPERATOR SKIP', log_status);
          = pfc$operator_terminate =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'OPERATOR TERMINATE', log_status);
          = pfc$set_threshold_exceeded =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'SET THRESHOLD EXCEEDED',
                  log_status);
          = pfc$unexpected_abort =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'UNEXPECTED_ABORT', log_status);
          = pfc$volume_threshold_exceeded =
            osp$append_status_parameter (osc$status_parameter_delimiter, 'VOLUME THRESHOLD EXCEEDED',
                  log_status);
          ELSE
          CASEND;
          osp$log_executed_policy (log_status);
        IFEND;
        osp$log_executed_policy (initial_status);

      PROCEND report_move_status;
?? OLDTITLE ??
?? EJECT ??
      catalog_moved := FALSE;

      default_movement_statistics.abnormal_status := 0;
      default_movement_statistics.bytes_moved := 0;
      default_movement_statistics.bytes_released := 0;
      default_movement_statistics.cycle_busy := 0;
      default_movement_statistics.cycles_released := 0;
      default_movement_statistics.insufficient_space := 0;
      default_movement_statistics.no_available_space := 0;
      default_movement_statistics.objects_moved := 0;
      default_movement_statistics.objects_not_moved := 0;
      default_movement_statistics.unrecovered_read_error := 0;

      PUSH move_object_info_p;

      FOR ch := 'A' TO 'Z' DO
        move_object_info_p^.class_statistics [ch] := default_movement_statistics;
      FOREND;

      move_object_info_p^.dest_volume_list_p := NIL;
      move_object_info_p^.mass_storage_class := $dmt$class [];
      move_object_info_p^.move_bytes_threshold := 0;
      move_object_info_p^.overall_statistics := default_movement_statistics;
      move_object_info_p^.perform_move := TRUE;
      move_object_info_p^.performance_statistics.catalog_count := 0;
      move_object_info_p^.performance_statistics.cycle_count := 0;
      move_object_info_p^.performance_statistics.file_count := 0;
      move_object_info_p^.release_mass_storage := pfc$never;
      move_object_info_p^.set_name := osc$null_name;
      move_object_info_p^.set_volume_list_p := NIL;
      move_object_info_p^.source_volume_list_p := NIL;
      move_object_info_p^.update_available_space_total := 0;
      move_object_info_p^.volume_overflow_allowed := TRUE;
      move_object_info_p^.wait := TRUE;

      pmp$get_compact_date_time (move_object_info_p^.performance_statistics.initial_date_time, local_status);
      IF local_status.normal THEN
        pmp$get_microsecond_clock (move_object_info_p^.performance_statistics.initial_microsecond_clock,
              local_status);
        IF local_status.normal THEN
          pmp$get_task_cp_time (move_object_info_p^.performance_statistics.initial_task_cp_time,
                local_status);
          IF local_status.normal THEN
            volume_list_size := 2 * UPPERVALUE (dmt$subfile_index) * #SIZE (pft$subfile);
            PUSH move_object_info_p^.move_status.volume_list_storage_p: [[REP volume_list_size OF cell]];
            RESET move_object_info_p^.move_status.volume_list_storage_p;
            move_object_info_p^.move_status.move_successful := FALSE;
            move_object_info_p^.move_status.new_subfile_list_p := NIL;
            move_object_info_p^.move_status.old_subfile_list_p := NIL;
            move_object_info_p^.move_status.reason_for_move_failure := pfc$unexpected_abort;
            move_object_info_p^.set_name := criteria.set_name;

            number_of_volumes_in_set := 10;
            REPEAT
              PUSH volume_list_p: [1 .. number_of_volumes_in_set];
              pfp$get_volumes_in_set (criteria.set_name, volume_list_p^, number_of_volumes_in_set,
                    local_status);
            UNTIL (NOT local_status.normal OR (number_of_volumes_in_set <= UPPERBOUND (volume_list_p^)));
            IF local_status.normal THEN
              PUSH move_object_info_p^.set_volume_list_p: [1 .. number_of_volumes_in_set];
              FOR i := 1 TO number_of_volumes_in_set DO
                move_object_info_p^.set_volume_list_p^ [i].recorded_vsn := volume_list_p^ [i];
              FOREND;
              set_volume_list_p := move_object_info_p^.set_volume_list_p;

              initialize_set_volume_list (move_object_info_p^.set_volume_list_p, local_status);
              IF local_status.normal THEN
                move_object_info_p^.mass_storage_class := $dmt$class [criteria.mass_storage_class];
              IFEND;

              move_object_info_p^.perform_move := TRUE;

              PUSH move_object_info_p^.source_volume_list_p: [1 .. 1];
              element_count := 0;

              FOR i := 1 TO UPPERBOUND (set_volume_list_p^) DO
                IF criteria.volume_list^ [1].recorded_vsn = set_volume_list_p^ [i].recorded_vsn THEN
                  element_count := element_count + 1;
                  move_object_info_p^.source_volume_list_p^ [element_count] := ^set_volume_list_p^ [i];
                  set_volume_list_p^ [i].volume_type := pfc$source_volume;
                IFEND;
              FOREND;

              move_object_info_p^.release_mass_storage := pfc$never;
              move_object_info_p^.volume_overflow_allowed := FALSE;
              move_object_info_p^.wait := FALSE;

              dest_volume_count := 0;
              FOR i := 1 TO number_of_volumes_in_set DO
                IF set_volume_list_p^ [i].available AND (set_volume_list_p^ [i].volume_type =
                      pfc$unspecified_volume) AND ((move_object_info_p^.mass_storage_class *
                      set_volume_list_p^ [i].ms_class) <> $dmt$class []) THEN
                  dest_volume_count := dest_volume_count + 1;
                IFEND;
              FOREND;
              IF dest_volume_count > 0 THEN
                PUSH move_object_info_p^.dest_volume_list_p: [1 .. dest_volume_count];
                j := 1;
                FOR i := 1 TO number_of_volumes_in_set DO
                  IF set_volume_list_p^ [i].available AND (set_volume_list_p^ [i].volume_type =
                        pfc$unspecified_volume) AND ((move_object_info_p^.mass_storage_class *
                        set_volume_list_p^ [i].ms_class) <> $dmt$class []) THEN
                    set_volume_list_p^ [i].volume_type := pfc$destination_volume;
                    move_object_info_p^.dest_volume_list_p^ [j] := ^set_volume_list_p^ [i];
                    j := j + 1;
                  IFEND;
                FOREND;
                pfp$r3_get_move_obj_device_info (move_object_info_p, local_status);
                IF local_status.normal THEN
                  pfp$r3_physically_move_catalog (path, move_object_info_p, local_status);
                  IF local_status.normal AND move_object_info_p^.move_status.move_successful THEN
                    catalog_moved := TRUE;
                    context.catalog_move_count := context.catalog_move_count + 1;
                  IFEND;
                  report_move_status (move_object_info_p^.move_status);
                IFEND;
              ELSEIF context.initial_call THEN
                osp$set_status_condition (ose$log_catalog_move_failure, log_status);
                report_context (log_status);
                osp$append_status_parameter (osc$status_parameter_delimiter, 'NO DESTINATION VOLUMES',
                      log_status);
                osp$log_executed_policy (log_status);
                osp$log_executed_policy (initial_status);
              IFEND;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

    PROCEND move_catalog;
?? OLDTITLE ??
?? NEWTITLE := '  report_context', EJECT ??

    PROCEDURE report_context
      (VAR log_status {input, output} : ost$status);

      VAR
        text: string (31);

      osp$append_status_file (osc$status_parameter_delimiter, criteria.file, log_status);

      CASE access_condition_entry.file_access_condition OF
      = fsc$catalog_media_missing =
        text := 'CATALOG_MEDIA_MISSING';
      = fsc$catalog_volume_unavailable =
        text := 'CATALOG_VOLUME_UNAVAILABLE';
      = fsc$cycle_busy =
        text := 'CYCLE_BUSY';
      = fsc$data_restoration_required =
        text := 'CYCLE_RESTORATION_REQUIRED';
      = fsc$data_retrieval_required =
        text := 'CYCLE_RETRIEVAL_REQUIRED';
      = fsc$file_server_inactive =
        text := 'FILE_SERVER_INACTIVE';
      = fsc$media_missing =
        text := 'MEDIA_MISSING';
      = fsc$space_unavailable =
        text := 'SPACE_UNAVAILABLE';
      = fsc$volume_unavailable =
        text := 'VOLUME_UNAVAILABLE';
      ELSE
        text := 'UNKNOWN CONDITION';
      CASEND;

      osp$append_status_parameter (osc$status_parameter_delimiter, text, log_status);

    PROCEND report_context;
?? OLDTITLE ??
?? NEWTITLE := '  report_ending_status', EJECT ??

    PROCEDURE report_ending_status;

      VAR
        log_status: ost$status;

      IF context.logging_allowed THEN
        osp$set_status_condition (ose$log_ending_status, log_status);
        osp$log_executed_policy (log_status);
        osp$log_executed_policy (context.condition_status);
      IFEND;

    PROCEND report_ending_status;
?? OLDTITLE ??
?? EJECT ??

    CONST
      max_volume_number = 500;

    VAR
      catalog_moved: boolean,
      entry_found: boolean,
      local_status: ost$status,
      mapped_status_variable: boolean,
      problematic_volume: rmt$recorded_vsn,
      sequence: ^SEQ ( * ),
      seq_size: ost$positive_integers,
      string1: string (1),
      vsn_name_error_size: integer;

    #CALLER_ID (caller_id);

    ring3_caller := FALSE;

    IF enforce_except_policies_active = TRUE THEN
      osp$wait_on_condition (context.condition_status.condition);
      RETURN; {----->
    ELSE
      {Recursion is only of concern in ring 3 or less
      IF caller_id.ring <= osc$tsrv_ring THEN
        ring3_caller := TRUE;
        enforce_except_policies_active := TRUE;
      IFEND;
    IFEND;
    #SPOIL (ring3_caller);
    #SPOIL (enforce_except_policies_active);
    osp$establish_block_exit_hndlr (^enforce_exit_handler);
    context.elapsed_wait_time := 0;

    initial_status := context.condition_status;

    osp$get_access_condition_entry (context.condition_status, access_condition_entry, entry_found);
    IF entry_found THEN
      mapped_status_variable := context.condition_status.condition <> initial_status.condition;
      osp$get_login_user_criteria (criteria, local_status);
      IF local_status.normal THEN
        seq_size := #SIZE (fst$goi_object_information) + fsc$max_path_size + #SIZE (fst$goi_object) +
              #SIZE (fst$device_information) + (max_volume_number *
              (#SIZE (rmt$volume_descriptor) + #SIZE (fst$file_access_condition)));
        PUSH sequence: [[REP seq_size OF cell]];

        actions := $ost$ecp_actions [];
        criteria.condition := access_condition_entry.file_access_condition;
        criteria.mass_storage_class := rmc$unspecified_file_class;
        criteria.volume_list := NIL;
        volume_condition_list := NIL;

        osp$get_file_criteria (context.file, context.catalog_object, {catalog_space_unavailable}
              (initial_status.condition = pfe$catalog_full), context.password, sequence, criteria,
              volume_condition_list, local_status);
        IF local_status.normal THEN
          IF (initial_status.condition = pfe$catalog_volume_unavailable) AND (volume_condition_list = NIL) AND
                (criteria.volume_list = NIL) THEN
            PUSH volume_condition_list: [1 .. 1];
            volume_condition_list^ [1] := fsc$catalog_volume_unavailable;
            PUSH criteria.volume_list: [1 .. 1];
            vsn_name_error_size := initial_status.text.size - 1;
            IF vsn_name_error_size > 6 THEN
              vsn_name_error_size := 6;
            IFEND;
            criteria.volume_list^ [1].recorded_vsn := initial_status.text.value (2, vsn_name_error_size);
            criteria.volume_list^ [1].external_vsn := initial_status.text.value (2, vsn_name_error_size);
          IFEND;

          get_applicable_policy (criteria, actions, applicable_poll_frequency);
          IF (actions = $ost$ecp_actions []) THEN
            IF jmp$system_job () THEN
              IF (context.condition_status.condition = pfe$cycle_busy) OR
                    (context.condition_status.condition = ame$space_unavailable) THEN
                actions := $ost$ecp_actions [osc$ecp_wait];
              ELSE
                actions := $ost$ecp_actions [];
                context.wait := FALSE;
              IFEND;
            ELSE
              actions := $ost$ecp_actions [osc$ecp_wait];
            IFEND;
          IFEND;

          {Wait is implied if the actions consist only of "enable release" options
          IF ((actions * $ost$ecp_actions [osc$ecp_enable_matching_image, osc$ecp_enable_nonmatch_image,
                osc$ecp_set_damage_condition]) <> $ost$ecp_actions []) AND
                ((actions - $ost$ecp_actions [osc$ecp_enable_matching_image, osc$ecp_enable_nonmatch_image,
                osc$ecp_set_damage_condition]) = $ost$ecp_actions []) THEN
            actions := actions + $ost$ecp_actions [osc$ecp_wait];
          IFEND;

          context.externalized_info.when_handler_status := TRUE;
          context.externalized_info.exception_status := context.condition_status;
          context.externalized_info.file_access_condition := access_condition_entry.file_access_condition;

          IF criteria.file <> osc$null_name THEN
            fsp$evaluate_file_reference (criteria.file, {command_file_reference_allowed} FALSE,
                  evaluated_file_reference, local_status);
            pf_path := NIL;
            IF local_status.normal THEN
              PUSH pf_path: [1 .. evaluated_file_reference.number_of_path_elements];
              pfp$convert_fs_to_pft$path (evaluated_file_reference, pf_path^);
              clp$convert_cyc_ref_to_cyc_sel (evaluated_file_reference.cycle_reference, cycle_selector);
              context.externalized_info.object_name := pf_path^
                    [evaluated_file_reference.number_of_path_elements];
            ELSE
              actions := actions * $ost$ecp_actions [osc$ecp_exit, osc$ecp_wait];
              IF actions = $ost$ecp_actions [] THEN
                actions := $ost$ecp_actions [osc$ecp_wait];
              IFEND;
            IFEND;
          ELSE
            actions := actions * $ost$ecp_actions [osc$ecp_exit, osc$ecp_wait];
            IF actions = $ost$ecp_actions [] THEN
              actions := $ost$ecp_actions [osc$ecp_wait];
            IFEND;
          IFEND;

          IF context.file.selector = osc$ecp_file_segment THEN
            context.externalized_info.file_segment_isolated := TRUE;
            context.externalized_info.file_segment := #SEGMENT (context.file.file_segment);
          IFEND;

          IF context.force_wait THEN
            actions := $ost$ecp_actions [osc$ecp_wait];
          IFEND;

          IF (initial_status.condition = pfe$catalog_full) AND
                (context.catalog_move_count < osc$ecp_max_catalog_moves) AND
                (criteria.volume_list <> NIL) THEN
            move_catalog (pf_path^, criteria, catalog_moved);
            IF NOT catalog_moved THEN
              execute_exception_policy;
            IFEND;
          ELSE
            execute_exception_policy;
          IFEND;

          IF osp$file_access_condition (context.condition_status) THEN

            CASE access_condition_entry.file_access_condition OF
            = fsc$catalog_media_missing, fsc$catalog_volume_unavailable =
              find_problematic_volume (volume_condition_list, criteria.volume_list, problematic_volume);
              osp$set_status_condition (context.condition_status.condition, local_status);
              osp$append_status_parameter (osc$status_parameter_delimiter, problematic_volume, local_status);
              context.condition_status := local_status;
            = fsc$media_missing, fsc$volume_unavailable =
              find_problematic_volume (volume_condition_list, criteria.volume_list, problematic_volume);
              osp$set_status_condition (context.condition_status.condition, local_status);
              osp$append_status_file (osc$status_parameter_delimiter, criteria.file, local_status);
              osp$append_status_parameter (osc$status_parameter_delimiter, problematic_volume, local_status);
              context.condition_status := local_status;
            = fsc$space_unavailable =
              osp$set_status_condition (context.condition_status.condition, local_status);
              osp$append_status_file (osc$status_parameter_delimiter, criteria.file, local_status);
              #UNCHECKED_CONVERSION (criteria.mass_storage_class, string1);
              IF criteria.mass_storage_class = rmc$unspecified_file_class THEN
                osp$append_status_parameter (osc$status_parameter_delimiter, '?', local_status);
              ELSE
                osp$append_status_parameter (osc$status_parameter_delimiter, string1, local_status);
              IFEND;
              context.condition_status := local_status;
            ELSE
            CASEND;
          IFEND;
        ELSE
          context.wait := FALSE;
        IFEND;
      ELSE
        context.wait := FALSE;
      IFEND;
      IF context.initial_call AND (mapped_status_variable OR
            (initial_status.text <> context.condition_status.text)) THEN
        report_ending_status;
      IFEND;
    ELSE
      context.wait := FALSE;
    IFEND;

    context.initial_call := FALSE;

  PROCEND osp$enforce_exception_policies;
?? OLDTITLE ??
?? NEWTITLE := '  get_applicable_policy', EJECT ??

  PROCEDURE get_applicable_policy
    (    criteria: ost$ecp_criteria;
     VAR applicable_actions: ost$ecp_actions;
     VAR polling_frequency: ost$ecp_polling_frequency);

    CONST
      one_second = 1000;

    VAR
      status: ost$status;

    status.normal := TRUE;

    REPEAT
      osp$r3_get_applicable_policy (criteria, applicable_actions, polling_frequency, status);
      IF (NOT status.normal) AND (status.condition = ose$exception_policies_locked) THEN
        pmp$wait (one_second, one_second);
      IFEND;
    UNTIL status.normal OR (status.condition <> ose$exception_policies_locked);

  PROCEND get_applicable_policy;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] osp$format_wait_message', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$format_wait_message
    (    access_condition_entry: ^fst$access_condition_entry;
         file: ^fst$file_reference;
         mass_storage_class: rmt$mass_storage_class;
         volume_condition_list: ^fst$volume_condition_list;
         volume_list: ^rmt$volume_list;
     VAR wait_message: oft$display_message);

    CONST
      waiting_for = ' Waiting for';

    VAR
      local_status: ost$status,
      message_container: ost$status_message,
      message_container_ptr: ^ost$status_message,
      message_line: ^ost$status_message_line,
      message_line_count: ^ost$status_message_line_count,
      message_line_index: 1 .. osc$max_status_message_lines,
      message_line_size: ^ost$status_message_line_size,
      message_module: pmt$program_name,
      message_parameters: array [1 .. 1] of ^ost$message_parameter,
      message_template: ^ost$message_template,
      module_index: 1 .. osc$max_system_message_modules,
      problematic_volume: rmt$recorded_vsn,
      relevant_path_size: fst$path_size,
      string1: string (1),
      wait_message_name: clt$parameter_name;

    message_line_size := NIL;
    message_line := NIL;
    message_parameters [1] := NIL;

    IF access_condition_entry = NIL THEN
      wait_message_name := fsc$wait_undefined_condition;
    ELSE
      wait_message_name := access_condition_entry^.wait_message_name;
      CASE access_condition_entry^.file_access_condition OF
      = fsc$catalog_media_missing, fsc$catalog_volume_unavailable, fsc$media_missing, fsc$volume_unavailable =
        find_problematic_volume (volume_condition_list, volume_list, problematic_volume);
        message_parameters [1] := ^problematic_volume (1, clp$trimmed_string_size (problematic_volume));
      = fsc$space_unavailable =
        message_parameters [1] := ^string1;
        IF mass_storage_class = rmc$unspecified_file_class THEN
          string1 := '?';
        ELSE
          #UNCHECKED_CONVERSION (mass_storage_class, string1);
        IFEND;
      ELSE
      CASEND;
    IFEND;

{ Search table of system message modules defined in osm$message_module_pointers }

  /loop/
    FOR module_index := 1 TO osc$max_system_message_modules DO
      IF fsc$wait_msg_module_name = osv$system_message_modules [module_index].module_name THEN
        osp$find_parameter_prompt (osv$system_message_modules [module_index].module_pointer_p^,
              wait_message_name, message_template, local_status);
        IF local_status.normal THEN
          osp$format_help_message (message_template, ^message_parameters, osc$max_status_message_line,
                message_container, local_status);
          IF local_status.normal THEN
            message_container_ptr := ^message_container;
            RESET message_container_ptr;
            NEXT message_line_count IN message_container_ptr;

            IF message_line_count^ > 0 THEN
              NEXT message_line_size IN message_container_ptr;
              NEXT message_line: [message_line_size^] IN message_container_ptr;
              message_line_size^ := clp$trimmed_string_size (message_line^);
            IFEND;
          IFEND;
        IFEND;
        EXIT /loop/; {----->
      IFEND;
    FOREND /loop/;

    IF message_line_size = NIL THEN
      PUSH message_line_size;
      message_line_size^ := STRLENGTH (waiting_for);
      PUSH message_line: [message_line_size^];
      message_line^ := waiting_for;
    IFEND;

    {Formatted messages have leading SPACE character which is not useful, so start at column 2
    wait_message.text := message_line^ (2, message_line_size^ -1);
    wait_message.size := clp$trimmed_string_size (wait_message.text);

    IF file <> NIL THEN
      osp$get_relevant_path_string (file^, wait_message.text (wait_message.size + 2, * ), relevant_path_size);
      wait_message.size := wait_message.size + relevant_path_size + 1;
    IFEND;

  PROCEND osp$format_wait_message;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] osp$get_relevant_path_string', EJECT ??

  PROCEDURE [XDCL, #GATE] osp$get_relevant_path_string
    (    path: fst$file_reference;
     VAR relevant_path: fst$file_reference;
     VAR relevant_path_size: fst$path_size);

    VAR
      ignore_path_size: fst$path_size,
      local_status: ost$status,
      path_size: fst$path_size;

?? NEWTITLE := 'get_relevant_substring', EJECT ??

    PROCEDURE get_relevant_substring
      (    path: fst$file_reference;
       VAR relevant_path: fst$file_reference;
       VAR relevant_path_size: fst$path_size);

      CONST
        ellipsis = ' .. ';

      VAR
        constraint: fst$path_size,
        i: integer,
        index: integer,
        j: ost$positive_integers,
        local_path_size: fst$path_size,
        path_index: 0 .. (fsc$max_path_size + 1),
        path_parts: ^array [1 .. (fsc$max_path_size DIV 2)] of integer,
        result: boolean,
        select: ^packed array [0 .. 255] of 0 .. 1;

      constraint := STRLENGTH (relevant_path);
      path_size := STRLENGTH (path);

      IF path_size > constraint THEN
        PUSH path_parts;
        PUSH select;

        FOR i := 0 TO 255 DO
          select^ [i] := 0;
        FOREND;
        select^ [$INTEGER ('.')] := 1; {Scan for period only}

        i := 0;
        path_index := 0;

        REPEAT
          i := i + 1;
          #SCAN (select^, path (path_index + 1, path_size - path_index), index, result);
          path_index := path_index + index;
          path_parts^ [i] := path_index;
        UNTIL NOT result;

        IF i > 1 THEN
          IF constraint >= (path_parts^ [2] - 1) THEN
            {Full family/user path fits
            relevant_path_size := path_parts^ [2] - 1;
            relevant_path := path (1, relevant_path_size);

            IF (i >= 2) AND ((constraint - path_parts^ [2] + 1) >= STRLENGTH (ellipsis)) THEN
              relevant_path (path_parts^ [2], STRLENGTH (ellipsis)) := ellipsis;
              relevant_path_size := relevant_path_size + STRLENGTH (ellipsis);

              IF (i > 2) AND ((constraint - relevant_path_size) > 0) THEN
                {get as many full path parts from the rightmost part of the path as will fit
                FOR j := 3 TO i - 1 DO
                  IF (path_parts^ [i] - path_parts^ [j]) <= (constraint - relevant_path_size) THEN
                    relevant_path (relevant_path_size + 1, * ) := path (path_parts^ [j], * );
                    relevant_path_size := relevant_path_size + (path_parts^ [i] - path_parts^ [j]);
                    RETURN; {----->
                  IFEND;
                FOREND;
              IFEND;
            IFEND;
          ELSE {Not enough room for full FAMILY/USER path}
            relevant_path := path;
            relevant_path_size := constraint;
          IFEND;
        ELSE {only a family path provided}
          relevant_path := path;
          relevant_path_size := constraint;
        IFEND;
      ELSE {path fits in string provided}
        relevant_path (1, constraint) := path;
        relevant_path_size := path_size;
      IFEND;
    PROCEND get_relevant_substring;
?? OLDTITLE ??
?? EJECT ??
    path_size := clp$trimmed_string_size (path);

    IF path_size > STRLENGTH (relevant_path) THEN
      get_relevant_substring (path (1, path_size), relevant_path, relevant_path_size);
    ELSE
      relevant_path (1, * ) := path (1, path_size);
      relevant_path_size := path_size;
    IFEND;

  PROCEND osp$get_relevant_path_string;
?? OLDTITLE ??
?? NEWTITLE := 'find_problematic_volume', EJECT ??

  PROCEDURE find_problematic_volume
    (    volume_condition_list: ^fst$volume_condition_list;
         volume_list: ^rmt$volume_list;
     VAR problematic_volume: rmt$recorded_vsn);

    VAR
      i: ost$positive_integers;

    problematic_volume := rmc$unspecified_vsn;

    IF (volume_condition_list <> NIL) AND (volume_list <> NIL) THEN

      FOR i := LOWERBOUND (volume_condition_list^) TO UPPERBOUND (volume_condition_list^) DO
        IF (volume_condition_list^ [i] IN $fst$file_access_conditions
              [fsc$catalog_media_missing, fsc$catalog_volume_unavailable, fsc$media_missing,
              fsc$volume_unavailable]) THEN
          problematic_volume := volume_list^ [i].recorded_vsn;
          RETURN; {----->
        IFEND;
      FOREND;
    IFEND;

  PROCEND find_problematic_volume;
?? OLDTITLE ??
MODEND osm$disk_fault_tolerance_2dd;
