?? LEFT := 1, RIGHT := 110 ??
MODULE pfm$r2_move_object;

{PURPOSE:
{  Ring 2 requests for move_classes.

?? TITLE := 'Global Declarations Referenced by this Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc pfc$average_share_history
*copyc pfc$catalog_ring
*copyc pfc$maximum_pf_length
*copyc pfe$external_archive_conditions
*copyc ost$positive_integers
*copyc pft$internal_cycle_path
*copyc pft$move_object_info
*copyc pft$variant_path
?? POP ??
*copyc amv$device_class_names
*copyc cmp$get_element_entry_via_lun
*copyc dmp$attach_file
*copyc dmp$calculate_device_capacity
*copyc dmp$calculate_remaining_space
*copyc dmp$change_file_damaged
*copyc dmp$delete_file_descriptor
*copyc dmp$destroy_permanent_file
*copyc dmp$detach_file
*copyc dmp$get_file_info
*copyc dmp$get_stored_fmd
*copyc dmp$get_stored_fmd_header_info
*copyc dmp$get_stored_fmd_size
*copyc dmp$get_stored_fmd_subfile_list
*copyc dmp$put_stored_fmd_header_info
*copyc dmv$active_volume_table
*copyc i#move
*copyc mmp$advise_out
*copyc mmp$close_segment
*copyc mmp$open_file_segment
*copyc mmp$os_preallocate_file_space
*copyc mmp$preset_page_streaming
*copyc mmp$set_segment_length
*copyc mmp$verify_no_space_available
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$disestablish_cond_handler
*copyc osp$establish_condition_handler
*copyc osp$get_parameter_prompt
*copyc osp$log_io_read_error
*copyc osp$prevalidate_free
*copyc osp$recoverable_system_error
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc pfp$access_object
*copyc pfp$attach_catalog
*copyc pfp$attach_root_catalog
*copyc pfp$build_archive_list_pointer
*copyc pfp$build_cycle_list_pointer
*copyc pfp$build_fmd_locator
*copyc pfp$build_fmd_pointer
*copyc pfp$compute_checksum
*copyc pfp$convert_cycle_path_to_strng
*copyc pfp$convert_pf_path_to_fs_path
*copyc pfp$convert_device_class_to_rm
*copyc pfp$create_catalog
*copyc pfp$dm_create_file_entry
*copyc pfp$destroy_catalog
*copyc pfp$detach_permanent_file
*copyc pfp$get_authority
*copyc pfp$locate_cycle
*copyc pfp$log_ascii
*copyc pfp$log_path
*copyc pfp$process_unexpected_status
*copyc pfp$reconcile_fmd
*copyc pfp$report_invalid_free
*copyc pfp$return_catalog
*copyc pfp$set_status_abnormal
*copyc pfp$shared_queue
*copyc pmp$continue_to_cause
*copyc pfp$shared_queue
*copyc pmp$date_time_compare
*copyc pmp$delay
*copyc pmp$get_compact_date_time
*copyc stp$get_pf_root
*copyc stp$store_pf_root
*copyc stv$system_set_name
*copyc syp$pop_inhibit_job_recovery
*copyc syp$push_inhibit_job_recovery

*if false
{Debug Code
*copyc pmp$test_condition_handler

  VAR
    osv$debug: [XREF] array [0 .. 15] of integer;

{Debug Code End
*ifend

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

  CONST
    pfc$update_device_info_limit = 10485760,
    pfc$move_while_locked_limit = 1048576;

?? OLDTITLE ??
?? NEWTITLE := ' pfp$r2_get_move_obj_device_info', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_get_move_obj_device_info
    (    move_object_info_p: ^pft$move_object_info;
     VAR status: ost$status);

    VAR
      entry_p: ^cmt$peripheral_element_entry,
      i: integer,
      mass_storage_available: integer,
      mass_storage_capacity: integer,
      set_volume_list_p: ^pft$mo_volume_list;

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

    IF move_object_info_p^.set_volume_list_p <> NIL THEN
      set_volume_list_p := move_object_info_p^.set_volume_list_p;

      FOR i := 1 TO UPPERBOUND (set_volume_list_p^) DO
        cmp$get_element_entry_via_lun (set_volume_list_p^ [i].logical_unit_number, entry_p);
        IF entry_p <> NIL THEN
          dmp$calculate_device_capacity (entry_p^.product_id, mass_storage_capacity, status);
          IF status.normal THEN
            set_volume_list_p^ [i].mass_storage_capacity := mass_storage_capacity;
            dmp$calculate_remaining_space (set_volume_list_p^ [i].logical_unit_number, mass_storage_available,
                  status);
            IF status.normal THEN
              set_volume_list_p^ [i].mass_storage_available := mass_storage_available;
            IFEND;
          IFEND;
          IF NOT status.normal THEN
            RETURN; {----->
          IFEND;
        IFEND;
      FOREND;
    IFEND;

  PROCEND pfp$r2_get_move_obj_device_info;
?? OLDTITLE ??
?? NEWTITLE := ' pfp$r2_physically_move_catalog', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_physically_move_catalog
    (    path: pft$complete_path;
         move_object_info_p: ^pft$move_object_info;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      class_string: string (1),
      destination_file_info: dmt$file_information,
      file_info: dmt$file_information,
      fmd_header: pft$fmd_header,
      fs_path_size: fst$path_size,
      gfn_dest: dmt$global_file_name,
      gfn_source: dmt$global_file_name,
      job_recovery_inhibited: boolean,
      local_status: ost$status,
      new_catalog_active: boolean,
      new_catalog_locator: pft$catalog_locator,
      p_catalog_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_mass_storage_request_info: ^fmt$mass_storage_request_info,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_physical_fmd: ^pft$physical_fmd,
      parent_catalog_active: boolean,
      parent_catalog_locator: pft$catalog_locator,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      resides_on_destination_volumes: boolean,
      selected_volume: rmt$recorded_vsn,
      sfid_dest: gft$system_file_identifier,
      sfid_src: gft$system_file_identifier,
      stored_fmd_size: dmt$stored_fmd_size,
      temp_subfile_list_p: ^pft$subfile_list,
      verify_status: ost$status,
      volume_index: ost$positive_integers;

?? NEWTITLE := ' physically_move_catalog_handler', EJECT ??

    PROCEDURE physically_move_catalog_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           p_sfsa: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      VAR
        local_status: ost$status,
        status_id: ost$status_identifier,
        variant_path: pft$variant_path;

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;

      IF NOT process_non_local_exit THEN
        pfp$log_ascii ('***PF Condition Handler***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
              pmc$msg_origin_system, {critical_message} FALSE, local_status);
        pfp$log_path (variant_path, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
              {critical_message} FALSE, local_status);
      IFEND;

      CASE condition.selector OF
      = pmc$system_conditions, pmc$block_exit_processing, mmc$segment_access_condition =
        IF process_non_local_exit THEN
          RETURN;
        IFEND;

        IF new_catalog_active THEN
          pfp$return_catalog (new_catalog_locator, local_status);
          new_catalog_active := NOT local_status.normal;
          #SPOIL (new_catalog_active);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF catalog_active THEN
          catalog_locator.abort_catalog_operation := TRUE;
          pfp$return_catalog (catalog_locator, local_status);
          catalog_active := NOT local_status.normal;
          #SPOIL (catalog_active);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF parent_catalog_active THEN
          parent_catalog_locator.abort_catalog_operation := TRUE;
          pfp$return_catalog (parent_catalog_locator, local_status);
          parent_catalog_active := NOT local_status.normal;
          #SPOIL (parent_catalog_active);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF job_recovery_inhibited THEN
          syp$pop_inhibit_job_recovery;
          job_recovery_inhibited := FALSE;
          #SPOIL (job_recovery_inhibited);
        IFEND;

        osp$set_status_from_condition (status_id, condition, p_sfsa, local_status, handler_status);
        osp$recoverable_system_error ('UNEXPECTED STATUS', ^local_status);

        status := local_status;
        initiate_non_local_exit;

      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          {syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND physically_move_catalog_handler;
?? OLDTITLE ??
?? NEWTITLE := ' initiate_non_local_exit', EJECT ??

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_physically_move_catalog;

    PROCEND initiate_non_local_exit;
?? OLDTITLE ??
?? EJECT ??

    IF UPPERBOUND (path) <= 2 THEN
      IF move_object_info_p^.set_name = stv$system_set_name THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_sys_set_root_not_moved,
              move_object_info_p^.set_name, status);
      ELSE
        move_root_catalog (path, move_object_info_p, status);
      IFEND;
      RETURN;
    IFEND;

    syp$push_inhibit_job_recovery;
    job_recovery_inhibited := TRUE;
    #SPOIL (job_recovery_inhibited);

  /move_object/
    BEGIN
      catalog_active := FALSE;
      #SPOIL (catalog_active);
      new_catalog_active := FALSE;
      #SPOIL (new_catalog_active);
      parent_catalog_active := FALSE;
      #SPOIL (parent_catalog_active);
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);
      fmd_header.requested_class := rmc$unspecified_file_class;
      p_new_physical_fmd := NIL;
      status.normal := TRUE;

      move_object_info_p^.move_status.move_successful := FALSE;
      move_object_info_p^.move_status.old_subfile_list_p := NIL;
      move_object_info_p^.move_status.new_subfile_list_p := NIL;
      move_object_info_p^.move_status.reason_for_move_failure := pfc$unexpected_abort;

      pfp$get_authority (path, system_privilege, authority, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$catalog_object],
            parent_charge_id, parent_catalog_locator, p_catalog_object, p_internal_cycle_path^.path,
            permit_entry, status);
      parent_catalog_active := status.normal;
      #SPOIL (parent_catalog_active);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      osp$establish_condition_handler (^physically_move_catalog_handler, {block_exit} TRUE);

      pfp$build_fmd_pointer (p_catalog_object^.object_entry.catalog_object_locator.fmd_locator,
            parent_catalog_locator.p_catalog_file, p_physical_fmd);

      gfn_source := p_catalog_object^.object_entry.catalog_object_locator.global_file_name;
      pfp$attach_catalog (^p_physical_fmd^.fmd, parent_catalog_locator.set_name,
            p_catalog_object^.object_entry.internal_object_name, gfn_source,
            pfc$write_access, {catalog_remote} FALSE, catalog_locator, status);
      catalog_active := status.normal;
      #SPOIL (catalog_active);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;
      sfid_src := catalog_locator.system_file_id;

      dmp$get_file_info (sfid_src, file_info, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_header_info (^p_physical_fmd^.fmd, fmd_header, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

      RESET move_object_info_p^.move_status.volume_list_storage_p;
      NEXT temp_subfile_list_p: [1 .. fmd_header.number_of_subfiles] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'catalog',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
        EXIT /move_object/;
      ELSE
        move_object_info_p^.move_status.old_subfile_list_p := temp_subfile_list_p;
      IFEND;

      dmp$get_stored_fmd_subfile_list (^p_physical_fmd^.fmd, file_info.total_allocated_length,
            move_object_info_p^.move_status.old_subfile_list_p, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      validate_volume_threshold (move_object_info_p);
      IF NOT move_object_info_p^.move_status.move_successful AND
            ((move_object_info_p^.move_status.reason_for_move_failure = pfc$volume_threshold_exceeded) OR
            (move_object_info_p^.move_status.reason_for_move_failure = pfc$set_threshold_exceeded)) THEN
        EXIT /move_object/;
      IFEND;

      PUSH p_mass_storage_request_info;
      select_volume (path, {p_cycle_number} NIL, fmd_header,
            move_object_info_p^.move_status.old_subfile_list_p^, file_info, move_object_info_p,
            p_mass_storage_request_info^, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF NOT move_object_info_p^.perform_move THEN
        destination_file_info := file_info;
        simulate_move_object (path, {p_cycle_number} NIL, fmd_header,
              move_object_info_p^.move_status.old_subfile_list_p^, file_info, move_object_info_p, status);
        EXIT /move_object/;
      IFEND;

      selected_volume := p_mass_storage_request_info^.initial_volume;

      pfp$create_catalog (path, p_mass_storage_request_info, authority, {lock_catalog} FALSE,
            new_catalog_locator, status);
      new_catalog_active := status.normal;
      #SPOIL (new_catalog_active);
      IF status.normal THEN
        verify_volume_residence (new_catalog_locator.system_file_id, move_object_info_p^.dest_volume_list_p,
              resides_on_destination_volumes, verify_status);
        IF NOT verify_status.normal THEN
          status := verify_status;
          EXIT /move_object/;
        IFEND;
        IF (NOT resides_on_destination_volumes) AND
              ((UPPERBOUND(move_object_info_p^.dest_volume_list_p^) -
              LOWERBOUND(move_object_info_p^.dest_volume_list_p^)) > 0) THEN
          pfp$destroy_catalog (new_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

          pfp$return_catalog (new_catalog_locator, local_status);
          new_catalog_active := NOT local_status.normal;
          #SPOIL (new_catalog_active);
          pfp$process_unexpected_status (local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

        /try_other_volumes/
          FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.dest_volume_list_p^) DO
            IF (NOT (fmd_header.requested_class IN
                  move_object_info_p^.dest_volume_list_p^ [volume_index]^.ms_class)) OR
                  (move_object_info_p^.dest_volume_list_p^ [volume_index]^.recorded_vsn =
                  selected_volume) THEN
              CYCLE /try_other_volumes/;
            IFEND;
            p_mass_storage_request_info^.initial_volume :=
                  move_object_info_p^.dest_volume_list_p^ [volume_index]^.recorded_vsn;
            pfp$create_catalog (path, p_mass_storage_request_info, authority, {lock_catalog} FALSE,
                  new_catalog_locator, status);
            new_catalog_active := status.normal;
            #SPOIL (new_catalog_active);
            IF status.normal THEN
              verify_volume_residence (new_catalog_locator.system_file_id,
                    move_object_info_p^.dest_volume_list_p, resides_on_destination_volumes, verify_status);
              IF NOT verify_status.normal THEN
                status := verify_status;
                EXIT /move_object/;
              IFEND;
              IF NOT resides_on_destination_volumes THEN
                pfp$destroy_catalog (new_catalog_locator, local_status);
                pfp$process_unexpected_status (local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;

                pfp$return_catalog (new_catalog_locator, local_status);
                new_catalog_active := NOT local_status.normal;
                #SPOIL (new_catalog_active);
                pfp$process_unexpected_status (local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;
                CYCLE /try_other_volumes/;
              IFEND;
            ELSE
              EXIT /try_other_volumes/;
            IFEND;
          FOREND /try_other_volumes/;
        IFEND;
      IFEND;

      IF ((NOT status.normal) AND (status.condition = dme$unable_to_alloc_all_space)) OR
            (NOT resides_on_destination_volumes) THEN
        class_string (1) := fmd_header.requested_class;
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$no_available_space;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_no_available_space, class_string,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'catalog', status);
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size),
              status);
      IFEND;

      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      sfid_dest := new_catalog_locator.system_file_id;
      gfn_dest := new_catalog_locator.internal_catalog_name;

      allocate_space_and_move_data (path, catalog_locator.p_catalog_file, new_catalog_locator.p_catalog_file,
            file_info.eoi_byte_address, {p_cycle_number} NIL, move_object_info_p, fmd_header.requested_class,
            status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      mmp$set_segment_length (new_catalog_locator.p_catalog_file, pfc$catalog_ring,
            file_info.eoi_byte_address, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_size (sfid_dest, stored_fmd_size, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      ALLOCATE p_new_physical_fmd: [[REP stored_fmd_size OF cell]] IN
            parent_catalog_locator.p_catalog_file^.catalog_heap;
      IF p_new_physical_fmd = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'catalog fmd', status);
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd (sfid_dest, p_new_physical_fmd^.fmd, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_file_info (sfid_dest, destination_file_info, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$put_stored_fmd_header_info (fmd_header, ^p_new_physical_fmd^.fmd, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      pfp$compute_checksum (^p_new_physical_fmd^.fmd, #SIZE (p_new_physical_fmd^.fmd),
            p_new_physical_fmd^.checksum);

      dmp$get_stored_fmd_header_info (^p_new_physical_fmd^.fmd, fmd_header, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      NEXT temp_subfile_list_p: [1 .. fmd_header.number_of_subfiles] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'catalog',
              status);
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
        EXIT /move_object/;
      ELSE
        move_object_info_p^.move_status.new_subfile_list_p := temp_subfile_list_p;
      IFEND;

      dmp$get_stored_fmd_subfile_list (^p_new_physical_fmd^.fmd, destination_file_info.total_allocated_length,
            move_object_info_p^.move_status.new_subfile_list_p, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      pfp$build_fmd_locator (p_new_physical_fmd, parent_catalog_locator.p_catalog_file,
            p_catalog_object^.object_entry.catalog_object_locator.fmd_locator);

      p_catalog_object^.object_entry.catalog_object_locator.global_file_name := gfn_dest;
      pfp$compute_checksum (^p_catalog_object^.object_entry, #SIZE (pft$object_entry),
            p_catalog_object^.checksum);

      catalog_locator.queuing_info.set_catalog_alarm := TRUE;
      move_object_info_p^.move_status.move_successful := TRUE;
      move_object_info_p^.move_status.allocated_size := destination_file_info.total_allocated_length;
      move_object_info_p^.move_status.data_residence := pfc$unreleasable_data;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

    END /move_object/;

    IF new_catalog_active THEN
      IF NOT move_object_info_p^.move_status.move_successful THEN
        pfp$destroy_catalog (new_catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;

      pfp$return_catalog (new_catalog_locator, local_status);
      new_catalog_active := NOT local_status.normal;
      #SPOIL (new_catalog_active);
      pfp$process_unexpected_status (local_status);

      IF (NOT move_object_info_p^.move_status.move_successful) AND (p_new_physical_fmd <> NIL) THEN
        osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
              #OFFSET(^catalog_locator.p_catalog_file^.catalog_heap) - 16),
              ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_new_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR', 'catalog',
                prevalidate_free_result, #OFFSET(p_new_physical_fmd));
          p_new_physical_fmd := NIL;
        IFEND;
      IFEND;
    IFEND;

    IF catalog_active THEN
      IF move_object_info_p^.perform_move AND move_object_info_p^.move_status.move_successful THEN
        pfp$destroy_catalog (catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
        osp$prevalidate_free ((#OFFSET(p_physical_fmd) -
              #OFFSET(^parent_catalog_locator.p_catalog_file^.catalog_heap) - 16),
              ^parent_catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_physical_fmd IN parent_catalog_locator.p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, {p_cycle_number} NIL, 'FILE_MEDIA_DESCRIPTOR', 'catalog',
                prevalidate_free_result, #OFFSET(p_physical_fmd));
          p_physical_fmd := NIL;
        IFEND;
      ELSE
        pfp$return_catalog (catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;
      catalog_active := NOT local_status.normal;
      #SPOIL (catalog_active);
    IFEND;

    update_move_object_info (move_object_info_p, pfc$catalog_object, fmd_header,
          move_object_info_p^.move_status.old_subfile_list_p,
          move_object_info_p^.move_status.new_subfile_list_p, file_info, destination_file_info, local_status);
    pfp$process_unexpected_status (local_status);

    osp$disestablish_cond_handler;

    IF parent_catalog_active THEN
      pfp$return_catalog (parent_catalog_locator, local_status);
      parent_catalog_active := NOT local_status.normal;
      #SPOIL (parent_catalog_active);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
    job_recovery_inhibited := FALSE;
    #SPOIL (job_recovery_inhibited);

  PROCEND pfp$r2_physically_move_catalog;
?? OLDTITLE ??
?? NEWTITLE := ' pfp$r2_physically_move_cycle', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$r2_physically_move_cycle
    (    path: pft$complete_path;
         cycle_selector: pft$cycle_selector;
         move_object_info_p: ^pft$move_object_info;
     VAR cycle_number: fst$cycle_number;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      allocate_space_status: ost$status,
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      class_string: string (1),
      destination_file_attached: boolean,
      destination_file_info: dmt$file_information,
      destination_file_open: boolean,
      device_class: rmt$device_class,
      file_allocated_length: integer,
      file_damaged: boolean,
      file_info: dmt$file_information,
      file_move_successful: boolean,
      fs_path_size: fst$path_size,
      fmd_header: pft$fmd_header,
      fmd_modified: boolean,
      gfn_dest: dmt$global_file_name,
      gfn_source: dmt$global_file_name,
      ignore_status: ost$status,
      job_recovery_inhibited: boolean,
      local_status: ost$status,
      p_cycle: ^pft$physical_cycle,
      p_cycle_list: ^pft$cycle_list,
      p_file_object: ^pft$physical_object,
      p_fs_path: ^fst$path,
      p_internal_cycle_path: ^pft$internal_cycle_path,
      p_mass_storage_request_info: ^fmt$mass_storage_request_info,
      p_new_physical_fmd: ^pft$physical_fmd,
      p_new_subfile_list: ^pft$subfile_list,
      p_path_string: ^ost$string,
      p_physical_fmd: ^pft$physical_fmd,
      p_temp_physical_fmd: ^pft$physical_fmd,
      parent_charge_id: pft$charge_id,
      permit_entry: pft$permit_entry,
      prevalidate_free_result: ost$prevalidate_free_result,
      process_non_local_exit: boolean,
      resides_on_destination_volumes: boolean,
      save_modification_date_time: ost$date_time,
      seg_pointer_dest: mmt$segment_pointer,
      seg_pointer_src: mmt$segment_pointer,
      selected_volume: rmt$recorded_vsn,
      sfid_dest: gft$system_file_identifier,
      sfid_src: gft$system_file_identifier,
      share_selections: pft$share_selections,
      source_file_attached: boolean,
      source_file_open: boolean,
      source_volume_list_p: ^pft$mo_volume_list_p,
      stored_fmd_size: dmt$stored_fmd_size,
      subfile_index: ost$positive_integers,
      temp_fmd_header: pft$fmd_header,
      temp_subfile_list_p: ^pft$subfile_list,
      usage_selections: pft$usage_selections,
      verify_status: ost$status,
      volume_index: ost$positive_integers;

    VAR
      segment_attributes: array [1 .. 1] of mmt$attribute_descriptor;

*if false
{Debug Code

?? NEWTITLE := ' TEST_CONDITION_HANDLER', EJECT ??

     PROCEDURE test_condition_handler
     ( value: integer);

      VAR
        ignore_status: ost$status,
        psa: ^ost$stack_frame_save_area,
        test_condition: pmt$condition;

  test_condition.selector := mmc$segment_access_condition;

  IF value = 1 THEN
    test_condition.segment_access_condition.identifier := mmc$sac_read_beyond_eoi;
  ELSE
    test_condition.segment_access_condition.identifier := mmc$sac_io_read_error;
  IFEND;
  test_condition.segment_access_condition.segment := seg_pointer_src.seq_pointer;
  psa := #previous_save_area ();
  pmp$test_condition_handler (test_condition, psa, ignore_status);

     PROCEND test_condition_handler;
{Debug Code End
*ifend

?? NEWTITLE := ' physically_move_cycle_handler', EJECT ??

    PROCEDURE physically_move_cycle_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           p_sfsa: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

{We always log the call so we can identify the file, as ex. the condition handler cannot find the path
{of a file with read error.
{ - close & detach source file
{ - close & detach the destination file
{ - destroy the destination file if necessary
{ - return the catalog
{ - emit a stack trace except for IO read errors on the source file

      VAR
        local_status: ost$status,
        p_fs_path: ^fst$path,
        source_read_error: boolean,
        status_id: ost$status_identifier,
        variant_path: pft$variant_path;

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;

      source_read_error := source_file_open
{     } AND (condition.selector = mmc$segment_access_condition)
{     } AND (condition.segment_access_condition.identifier = mmc$sac_io_read_error)
{     } AND (#SEGMENT (seg_pointer_src.seq_pointer) = #SEGMENT (condition.segment_access_condition.segment));

      IF NOT process_non_local_exit THEN
*if true
        pfp$log_ascii ('***PF Condition Handler***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
                  pmc$msg_origin_system, {critical_message} FALSE, local_status);
*ifend
        IF source_read_error THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$log_io_read_error (p_fs_path^ (1, fs_path_size), gfc$fk_job_permanent_file,
                condition.segment_access_condition.segment);
        ELSE
*if false
          pfp$log_ascii ('***PF Condition Handler***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
                pmc$msg_origin_system, {critical_message} FALSE, local_status);
*ifend
          pfp$log_path (variant_path, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
                {critical_message} FALSE, local_status);
        IFEND;
      IFEND;

      CASE condition.selector OF
      = pmc$system_conditions, pmc$block_exit_processing, mmc$segment_access_condition =
        IF process_non_local_exit THEN
          RETURN;
        IFEND;

        IF source_file_open AND catalog_active THEN
          mmp$close_segment (seg_pointer_src, pfc$catalog_ring, local_status);
          source_file_open := NOT local_status.normal;
          #SPOIL (source_file_open);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF source_file_attached AND catalog_active THEN
          usage_selections := -$pft$usage_selections [];
          pfp$detach_permanent_file (^path, sfid_src, usage_selections, {catalog_access_allowed} TRUE,
                p_cycle, catalog_locator.p_catalog_file, dmc$df_ignore_file_info, fmd_modified, file_info,
                local_status);
          source_file_attached := NOT local_status.normal;
          #SPOIL (source_file_attached);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF destination_file_open THEN
          mmp$close_segment (seg_pointer_dest, pfc$catalog_ring, local_status);
          destination_file_open := NOT local_status.normal;
          #SPOIL (destination_file_open);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF destination_file_attached THEN
          dm_detach_file (sfid_dest, local_status);
          destination_file_attached := NOT local_status.normal;
          #SPOIL (destination_file_attached);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF catalog_active THEN
          catalog_locator.abort_catalog_operation := TRUE;
          pfp$return_catalog (catalog_locator, local_status);
          catalog_active := NOT local_status.normal;
          #SPOIL (catalog_active);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF job_recovery_inhibited THEN
          syp$pop_inhibit_job_recovery;
          job_recovery_inhibited := FALSE;
          #SPOIL (job_recovery_inhibited);
        IFEND;

        osp$set_status_from_condition (status_id, condition, p_sfsa, local_status, handler_status);
        IF NOT source_read_error THEN
          osp$recoverable_system_error ('UNEXPECTED STATUS', ^local_status);
        IFEND;

        status := local_status;
        initiate_non_local_exit;

      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          {syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND physically_move_cycle_handler;
?? OLDTITLE ??
?? NEWTITLE := ' initiate_non_local_exit', EJECT ??

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT pfp$r2_physically_move_cycle;

    PROCEND initiate_non_local_exit;
?? OLDTITLE ??
?? EJECT ??

    syp$push_inhibit_job_recovery;
    job_recovery_inhibited := TRUE;
    #SPOIL (job_recovery_inhibited);

  /move_object/
    BEGIN
      catalog_active := FALSE;
      #SPOIL (catalog_active);
      destination_file_attached := FALSE;
      #SPOIL (destination_file_attached);
      destination_file_open := FALSE;
      #SPOIL (destination_file_open);
      file_move_successful := FALSE;
      #SPOIL (file_move_successful);
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);
      source_file_attached := FALSE;
      #SPOIL (source_file_attached);
      source_file_open := FALSE;
      #SPOIL (source_file_open);
      p_new_physical_fmd := NIL;
      status.normal := TRUE;

      segment_attributes [1].keyword := mmc$kw_software_attributes;
      segment_attributes [1].software_attri_set := $mmt$software_attribute_set
            [mmc$sa_read_transfer_unit, mmc$sa_free_behind];

      move_object_info_p^.move_status.move_successful := FALSE;
      move_object_info_p^.move_status.old_subfile_list_p := NIL;
      move_object_info_p^.move_status.new_subfile_list_p := NIL;
      move_object_info_p^.move_status.reason_for_move_failure := pfc$unexpected_abort;

      pfp$get_authority (path, system_privilege, authority, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      PUSH p_internal_cycle_path: [1 .. UPPERBOUND (path)];
      pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
            parent_charge_id, catalog_locator, p_file_object, p_internal_cycle_path^.path, permit_entry,
            status);
      catalog_active := status.normal;
      #SPOIL (catalog_active);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      osp$establish_condition_handler (^physically_move_cycle_handler, {block_exit} TRUE);

      pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
            catalog_locator.p_catalog_file, p_cycle_list);
      pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      cycle_number := p_cycle^.cycle_entry.cycle_number;
      save_modification_date_time := p_cycle^.cycle_entry.cycle_statistics.modification_date_time;

      IF p_cycle^.cycle_entry.data_residence = pfc$offline_data THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_data_resides_offline,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
               {radix} 10, {include_radix_specifier} FALSE, status);
        EXIT /move_object/;
      IFEND;

      IF p_cycle^.cycle_entry.device_information.device_class_defined THEN
        pfp$convert_device_class_to_rm (p_cycle^.cycle_entry.device_information.device_class, device_class);
      ELSE
        device_class := rmc$mass_storage_device;
      IFEND;

      IF device_class <> rmc$mass_storage_device THEN
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_invalid_device_class,
              p_path_string^.value (1, p_path_string^.size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              amv$device_class_names [device_class].name, status);
        EXIT /move_object/;
      IFEND;

      pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, catalog_locator.p_catalog_file,
            p_physical_fmd);

      IF p_physical_fmd = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$undefined_data,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
              {radix} 10, {include_radix_specifier} FALSE, status);
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_header_info (^p_physical_fmd^.fmd, fmd_header, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF p_cycle^.cycle_entry.attach_status.attach_count > 0 THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
               {radix} 10, {include_radix_specifier} FALSE, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict, status);
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$cycle_busy;
        EXIT /move_object/;
      IFEND;

      gfn_source := p_cycle^.cycle_entry.internal_cycle_name;
      usage_selections := -$pft$usage_selections [];
      share_selections := -$pft$share_selections [];
      dm_attach_file (path, catalog_locator.p_catalog_file, usage_selections, share_selections, p_cycle,
            sfid_src, file_damaged, status);
      source_file_attached := status.normal;
      #SPOIL (source_file_attached);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_file_info (sfid_src, file_info, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;
      file_allocated_length := file_info.total_allocated_length;

      move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

      RESET move_object_info_p^.move_status.volume_list_storage_p;
      NEXT temp_subfile_list_p: [1 .. fmd_header.number_of_subfiles] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'file',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
        EXIT /move_object/;
      ELSE
        move_object_info_p^.move_status.old_subfile_list_p := temp_subfile_list_p;
      IFEND;

      dmp$get_stored_fmd_subfile_list (^p_physical_fmd^.fmd, file_info.total_allocated_length,
            move_object_info_p^.move_status.old_subfile_list_p, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      validate_volume_threshold (move_object_info_p);
      IF NOT move_object_info_p^.move_status.move_successful AND
            ((move_object_info_p^.move_status.reason_for_move_failure = pfc$volume_threshold_exceeded) OR
            (move_object_info_p^.move_status.reason_for_move_failure = pfc$set_threshold_exceeded)) THEN
        EXIT /move_object/;
      IFEND;

      IF (p_cycle^.cycle_entry.data_residence = pfc$releasable_data) AND
            (move_object_info_p^.release_mass_storage = pfc$always) THEN
        release_cycle_data (path, move_object_info_p^.perform_move, p_cycle, catalog_locator.p_catalog_file,
              status);
        IF status.normal THEN
          move_object_info_p^.move_status.move_successful := TRUE;
          move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
          move_object_info_p^.move_status.data_residence := pfc$offline_data;
          move_object_info_p^.move_status.modification_date_time :=
                p_cycle^.cycle_entry.data_modification_date_time;
          move_object_info_p^.move_status.ms_class := fmd_header.requested_class;
          EXIT /move_object/;
        ELSEIF (status.condition = pfe$empty_archive_list) OR
              (status.condition = pfe$data_not_releasable) THEN
          status.normal := TRUE;
        ELSE
          EXIT /move_object/;
        IFEND;
      IFEND;

      PUSH p_mass_storage_request_info;
      select_volume (path, ^p_cycle^.cycle_entry.cycle_number, fmd_header,
            move_object_info_p^.move_status.old_subfile_list_p^, file_info, move_object_info_p,
            p_mass_storage_request_info^, status);

      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF NOT move_object_info_p^.perform_move THEN
        destination_file_info := file_info;
        simulate_move_object (path, ^p_cycle^.cycle_entry.cycle_number, fmd_header,
              move_object_info_p^.move_status.old_subfile_list_p^, file_info, move_object_info_p, status);
        IF status.normal THEN
          move_object_info_p^.move_status.data_residence := p_cycle^.cycle_entry.data_residence;
          move_object_info_p^.move_status.modification_date_time :=
                p_cycle^.cycle_entry.cycle_statistics.modification_date_time;
        ELSEIF ((status.condition = pfe$movc_insufficient_space) OR
              (status.condition = pfe$movc_no_available_space)) AND
              (p_cycle^.cycle_entry.data_residence = pfc$releasable_data) AND
              (move_object_info_p^.release_mass_storage = pfc$when_insufficient_space) THEN
          release_cycle_data (path, move_object_info_p^.perform_move, p_cycle,
                catalog_locator.p_catalog_file, local_status);
          IF local_status.normal THEN
            status.normal := TRUE;
            move_object_info_p^.move_status.move_successful := TRUE;
            move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
            move_object_info_p^.move_status.data_residence := pfc$offline_data;
            move_object_info_p^.move_status.modification_date_time :=
                  p_cycle^.cycle_entry.data_modification_date_time;
            move_object_info_p^.move_status.ms_class := fmd_header.requested_class;
          IFEND;
        IFEND;
        EXIT /move_object/;
      IFEND;

      selected_volume := p_mass_storage_request_info^.initial_volume;

      mmp$open_file_segment (sfid_src, ^segment_attributes, mmc$cell_pointer, pfc$catalog_ring,
            sfc$no_limit, seg_pointer_src, status);
      source_file_open := status.normal;
      #SPOIL (source_file_open);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      resides_on_destination_volumes := TRUE;
      usage_selections := -$pft$usage_selections [];
      share_selections := $pft$share_selections [];
      pfp$dm_create_file_entry (path, p_cycle^.cycle_entry.cycle_number, authority, usage_selections,
            share_selections, p_mass_storage_request_info, sfid_dest, gfn_dest, status);
      destination_file_attached := status.normal;
      #SPOIL (destination_file_attached);
      IF status.normal THEN
        verify_volume_residence (sfid_dest, move_object_info_p^.dest_volume_list_p,
              resides_on_destination_volumes, verify_status);
        IF NOT verify_status.normal THEN
          status := verify_status;
          EXIT /move_object/;
        IFEND;
        IF (NOT resides_on_destination_volumes) AND
              ((UPPERBOUND(move_object_info_p^.dest_volume_list_p^) -
              LOWERBOUND(move_object_info_p^.dest_volume_list_p^)) > 0) THEN

          dmp$get_stored_fmd_size (sfid_dest, stored_fmd_size, local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

          PUSH p_temp_physical_fmd: [[REP stored_fmd_size OF cell]];
          dmp$get_stored_fmd (sfid_dest, p_temp_physical_fmd^.fmd, local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

          dm_detach_file (sfid_dest, local_status);
          destination_file_attached := NOT local_status.normal;
          #SPOIL (destination_file_attached);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

          dmp$destroy_permanent_file (gfn_dest, p_temp_physical_fmd^.fmd, local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

        /try_other_volumes/
          FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.dest_volume_list_p^) DO
            IF (NOT (fmd_header.requested_class IN
                  move_object_info_p^.dest_volume_list_p^ [volume_index]^.ms_class)) OR
                  (move_object_info_p^.dest_volume_list_p^ [volume_index]^.recorded_vsn =
                  selected_volume) THEN
              CYCLE /try_other_volumes/;
            IFEND;
            p_mass_storage_request_info^.initial_volume :=
                  move_object_info_p^.dest_volume_list_p^ [volume_index]^.recorded_vsn;
            pfp$dm_create_file_entry (path, p_cycle^.cycle_entry.cycle_number, authority, usage_selections,
                  share_selections, p_mass_storage_request_info, sfid_dest, gfn_dest, status);
            destination_file_attached := status.normal;
            #SPOIL (destination_file_attached);
            IF status.normal THEN
              verify_volume_residence (sfid_dest, move_object_info_p^.dest_volume_list_p,
                    resides_on_destination_volumes, verify_status);
              IF NOT verify_status.normal THEN
                status := verify_status;
                EXIT /move_object/;
              IFEND;

              IF NOT resides_on_destination_volumes THEN
                dmp$get_stored_fmd_size (sfid_dest, stored_fmd_size, local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;

                PUSH p_temp_physical_fmd: [[REP stored_fmd_size OF cell]];
                dmp$get_stored_fmd (sfid_dest, p_temp_physical_fmd^.fmd, local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;

                dm_detach_file (sfid_dest, local_status);
                destination_file_attached := NOT local_status.normal;
                #SPOIL (destination_file_attached);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;

                dmp$destroy_permanent_file (gfn_dest, p_temp_physical_fmd^.fmd, local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;
                CYCLE /try_other_volumes/;
              IFEND;
            IFEND;
          FOREND /try_other_volumes/;
        IFEND;
      IFEND;

      IF ((NOT status.normal) AND (status.condition = dme$unable_to_alloc_all_space)) OR
            (NOT resides_on_destination_volumes) THEN
        class_string (1) := fmd_header.requested_class;
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$no_available_space;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_no_available_space, class_string,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'file', status);
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
      IFEND;

      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      mmp$open_file_segment (sfid_dest, ^segment_attributes, mmc$cell_pointer, pfc$catalog_ring,
            sfc$no_limit, seg_pointer_dest, status);
      destination_file_open := status.normal;
      #SPOIL (destination_file_open);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF file_info.eoi_byte_address <= pfc$move_while_locked_limit THEN
        allocate_space_and_move_data (path, seg_pointer_src.seq_pointer, seg_pointer_dest.seq_pointer,
              file_info.eoi_byte_address, ^cycle_number, move_object_info_p, fmd_header.requested_class,
              status);
        IF NOT status.normal THEN
          EXIT /move_object/;
        IFEND;
      ELSE
        pfp$return_catalog (catalog_locator, status);
        catalog_active := NOT status.normal;
        #SPOIL (catalog_active);
        IF NOT status.normal THEN
          EXIT /move_object/;
        IFEND;

        syp$pop_inhibit_job_recovery;
        job_recovery_inhibited := FALSE;
        #SPOIL (job_recovery_inhibited);

        allocate_space_and_move_data (path, seg_pointer_src.seq_pointer, seg_pointer_dest.seq_pointer,
              file_info.eoi_byte_address, ^cycle_number, move_object_info_p, fmd_header.requested_class,
              allocate_space_status);

*if false
{Debug Code
IF (osv$debug[13] = 1) OR (osv$debug[13] = 2) THEN
  test_condition_handler (osv$debug[13]);
IFEND;
{Debug Code End
*ifend

        syp$push_inhibit_job_recovery;
        job_recovery_inhibited := TRUE;
        #SPOIL (job_recovery_inhibited);

        pfp$access_object (path, pfc$write_access, authority, $pft$object_selections [pfc$file_object],
              parent_charge_id, catalog_locator, p_file_object, p_internal_cycle_path^.path, permit_entry,
              status);
        catalog_active := status.normal;
        #SPOIL (catalog_active);
        IF NOT status.normal THEN
          EXIT /move_object/;
        IFEND;

*if false
{Debug Code
IF (osv$debug[13] = 3) OR (osv$debug[13] = 4) THEN
  test_condition_handler (osv$debug[13] - 2);
IFEND;
{Debug Code End
*ifend

        pfp$build_cycle_list_pointer (p_file_object^.object_entry.cycle_list_locator,
              catalog_locator.p_catalog_file, p_cycle_list);

        pfp$locate_cycle (path, p_cycle_list, cycle_selector, p_cycle, status);
        IF NOT status.normal THEN
          EXIT /move_object/;
        IFEND;

        IF NOT allocate_space_status.normal THEN
          status := allocate_space_status;
          EXIT /move_object/;
        IFEND;
      IFEND;

      mmp$set_segment_length (seg_pointer_dest.seq_pointer, pfc$catalog_ring, file_info.eoi_byte_address,
            status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF (p_cycle^.cycle_entry.attach_status.attach_count > 0) OR
            (save_modification_date_time <> p_cycle^.cycle_entry.cycle_statistics.modification_date_time) OR
            (p_cycle^.cycle_entry.internal_cycle_name <> gfn_source) THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$cycle_busy,
              p_fs_path^ (1, fs_path_size), status);
        osp$append_status_integer (osc$status_parameter_delimiter, p_cycle^.cycle_entry.cycle_number,
               {radix} 10, {include_radix_specifier} FALSE, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, pfc$multiple_job_usage_conflict, status);
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$cycle_busy;
        EXIT /move_object/;
      IFEND;

      verify_volume_residence (sfid_dest, move_object_info_p^.dest_volume_list_p,
            resides_on_destination_volumes, verify_status);
      IF NOT verify_status.normal THEN
        status := verify_status;
        EXIT /move_object/;
      IFEND;

      IF NOT resides_on_destination_volumes THEN
        class_string (1) := fmd_header.requested_class;
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$insufficient_space;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_insufficient_space, class_string,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'file', status);
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
        osp$append_status_parameter (osc$status_parameter_delimiter,
             p_path_string^.value (1, p_path_string^.size), status);
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_size (sfid_dest, stored_fmd_size, local_status);
      IF NOT local_status.normal THEN
        status := local_status;
        EXIT /move_object/;
      IFEND;

      ALLOCATE p_new_physical_fmd: [[REP stored_fmd_size OF cell]] IN
            catalog_locator.p_catalog_file^.catalog_heap;
      IF p_new_physical_fmd = NIL THEN
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$catalog_full, 'cycle fmd', status);
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd (sfid_dest, p_new_physical_fmd^.fmd, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_file_info (sfid_dest, destination_file_info, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$put_stored_fmd_header_info (fmd_header, ^p_new_physical_fmd^.fmd, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_header_info (^p_new_physical_fmd^.fmd, fmd_header, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      NEXT temp_subfile_list_p: [1 .. fmd_header.number_of_subfiles] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'file',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
        EXIT /move_object/;
      ELSE
        move_object_info_p^.move_status.new_subfile_list_p := temp_subfile_list_p;
      IFEND;

      dmp$get_stored_fmd_subfile_list (^p_new_physical_fmd^.fmd, destination_file_info.total_allocated_length,
            move_object_info_p^.move_status.new_subfile_list_p, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF file_damaged THEN
        dmp$change_file_damaged (sfid_dest, {file_damaged} TRUE, gfn_dest, status);
        IF NOT status.normal THEN
          EXIT /move_object/;
        IFEND;
      IFEND;

      pfp$compute_checksum (^p_new_physical_fmd^.fmd, #SIZE (p_new_physical_fmd^.fmd),
            p_new_physical_fmd^.checksum);

      pfp$build_fmd_locator (p_new_physical_fmd, catalog_locator.p_catalog_file,
            p_cycle^.cycle_entry.fmd_locator);

      move_object_info_p^.move_status.move_successful := TRUE;
      file_move_successful := TRUE;
      #SPOIL (file_move_successful);

      p_cycle^.cycle_entry.internal_cycle_name := gfn_dest;

      pfp$compute_checksum (^p_cycle^.cycle_entry, #SIZE (pft$cycle_entry), p_cycle^.checksum);

      move_object_info_p^.move_status.allocated_size := destination_file_info.total_allocated_length;
      move_object_info_p^.move_status.data_residence := p_cycle^.cycle_entry.data_residence;
      move_object_info_p^.move_status.modification_date_time :=
            p_cycle^.cycle_entry.cycle_statistics.modification_date_time;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

    END /move_object/;

    IF catalog_active AND (NOT status.normal) AND ((status.condition = pfe$movc_insufficient_space) OR
          (status.condition = pfe$movc_no_available_space)) AND
          (p_cycle^.cycle_entry.data_residence = pfc$releasable_data) AND
          (move_object_info_p^.release_mass_storage = pfc$when_insufficient_space) THEN
      release_cycle_data (path, move_object_info_p^.perform_move, p_cycle,
            catalog_locator.p_catalog_file, local_status);
      IF local_status.normal THEN
        status.normal := TRUE;
        move_object_info_p^.move_status.move_successful := TRUE;
        move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
        move_object_info_p^.move_status.data_residence := pfc$offline_data;
        move_object_info_p^.move_status.modification_date_time :=
              p_cycle^.cycle_entry.data_modification_date_time;
        move_object_info_p^.move_status.ms_class := fmd_header.requested_class;
      IFEND;
    IFEND;

    IF source_file_open AND catalog_active THEN
      mmp$close_segment (seg_pointer_src, pfc$catalog_ring, local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    IF destination_file_open THEN
      mmp$close_segment (seg_pointer_dest, pfc$catalog_ring, local_status);
      destination_file_open := NOT local_status.normal;
      #SPOIL (destination_file_open);
      pfp$process_unexpected_status (local_status);
    IFEND;

    IF destination_file_attached THEN
      dmp$get_stored_fmd_size (sfid_dest, stored_fmd_size, local_status);
      IF local_status.normal THEN
        PUSH p_temp_physical_fmd: [[REP stored_fmd_size OF cell]];
        dmp$get_stored_fmd (sfid_dest, p_temp_physical_fmd^.fmd, local_status);
        IF local_status.normal THEN
          dm_detach_file (sfid_dest, local_status);
          destination_file_attached := NOT local_status.normal;
          #SPOIL (destination_file_attached);
          IF local_status.normal AND (NOT file_move_successful) THEN
            dmp$destroy_permanent_file (gfn_dest, p_temp_physical_fmd^.fmd, local_status);
          IFEND;
        IFEND;
      IFEND;
      IF (NOT file_move_successful) AND (p_new_physical_fmd <> NIL) THEN
        osp$prevalidate_free ((#OFFSET(p_new_physical_fmd) -
              #OFFSET(^catalog_locator.p_catalog_file^.catalog_heap) - 16),
              ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
        IF prevalidate_free_result = osc$heap_free_valid THEN
          FREE p_new_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
        ELSE
          pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
                prevalidate_free_result, #OFFSET(p_new_physical_fmd));
          p_new_physical_fmd := NIL;
        IFEND;
      IFEND;
    IFEND;

    IF source_file_attached AND catalog_active THEN
      usage_selections := -$pft$usage_selections [];
      pfp$detach_permanent_file (^path, sfid_src, usage_selections, {catalog_access_allowed} TRUE, p_cycle,
            catalog_locator.p_catalog_file, dmc$df_ignore_trimmed_length, fmd_modified, file_info,
            local_status);
      pfp$process_unexpected_status (local_status);
    IFEND;

    IF file_move_successful AND catalog_active THEN
      dmp$destroy_permanent_file (gfn_source, p_physical_fmd^.fmd, local_status);
      osp$prevalidate_free ((#OFFSET(p_physical_fmd) -
            #OFFSET(^catalog_locator.p_catalog_file^.catalog_heap) - 16),
            ^catalog_locator.p_catalog_file^.catalog_heap, prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_physical_fmd IN catalog_locator.p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR', 'file',
              prevalidate_free_result, #OFFSET(p_physical_fmd));
        p_physical_fmd := NIL;
      IFEND;
      IF (NOT local_status.normal) AND (local_status.condition <> dme$file_descriptor_not_deleted) THEN
        pfp$process_unexpected_status (local_status);
      IFEND;
    IFEND;

    update_move_object_info (move_object_info_p, pfc$file_object, fmd_header,
          move_object_info_p^.move_status.old_subfile_list_p,
          move_object_info_p^.move_status.new_subfile_list_p, file_info, destination_file_info, local_status);
    pfp$process_unexpected_status (local_status);

    osp$disestablish_cond_handler;

    IF catalog_active THEN
      pfp$return_catalog (catalog_locator, local_status);
      catalog_active := NOT local_status.normal;
      #SPOIL (catalog_active);
      pfp$process_unexpected_status (local_status);
    IFEND;

    syp$pop_inhibit_job_recovery;
    job_recovery_inhibited := FALSE;
    #SPOIL (job_recovery_inhibited);

  PROCEND pfp$r2_physically_move_cycle;
?? OLDTITLE ??
?? NEWTITLE := ' allocate_space_and_move_data', EJECT ??

  PROCEDURE allocate_space_and_move_data
    (    path: pft$complete_path;
         source_pva: ^cell;
         destination_pva: ^cell;
         length: integer;
         p_cycle_number: ^fst$cycle_number;
         move_object_info_p: ^pft$move_object_info;
         mass_storage_class: dmt$class_member;
     VAR status: ost$status);

    CONST
      destination_transfer_size =  4000(16), {16,384 bytes}
      maximum_byte_move = 80000(16), {512K = 524,288}
      minimum_preset = 4096,
      unable_to_alloc_all_space_delay = 5 * 1000, {wait 5 seconds if out of MAT space}
      source_transfer_size =  10000(16); {65,536 bytes}

    VAR
      advise_pointer: ^cell,
      advise_size: integer,
      bytes_to_move: amt$file_byte_address,
      class_string: string(1),
      current_byte_address: amt$file_byte_address,
      from_pointer: ^cell,
      fs_path_size: fst$path_size,
      ignore_free_behind: boolean,
      ignore_transfer_size: 0..15,
      local_status: ost$status,
      no_space_available: boolean,
      p_fs_path: ^fst$path,
      p_path_string: ^ost$string,
      to_pointer: ^cell;

*if false
{Debug Code

?? NEWTITLE := ' TEST_CONDITION_HANDLER', EJECT ??

     PROCEDURE test_condition_handler;

      VAR
        ignore_status: ost$status,
        psa: ^ost$stack_frame_save_area,
        test_condition: pmt$condition;

  test_condition.selector := mmc$segment_access_condition;
  test_condition.segment_access_condition.identifier := mmc$sac_io_read_error;
  test_condition.segment_access_condition.segment :=
        #ADDRESS ( #RING (source_pva), #SEGMENT (source_pva), current_byte_address);
  psa := #previous_save_area ();
  pmp$test_condition_handler (test_condition, psa, ignore_status);

     PROCEND test_condition_handler;
{Debug Code End
*ifend
?? NEWTITLE := ' ALLOC_SPACE_AND_MOVE_DATA_HDLR', EJECT ??

    PROCEDURE alloc_space_and_move_data_hdlr
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           p_sfsa: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

{For Source read errors the IO is logged, as the standard handler cannot find the file path. Then, we
{set the abnormal status (mme$io_read_error) and return control to the caller.
{Other conditions are passed to the callers condition handler.

      VAR
        fs_path_size: fst$path_size,
        p_fs_path: ^fst$path,
        p_path_string: ^ost$string,
        source_read_error: boolean;

      source_read_error := (condition.selector = mmc$segment_access_condition)
{     } AND (condition.segment_access_condition.identifier = mmc$sac_io_read_error)
{     } AND (#SEGMENT (source_pva) = #SEGMENT (condition.segment_access_condition.segment));

      IF source_read_error THEN
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$io_error;

        IF p_cycle_number = NIL THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);

          osp$log_io_read_error (p_fs_path^ (1, fs_path_size), gfc$fk_catalog,
                condition.segment_access_condition.segment);
        ELSE
          PUSH p_path_string;
          pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
          osp$log_io_read_error (p_path_string^.value (1, p_path_string^.size), gfc$fk_job_permanent_file,
                condition.segment_access_condition.segment);
        IFEND;

        osp$set_status_from_condition ('PM', condition, p_sfsa, status, handler_status);
        EXIT allocate_space_and_move_data; {----->

      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      IFEND;

    PROCEND alloc_space_and_move_data_hdlr;
?? OLDTITLE ??
?? EJECT ??

    osp$establish_condition_handler (^alloc_space_and_move_data_hdlr, {block_exit} FALSE);

  /preallocate_file_space/
    REPEAT
      mmp$os_preallocate_file_space (destination_pva, length, {maximum_wait_seconds} 1, status);
      IF NOT status.normal THEN
        IF status.condition = dme$unable_to_alloc_all_space THEN
          mmp$verify_no_space_available (destination_pva, no_space_available, local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            RETURN;
          ELSE
            IF no_space_available THEN
              move_object_info_p^.move_status.move_successful := FALSE;
              move_object_info_p^.move_status.reason_for_move_failure := pfc$insufficient_space;
              class_string (1) := mass_storage_class;
              osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_insufficient_space,
                    class_string, status);
              osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name,
                    status);
              IF p_cycle_number = NIL THEN
                osp$append_status_parameter (osc$status_parameter_delimiter, 'catalog', status);
                PUSH p_fs_path;
                pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      p_fs_path^ (1, fs_path_size), status);
              ELSE
                osp$append_status_parameter (osc$status_parameter_delimiter, 'file', status);
                PUSH p_path_string;
                pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
                osp$append_status_parameter (osc$status_parameter_delimiter,
                      p_path_string^.value (1, p_path_string^.size), status);
              IFEND;
              RETURN;
            ELSE
              pmp$delay (unable_to_alloc_all_space_delay, local_status);
              CYCLE /preallocate_file_space/
            IFEND;
          IFEND;
        ELSE
          RETURN;
        IFEND;
      IFEND;
    UNTIL status.normal;

  /move_data/
    BEGIN
      current_byte_address := 0;

      WHILE current_byte_address < length DO
        bytes_to_move := maximum_byte_move;
        IF (current_byte_address + bytes_to_move) >= length THEN
          bytes_to_move := length - current_byte_address;
        IFEND;

        from_pointer := #ADDRESS ( #RING (source_pva), #SEGMENT (source_pva), current_byte_address);
        to_pointer := #address ( #RING (destination_pva), #SEGMENT (destination_pva), current_byte_address);

        IF (current_byte_address = 0) AND (bytes_to_move > minimum_preset) THEN

{ If the file is small (length is <= MINIMUM_PRESET (4096)), use I#MOVE without
{ presetting streaming mode.
{ If the file is large (length is > MINIMUM_PRESET (4096)), data is moved in
{ blocks of MAXIMUM_BYTE_MOVE (512K) bytes and MMP$PRESET_PAGE_STREAMING is
{ called prior to the first move to set streaming mode on both the source and
{ destination files before calling I#MOVE.  The reason for setting streaming
{ mode on the destination file is to enable FREE_BEHIND.

          mmp$preset_page_streaming ({preset_and_save_ts_fb} TRUE, from_pointer, source_transfer_size,
                ignore_transfer_size, ignore_free_behind, status);
          IF NOT status.normal THEN
            EXIT /move_data/;
          IFEND;

{ Use a transfer size of 16K on the destination file so free behind will release
{ pages faster than it would with a 64K transfer size.  If the disk allocation
{ unit is greater than 16K, memory management uses the AU size for the free
{ behind size.

          mmp$preset_page_streaming ({preset_and_save_ts_fb} TRUE, to_pointer, destination_transfer_size,
                ignore_transfer_size, ignore_free_behind, status);
          IF NOT status.normal THEN
            EXIT /move_data/;
          IFEND;
        IFEND;

        i#move (from_pointer, to_pointer, bytes_to_move);
        current_byte_address := current_byte_address + bytes_to_move;

*if false
{Debug Code
IF (osv$debug[14] <> 0) and (osv$debug [15] >= current_byte_address) THEN
  test_condition_handler;
IFEND;
{Debug Code End
*ifend

{ Even though FREE_BEHIND is set for the source file, the last 2 or 3 transfer
{ units plus a partial transfer unit are still in the working set.  For the
{ destination file, the last transfer unit plus a partial transfer unit are
{ still in the working set.  An advise out on the entire file is done to remove
{ these pages from memory.

        advise_size:= #OFFSET (from_pointer) + bytes_to_move;
        advise_pointer := #ADDRESS (#RING (from_pointer), #SEGMENT (from_pointer), 0);
        mmp$advise_out (advise_pointer, advise_size, status);
        IF NOT status.normal THEN
          EXIT /move_data/;
        IFEND;

        advise_size:= #OFFSET (to_pointer) + bytes_to_move;
        advise_pointer := #ADDRESS (#RING (to_pointer), #SEGMENT (to_pointer), 0);
        mmp$advise_out (advise_pointer, advise_size, status);
        IF NOT status.normal THEN
          EXIT /move_data/;
        IFEND;

      WHILEND;

    END /move_data/;

    osp$disestablish_cond_handler;

  PROCEND allocate_space_and_move_data;
?? OLDTITLE ??
?? NEWTITLE := ' dm_attach_file', EJECT ??

  PROCEDURE dm_attach_file
    (    path: pft$complete_path;
         p_catalog_file: {input^} pft$p_catalog_file;
         usage_intentions: pft$usage_selections;
         share_selections: pft$share_selections;
         p_cycle: {i^/o^} pft$p_cycle;
     VAR system_file_id: gft$system_file_identifier;
     VAR file_damaged: boolean;
     VAR status: ost$status);

    CONST
      update_catalog = TRUE;

    VAR
      existing_sft_entry: dmt$existing_sft_entry,
      exit_on_unknown_file: boolean,
      fs_path_size: fst$path_size,
      p_fs_path: ^fst$path,
      p_path_string: ^ost$string,
      p_physical_fmd: pft$p_physical_fmd,
      recorded_vsn: rmt$recorded_vsn;

    pfp$build_fmd_pointer (p_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);

    {exit_on_unknown_file := cycle attached for write access
    exit_on_unknown_file := (p_cycle^.cycle_entry.attach_status.attach_count > 0) AND
          ((p_cycle^.cycle_entry.attach_status.usage_counts [pfc$shorten] > 0) OR
          (p_cycle^.cycle_entry.attach_status.usage_counts [pfc$append] > 0) OR
          (p_cycle^.cycle_entry.attach_status.usage_counts [pfc$modify] > 0));

    dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
          p_physical_fmd^.fmd, usage_intentions, share_selections, pfc$average_share_history,
          pfc$maximum_pf_length, {restricted_attach} FALSE, exit_on_unknown_file, {server_file} FALSE,
          pfp$shared_queue (p_cycle^.cycle_entry.shared_queue_info, share_selections), file_damaged,
          system_file_id, existing_sft_entry, status);
    IF status.normal THEN
      pfp$reconcile_fmd (^path, p_cycle^.cycle_entry.internal_cycle_name, existing_sft_entry, update_catalog,
            p_catalog_file, p_cycle, p_physical_fmd, status);
      IF status.normal AND ((existing_sft_entry = dmc$restricted_attach_entry) OR
            (exit_on_unknown_file AND (existing_sft_entry = dmc$entry_not_found))) THEN
        dmp$attach_file (p_cycle^.cycle_entry.internal_cycle_name, gfc$fk_job_permanent_file,
              p_physical_fmd^.fmd, usage_intentions, share_selections, pfc$average_share_history,
              pfc$maximum_pf_length, {restricted_attach} FALSE, {exit_on_unknown_file} FALSE,
              {server_file} FALSE,
              pfp$shared_queue (p_cycle^.cycle_entry.shared_queue_info, share_selections), file_damaged,
              system_file_id, existing_sft_entry, status);
      IFEND;
    IFEND;

    IF NOT status.normal THEN
      PUSH p_path_string;
      pfp$convert_cycle_path_to_strng (path, p_cycle^.cycle_entry.cycle_number, p_path_string^);
      IF status.condition = dme$volume_unavailable THEN
        recorded_vsn := status.text.value (2, 6);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_unavailable,
              p_path_string^.value (1, p_path_string^.size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
      ELSEIF status.condition = dme$some_volumes_not_online THEN
        recorded_vsn := status.text.value (2, 6);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$volume_not_online,
              p_path_string^.value (1, p_path_string^.size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, recorded_vsn, status);
      ELSE
        pfp$report_unexpected_status (status);
        pfp$process_unexpected_status (status);
      IFEND;
    IFEND;

  PROCEND dm_attach_file;
?? OLDTITLE ??
?? NEWTITLE := ' dm_detach_file', EJECT ??

  PROCEDURE dm_detach_file
    (    system_file_id: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      file_modified: boolean,
      file_info: dmt$file_information,
      fmd_modified: boolean;

    dmp$detach_file (system_file_id, {access_allowed} TRUE, {flush_pages} TRUE, dmc$df_ignore_file_info,
          file_modified, fmd_modified, file_info, status);
    IF status.normal THEN
      dmp$delete_file_descriptor (system_file_id, status);
      IF NOT (status.normal) AND (status.condition = dme$file_descriptor_not_deleted) THEN
        status.normal := TRUE;
      IFEND;
    IFEND;

  PROCEND dm_detach_file;
?? OLDTITLE ??
?? NEWTITLE := ' move_root_catalog', EJECT ??

  PROCEDURE move_root_catalog
    (    path: pft$complete_path;
         move_object_info_p: ^pft$move_object_info;
     VAR status: ost$status);

    CONST
      system_privilege = TRUE;

    VAR
      authority: pft$authority,
      catalog_active: boolean,
      catalog_locator: pft$catalog_locator,
      class_string: string (1),
      destination_file_info: dmt$file_information,
      file_info: dmt$file_information,
      fmd_header: pft$fmd_header,
      fs_path_size: fst$path_size,
      job_recovery_inhibited: boolean,
      local_status: ost$status,
      new_catalog_active: boolean,
      new_catalog_locator: pft$catalog_locator,
      p_fs_path: ^fst$path,
      p_internal_catalog_name: ^pft$internal_catalog_name,
      p_mass_storage_request_info: ^fmt$mass_storage_request_info,
      p_path_string: ^ost$string,
      p_root: ^pft$root,
      p_stored_fmd: ^dmt$stored_fmd,
      p_stored_fmd_size: ^dmt$stored_fmd_size,
      process_non_local_exit: boolean,
      resides_on_destination_volumes: boolean,
      root_size: pft$root_size,
      selected_volume: rmt$recorded_vsn,
      set_path: array [1 .. 1] of ost$name,
      stored_fmd_size: dmt$stored_fmd_size,
      temp_subfile_list_p: ^pft$subfile_list,
      verify_status: ost$status,
      volume_index: ost$positive_integers;

?? NEWTITLE := ' move_root_catalog_handler', EJECT ??

    PROCEDURE move_root_catalog_handler
      (    condition: pmt$condition;
           p_condition_info: ^pmt$condition_information;
           p_sfsa: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      VAR
        fs_path_size: fst$path_size,
        local_status: ost$status,
        p_fs_path: ^fst$path,
        status_id: ost$status_identifier,
        variant_path: pft$variant_path;

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;

      IF NOT process_non_local_exit THEN
        pfp$log_ascii ('***PF Condition Handler***', $pmt$ascii_logset [pmc$system_log, pmc$job_log],
              pmc$msg_origin_system, {critical_message} FALSE, local_status);
        pfp$log_path (variant_path, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
              {critical_message} FALSE, local_status);
      IFEND;

      CASE condition.selector OF
      = pmc$system_conditions, pmc$block_exit_processing, mmc$segment_access_condition =
        IF process_non_local_exit THEN
          RETURN;
        IFEND;

        IF new_catalog_active THEN
          pfp$return_catalog (new_catalog_locator, local_status);
          new_catalog_active := NOT local_status.normal;
          #SPOIL (new_catalog_active);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF catalog_active THEN
          catalog_locator.abort_catalog_operation := TRUE;
          pfp$return_catalog (catalog_locator, local_status);
          catalog_active := NOT local_status.normal;
          #SPOIL (catalog_active);
          pfp$process_unexpected_status (local_status);
        IFEND;

        IF job_recovery_inhibited THEN
          syp$pop_inhibit_job_recovery;
          job_recovery_inhibited := FALSE;
          #SPOIL (job_recovery_inhibited);
        IFEND;

        osp$set_status_from_condition (status_id, condition, p_sfsa, local_status, handler_status);
        osp$recoverable_system_error ('UNEXPECTED STATUS', ^local_status);

        status := local_status;
        initiate_non_local_exit;

      = pmc$user_defined_condition =
        IF condition.user_condition_name = 'OSC$JOB_RECOVERY' THEN
          {syp$invalidate_open_sfid (catalog_locator.system_file_id, local_status);
          initiate_non_local_exit;
        ELSE
          pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        IFEND;
      ELSE
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
      CASEND;

    PROCEND move_root_catalog_handler;
?? OLDTITLE ??
?? NEWTITLE := ' initiate_non_local_exit', EJECT ??

    PROCEDURE initiate_non_local_exit;

      process_non_local_exit := TRUE;
      #SPOIL (process_non_local_exit);
      EXIT move_root_catalog;

    PROCEND initiate_non_local_exit;
?? OLDTITLE ??
?? EJECT ??

    syp$push_inhibit_job_recovery;
    job_recovery_inhibited := TRUE;
    #SPOIL (job_recovery_inhibited);

  /move_object/
    BEGIN
      catalog_active := FALSE;
      #SPOIL (catalog_active);
      new_catalog_active := FALSE;
      #SPOIL (new_catalog_active);
      process_non_local_exit := FALSE;
      #SPOIL (process_non_local_exit);
      fmd_header.requested_class := rmc$unspecified_file_class;
      status.normal := TRUE;

      move_object_info_p^.move_status.move_successful := FALSE;
      move_object_info_p^.move_status.old_subfile_list_p := NIL;
      move_object_info_p^.move_status.new_subfile_list_p := NIL;
      move_object_info_p^.move_status.reason_for_move_failure := pfc$unexpected_abort;

      root_size := 255; {estimate}
      REPEAT
        PUSH p_root: [[REP root_size OF cell]];
        RESET p_root;
        stp$get_pf_root (move_object_info_p^.set_name, root_size, p_root^, status);
      UNTIL status.normal OR (status.condition <> ste$incorrect_root_size);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      RESET p_root;
      NEXT p_internal_catalog_name IN p_root;
      NEXT p_stored_fmd_size IN p_root;
      NEXT p_stored_fmd: [[REP p_stored_fmd_size^ OF cell]] IN p_root;

      pfp$attach_root_catalog (move_object_info_p^.set_name, pfc$write_access, catalog_locator, status);
      catalog_active := status.normal;
      #SPOIL (catalog_active);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      osp$establish_condition_handler (^move_root_catalog_handler, {block_exit} TRUE);

      dmp$get_file_info (catalog_locator.system_file_id, file_info, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_header_info (p_stored_fmd, fmd_header, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

      RESET move_object_info_p^.move_status.volume_list_storage_p;
      NEXT temp_subfile_list_p: [1 .. fmd_header.number_of_subfiles] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'catalog',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
        EXIT /move_object/;
      ELSE
        move_object_info_p^.move_status.old_subfile_list_p := temp_subfile_list_p;
      IFEND;

      dmp$get_stored_fmd_subfile_list (p_stored_fmd, file_info.total_allocated_length,
            move_object_info_p^.move_status.old_subfile_list_p, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      PUSH p_mass_storage_request_info;
      select_volume (path, {p_cycle_number} NIL, fmd_header,
            move_object_info_p^.move_status.old_subfile_list_p^, file_info, move_object_info_p,
            p_mass_storage_request_info^, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      IF NOT move_object_info_p^.perform_move THEN
        destination_file_info := file_info;
        simulate_move_object (path, {p_cycle_number} NIL, fmd_header,
              move_object_info_p^.move_status.old_subfile_list_p^, file_info, move_object_info_p, status);
        EXIT /move_object/;
      IFEND;

      selected_volume := p_mass_storage_request_info^.initial_volume;

      pfp$get_authority (path, system_privilege, authority, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      set_path [1] := move_object_info_p^.set_name;
      pfp$create_catalog (path, p_mass_storage_request_info, authority, {lock_catalog} FALSE,
            new_catalog_locator, status);
      new_catalog_active := status.normal;
      #SPOIL (new_catalog_active);
      IF status.normal THEN
        verify_volume_residence (new_catalog_locator.system_file_id, move_object_info_p^.dest_volume_list_p,
              resides_on_destination_volumes, verify_status);
        IF NOT verify_status.normal THEN
          status := verify_status;
          EXIT /move_object/;
        IFEND;
        IF (NOT resides_on_destination_volumes) AND
              ((UPPERBOUND(move_object_info_p^.dest_volume_list_p^) -
              LOWERBOUND(move_object_info_p^.dest_volume_list_p^)) > 0) THEN
          pfp$destroy_catalog (new_catalog_locator, local_status);
          pfp$process_unexpected_status (local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

          pfp$return_catalog (new_catalog_locator, local_status);
          new_catalog_active := NOT local_status.normal;
          #SPOIL (new_catalog_active);
          pfp$process_unexpected_status (local_status);
          IF NOT local_status.normal THEN
            status := local_status;
            EXIT /move_object/;
          IFEND;

        /try_other_volumes/
          FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.dest_volume_list_p^) DO
            IF (NOT (fmd_header.requested_class IN
                  move_object_info_p^.dest_volume_list_p^ [volume_index]^.ms_class)) OR
                  (move_object_info_p^.dest_volume_list_p^ [volume_index]^.recorded_vsn =
                  selected_volume) THEN
              CYCLE /try_other_volumes/;
            IFEND;
            p_mass_storage_request_info^.initial_volume :=
                  move_object_info_p^.dest_volume_list_p^ [volume_index]^.recorded_vsn;
            pfp$create_catalog (path, p_mass_storage_request_info, authority, {lock_catalog} FALSE,
                  new_catalog_locator, status);
            new_catalog_active := status.normal;
            #SPOIL (new_catalog_active);
            IF status.normal THEN
              verify_volume_residence (new_catalog_locator.system_file_id,
                    move_object_info_p^.dest_volume_list_p, resides_on_destination_volumes, verify_status);
              IF NOT verify_status.normal THEN
                status := verify_status;
                EXIT /move_object/;
              IFEND;
              IF NOT resides_on_destination_volumes THEN
                pfp$destroy_catalog (new_catalog_locator, local_status);
                pfp$process_unexpected_status (local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;

                pfp$return_catalog (new_catalog_locator, local_status);
                new_catalog_active := NOT local_status.normal;
                #SPOIL (new_catalog_active);
                pfp$process_unexpected_status (local_status);
                IF NOT local_status.normal THEN
                  status := local_status;
                  EXIT /move_object/;
                IFEND;
                CYCLE /try_other_volumes/;
              IFEND;
            ELSE
              EXIT /try_other_volumes/;
            IFEND;
          FOREND /try_other_volumes/;
        IFEND;
      IFEND;

      IF ((NOT status.normal) AND (status.condition = dme$unable_to_alloc_all_space)) OR
            (NOT resides_on_destination_volumes) THEN
        class_string (1) := fmd_header.requested_class;
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$no_available_space;
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_no_available_space, class_string,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name,
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, 'catalog', status);
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^ , fs_path_size);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_fs_path^ (1, fs_path_size), status);
      IFEND;

      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      allocate_space_and_move_data (path, catalog_locator.p_catalog_file, new_catalog_locator.p_catalog_file,
            file_info.eoi_byte_address, {p_cycle_number} NIL, move_object_info_p, fmd_header.requested_class,
            status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      mmp$set_segment_length (new_catalog_locator.p_catalog_file, pfc$catalog_ring,
            file_info.eoi_byte_address, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_size (new_catalog_locator.system_file_id, stored_fmd_size, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      PUSH p_root: [[REP 1 OF pft$internal_catalog_name, REP 1 OF dmt$stored_fmd_size,
            REP stored_fmd_size OF cell]];

      RESET p_root;
      NEXT p_internal_catalog_name IN p_root;
      p_internal_catalog_name^ := new_catalog_locator.internal_catalog_name;

      NEXT p_stored_fmd_size IN p_root;
      p_stored_fmd_size^ := stored_fmd_size;

      NEXT p_stored_fmd: [[REP stored_fmd_size OF cell]] IN p_root;
      dmp$get_stored_fmd (new_catalog_locator.system_file_id, p_stored_fmd^, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_file_info (new_catalog_locator.system_file_id, destination_file_info, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$put_stored_fmd_header_info (fmd_header, p_stored_fmd, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      dmp$get_stored_fmd_header_info (p_stored_fmd, fmd_header, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      NEXT temp_subfile_list_p: [1 .. fmd_header.number_of_subfiles] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'catalog',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
        EXIT /move_object/;
      ELSE
        move_object_info_p^.move_status.new_subfile_list_p := temp_subfile_list_p;
      IFEND;

      dmp$get_stored_fmd_subfile_list (p_stored_fmd, destination_file_info.total_allocated_length,
            move_object_info_p^.move_status.new_subfile_list_p, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      stp$store_pf_root (move_object_info_p^.set_name, p_root^, status);
      IF NOT status.normal THEN
        EXIT /move_object/;
      IFEND;

      catalog_locator.queuing_info.set_catalog_alarm := TRUE;
      move_object_info_p^.move_status.move_successful := TRUE;
      move_object_info_p^.move_status.allocated_size := destination_file_info.total_allocated_length;
      move_object_info_p^.move_status.data_residence := pfc$unreleasable_data;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

    END /move_object/;

    IF new_catalog_active THEN
      IF NOT move_object_info_p^.move_status.move_successful THEN
        pfp$destroy_catalog (new_catalog_locator, local_status);
        pfp$process_unexpected_status (local_status);
      IFEND;

      pfp$return_catalog (new_catalog_locator, local_status);
      new_catalog_active := NOT local_status.normal;
      #SPOIL (new_catalog_active);
      pfp$process_unexpected_status (local_status);
    IFEND;

    update_move_object_info (move_object_info_p, pfc$catalog_object, fmd_header,
          move_object_info_p^.move_status.old_subfile_list_p,
          move_object_info_p^.move_status.new_subfile_list_p, file_info, destination_file_info, local_status);
    pfp$process_unexpected_status (local_status);

    osp$disestablish_cond_handler;

    IF catalog_active THEN
      IF move_object_info_p^.perform_move AND move_object_info_p^.move_status.move_successful THEN
        pfp$destroy_catalog (catalog_locator, local_status);
        catalog_active := NOT local_status.normal;
        #SPOIL (catalog_active);
        pfp$process_unexpected_status (local_status);
      ELSE
        pfp$return_catalog (catalog_locator, local_status);
        catalog_active := NOT local_status.normal;
        #SPOIL (catalog_active);
        pfp$process_unexpected_status (local_status);
      IFEND;
    IFEND;

    syp$pop_inhibit_job_recovery;
    job_recovery_inhibited := FALSE;
    #SPOIL (job_recovery_inhibited);

  PROCEND move_root_catalog;
?? OLDTITLE ??
?? NEWTITLE := ' release_cycle_data', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to release mass storage data for a
{   specified file cycle.
{
{ NOTES:
{   If the cycle data has been modified since the most recent archive entry was
{   created, mass storage data is not released.
{

  PROCEDURE release_cycle_data
    (    path: pft$complete_path;
         perform_changes: boolean;
         p_physical_cycle: {i^/o^} ^pft$physical_cycle;
         p_catalog_file: {i^/o^} ^pft$catalog_file;
     VAR status: ost$status);

    VAR
      archive_date_time: ost$date_time,
      archive_index: pft$archive_index,
      comparison_result: pmt$comparison_result,
      data_modification_date_time: ost$date_time,
      p_archive_entry: ^pft$archive_entry,
      p_archive_list: ^pft$archive_list,
      p_physical_fmd: ^pft$physical_fmd,
      prevalidate_free_result: ost$prevalidate_free_result,
      release_date_time: ost$date_time,
      valid_archive_entry_found: boolean,
      variant_path: pft$variant_path;

    status.normal := TRUE;

    pfp$build_archive_list_pointer (p_physical_cycle^.cycle_entry.archive_list_locator, p_catalog_file,
          p_archive_list);
    IF p_archive_list = NIL THEN
      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;
      pfp$set_status_abnormal (variant_path, pfe$empty_archive_list, status);
      RETURN;
    IFEND;
    {
    { Locate most recently created archive entry.
    {
    p_archive_entry := ^p_archive_list^ [1].archive_entry;
    archive_date_time := p_archive_entry^.archive_date_time;

  /search_archive_list/
    FOR archive_index := 2 TO UPPERBOUND (p_archive_list^) DO
      pmp$date_time_compare (p_archive_list^ [archive_index].archive_entry.archive_date_time,
            archive_date_time, comparison_result, status);
      IF NOT status.normal THEN
        CYCLE /search_archive_list/;
      IFEND;
      IF comparison_result = pmc$left_is_greater THEN
        archive_date_time := p_archive_list^ [archive_index].archive_entry.archive_date_time;
        p_archive_entry := ^p_archive_list^ [archive_index].archive_entry;
      IFEND;
    FOREND /search_archive_list/;
    {
    { The archive entry will be considered a valid archive entry if it was created after
    { the cycle was last modified.
    {
    data_modification_date_time := p_physical_cycle^.cycle_entry.data_modification_date_time;
    pmp$date_time_compare (archive_date_time, data_modification_date_time, comparison_result, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    valid_archive_entry_found := (comparison_result = pmc$left_is_greater);
    {
    { If a valid archive entry does not exist, the release request will be rejected.
    {
    IF NOT valid_archive_entry_found THEN
      p_physical_cycle^.cycle_entry.data_residence := pfc$unreleasable_data;
      pfp$compute_checksum (^p_physical_cycle^.cycle_entry, #SIZE (pft$cycle_entry),
            p_physical_cycle^.checksum);

      variant_path.complete_path := TRUE;
      variant_path.p_complete_path := ^path;
      pfp$set_status_abnormal (variant_path, pfe$data_not_releasable, status);
      osp$append_status_integer (osc$status_parameter_delimiter, p_physical_cycle^.cycle_entry.cycle_number,
            {radix} 10, {include_radix_specifier} FALSE, status);
      RETURN;
    IFEND;

    IF NOT perform_changes THEN
      RETURN;
    IFEND;

    pfp$build_fmd_pointer (p_physical_cycle^.cycle_entry.fmd_locator, p_catalog_file, p_physical_fmd);
    IF p_physical_fmd <> NIL THEN
      dmp$destroy_permanent_file (p_physical_cycle^.cycle_entry.internal_cycle_name, p_physical_fmd^.fmd,
            status);
      pfp$process_unexpected_status (status);
      status.normal := TRUE;
      {
      { Release the file_media_descriptor even if there is a failure in
      { releasing the mass storage for the file cycle.  This makes the
      { system more fault tolerant and allows the user to continue.
      { Recovery of the set will make the files known to both device
      { management and permanent file management.
      {
      osp$prevalidate_free ((#OFFSET(p_physical_fmd) -
            #OFFSET(^p_catalog_file^.catalog_heap) - 16), ^p_catalog_file^.catalog_heap,
            prevalidate_free_result);
      IF prevalidate_free_result = osc$heap_free_valid THEN
        FREE p_physical_fmd IN p_catalog_file^.catalog_heap;
      ELSE
        pfp$report_invalid_free (^path, ^p_physical_cycle^.cycle_entry.cycle_number, 'FILE_MEDIA_DESCRIPTOR',
              'file', prevalidate_free_result, #OFFSET(p_physical_fmd));
        p_physical_fmd := NIL;
      IFEND;
      pfp$build_fmd_locator ({p_physical_fmd} NIL, {p_catalog_file} NIL,
            p_physical_cycle^.cycle_entry.fmd_locator);
    IFEND;
    p_physical_cycle^.cycle_entry.data_residence := pfc$offline_data;
    p_physical_cycle^.cycle_entry.data_modification_date_time := p_archive_entry^.modification_date_time;
    p_physical_cycle^.cycle_entry.cycle_statistics.modification_date_time :=
          p_archive_entry^.modification_date_time;

    pmp$get_compact_date_time (release_date_time, status);

  /set_release_date_time/
    FOR archive_index := 1 TO UPPERBOUND (p_archive_list^) DO
      pmp$date_time_compare (p_archive_list^ [archive_index].archive_entry.modification_date_time,
            p_physical_cycle^.cycle_entry.data_modification_date_time, comparison_result, status);
      IF NOT status.normal THEN
        EXIT /set_release_date_time/;
      IFEND;

      IF comparison_result = pmc$equal THEN
        p_archive_list^ [archive_index].archive_entry.last_release_date_time := release_date_time;
        pfp$compute_checksum (^p_archive_list^ [archive_index].archive_entry, #SIZE (pft$archive_entry),
              p_archive_list^ [archive_index].checksum);
      IFEND;
    FOREND /set_release_date_time/;

    pfp$compute_checksum (^p_physical_cycle^.cycle_entry, #SIZE (pft$cycle_entry),
          p_physical_cycle^.checksum);

  PROCEND release_cycle_data;
?? OLDTITLE ??
?? NEWTITLE := ' select_volume', EJECT ??

  PROCEDURE select_volume
    (    path: pft$complete_path;
         p_cycle_number: ^fst$cycle_number,
         fmd_header: pft$fmd_header;
         subfile_list: pft$subfile_list;
         file_info: dmt$file_information;
         move_object_info_p: ^pft$move_object_info;
     VAR mass_storage_request_info: fmt$mass_storage_request_info;
     VAR status: ost$status);

    VAR
      best_volume: ost$non_negative_integers,
      class_string: string(1),
      dest_volume_list_p: ^pft$mo_volume_list_p,
      fs_path_size: fst$path_size,
      most_space_available: ost$non_negative_integers,
      p_fs_path: ^fst$path,
      p_path_string: ^ost$string,
      remaining_space_to_allocate: ost$non_negative_integers,
      resides_on_destination_volumes: boolean,
      resides_on_source_volumes: boolean,
      source_volume_list_p: ^pft$mo_volume_list_p,
      subfile_index: ost$positive_integers,
      volume_index: ost$positive_integers;

    status.normal := TRUE;
    class_string := fmd_header.requested_class;

    IF NOT (fmd_header.requested_class IN move_object_info_p^.mass_storage_class) THEN
      IF p_cycle_number = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_ms_class_conflict, 'catalog',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, class_string, status);
        RETURN;
      ELSE
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_ms_class_conflict, 'file', status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
        osp$append_status_parameter (osc$status_parameter_delimiter, class_string, status);
        RETURN;
      IFEND;
    IFEND;

    dest_volume_list_p := move_object_info_p^.dest_volume_list_p;
    IF dest_volume_list_p = NIL THEN
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_no_destination_volumes,
            move_object_info_p^.set_name, status);
      RETURN;
    IFEND;

  /check_subfiles_destination/
    FOR subfile_index := 1 TO UPPERBOUND (subfile_list) DO
      resides_on_destination_volumes := FALSE;
    /check_destination_volumes/
      FOR volume_index := 1 TO UPPERBOUND (dest_volume_list_p^) DO
        IF (subfile_list [subfile_index].recorded_vsn = dest_volume_list_p^ [volume_index]^.recorded_vsn) THEN
          resides_on_destination_volumes := TRUE;
          EXIT /check_destination_volumes/
        IFEND
      FOREND /check_destination_volumes/;
      IF NOT resides_on_destination_volumes THEN
        EXIT /check_subfiles_destination/
      IFEND;
    FOREND /check_subfiles_destination/;

    IF resides_on_destination_volumes THEN
      IF p_cycle_number = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$resides_on_dest_volumes, 'Catalog',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
      ELSE
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$resides_on_dest_volumes, 'File', status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
      IFEND;
      RETURN;
    IFEND;

    source_volume_list_p := move_object_info_p^.source_volume_list_p;

    resides_on_source_volumes := FALSE;
  /check_subfiles_source/
    FOR subfile_index := 1 TO UPPERBOUND (subfile_list) DO
      FOR volume_index := 1 TO UPPERBOUND (source_volume_list_p^) DO
        IF subfile_list [subfile_index].recorded_vsn = source_volume_list_p^ [volume_index]^.recorded_vsn THEN
          resides_on_source_volumes := TRUE;
          EXIT /check_subfiles_source/;
        IFEND;
      FOREND;
    FOREND /check_subfiles_source/;

    IF NOT resides_on_source_volumes THEN
      IF p_cycle_number = NIL THEN
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_not_on_source_volumes, 'catalog',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_fs_path^ (1, fs_path_size), status);
      ELSE
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
        osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_not_on_source_volumes, 'file',
              status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
      IFEND;
      RETURN;
    IFEND;

    best_volume := 0;
    most_space_available := 0;
    remaining_space_to_allocate := file_info.total_allocated_length;

  /check_requested_volume/
    FOR volume_index := 1 TO UPPERBOUND (dest_volume_list_p^) DO
      IF NOT (fmd_header.requested_class IN dest_volume_list_p^ [volume_index]^.ms_class) THEN
        CYCLE /check_requested_volume/;
      IFEND;

      IF (fmd_header.requested_volume.recorded_vsn = dest_volume_list_p^ [volume_index]^.recorded_vsn) AND
            (dest_volume_list_p^ [volume_index]^.mass_storage_available >= remaining_space_to_allocate) THEN
        remaining_space_to_allocate := 0;
        most_space_available := dest_volume_list_p^ [volume_index]^.mass_storage_available;
        best_volume := volume_index;
        EXIT /check_requested_volume/;
      IFEND;
    FOREND /check_requested_volume/;

    IF best_volume = 0 THEN
    /select_best_volume/
      FOR volume_index := 1 TO UPPERBOUND (dest_volume_list_p^) DO
        IF NOT (fmd_header.requested_class IN dest_volume_list_p^ [volume_index]^.ms_class) THEN
          CYCLE /select_best_volume/;
        IFEND;

        IF remaining_space_to_allocate > dest_volume_list_p^ [volume_index]^.mass_storage_available THEN
          remaining_space_to_allocate := remaining_space_to_allocate -
                dest_volume_list_p^ [volume_index]^.mass_storage_available;
        ELSE
          remaining_space_to_allocate := 0;
        IFEND;

        IF dest_volume_list_p^ [volume_index]^.mass_storage_available >= most_space_available THEN
          most_space_available := dest_volume_list_p^ [volume_index]^.mass_storage_available;
          best_volume := volume_index;
        IFEND;
      FOREND /select_best_volume/;
    IFEND;

    IF (remaining_space_to_allocate > 0) OR ((NOT move_object_info_p^.volume_overflow_allowed) AND
          (file_info.total_allocated_length > most_space_available)) THEN
      move_object_info_p^.move_status.move_successful := FALSE;
      move_object_info_p^.move_status.reason_for_move_failure := pfc$insufficient_space;
      osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_insufficient_space, class_string,
            status);
      osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name, status);
      IF p_cycle_number = NIL THEN
        osp$append_status_parameter (osc$status_parameter_delimiter, 'catalog', status);
        PUSH p_fs_path;
        pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
        osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
      ELSE
        osp$append_status_parameter (osc$status_parameter_delimiter, 'file', status);
        PUSH p_path_string;
        pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              p_path_string^.value (1, p_path_string^.size), status);
      IFEND;
      RETURN;
    IFEND;

    mass_storage_request_info.allocation_size := fmd_header.requested_allocation_size;
    mass_storage_request_info.estimated_file_size := rmc$unspecified_file_size;
    mass_storage_request_info.mass_storage_class := fmd_header.requested_class;
    mass_storage_request_info.initial_volume := dest_volume_list_p^ [best_volume]^.recorded_vsn;
    mass_storage_request_info.transfer_size := fmd_header.requested_transfer_size;
    mass_storage_request_info.volume_overflow_allowed := fmd_header.overflow_allowed;
    IF NOT move_object_info_p^.volume_overflow_allowed THEN
      mass_storage_request_info.volume_overflow_allowed := FALSE;
    IFEND;
    mass_storage_request_info.user_privilege := rmc$system_user;
    mass_storage_request_info.maintenance_job := FALSE;

  PROCEND select_volume;
?? OLDTITLE ??
?? NEWTITLE := ' simulate_move_object', EJECT ??

  PROCEDURE simulate_move_object
    (    path: pft$complete_path;
         p_cycle_number: ^fst$cycle_number,
         fmd_header: pft$fmd_header;
         old_subfile_list: pft$subfile_list;
         file_info: dmt$file_information;
         move_object_info_p: ^pft$move_object_info;
     VAR status: ost$status);

    VAR
      best_volume: ost$non_negative_integers,
      class_string: string(1),
      current_byte_address: amt$file_byte_address,
      dest_volume_list_p: ^pft$mo_volume_list_p,
      fs_path_size: fst$path_size,
      most_space_available: ost$non_negative_integers,
      new_subfile_count: ost$non_negative_integers,
      new_subfile_list_p: ^pft$subfile_list,
      p_fs_path: ^fst$path,
      p_path_string: ^ost$string,
      remaining_space_to_allocate: ost$non_negative_integers,
      subfile_index: ost$positive_integers,
      temp_subfile_list_p: ^pft$subfile_list,
      volume_index: ost$positive_integers;

    status.normal := TRUE;
    move_object_info_p^.move_status.move_successful := FALSE;
    class_string := fmd_header.requested_class;
    current_byte_address := 0;
    new_subfile_count := 0;
    remaining_space_to_allocate := file_info.total_allocated_length;
    dest_volume_list_p := move_object_info_p^.dest_volume_list_p;
    PUSH new_subfile_list_p: [1 .. UPPERBOUND (dest_volume_list_p^)];

  /simulate_allocation/
    BEGIN

    /allocate_space/
      WHILE remaining_space_to_allocate > 0 DO

        best_volume := 0;
        most_space_available := 0;
      /select_best_volume/
        FOR volume_index := 1 TO UPPERBOUND (dest_volume_list_p^) DO
          IF NOT (fmd_header.requested_class IN dest_volume_list_p^ [volume_index]^.ms_class) THEN
            CYCLE /select_best_volume/;
          IFEND;
          IF dest_volume_list_p^ [volume_index]^.mass_storage_available > most_space_available THEN
            most_space_available := dest_volume_list_p^ [volume_index]^.mass_storage_available;
            best_volume := volume_index;
          IFEND;
        FOREND /select_best_volume/;

        IF (most_space_available = 0) OR
              ((p_cycle_number = NIL) AND (remaining_space_to_allocate > most_space_available)) OR
              ((NOT move_object_info_p^.volume_overflow_allowed) AND (new_subfile_count = 0) AND
              (remaining_space_to_allocate > most_space_available)) THEN
          move_object_info_p^.move_status.reason_for_move_failure := pfc$insufficient_space;
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_insufficient_space, class_string,
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, move_object_info_p^.set_name, status);
          IF p_cycle_number = NIL THEN
            osp$append_status_parameter (osc$status_parameter_delimiter, 'catalog', status);
            PUSH p_fs_path;
            pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
            osp$append_status_parameter (osc$status_parameter_delimiter,
                  p_fs_path^ (1, fs_path_size), status);
          ELSE
            osp$append_status_parameter (osc$status_parameter_delimiter, 'file', status);
            PUSH p_path_string;
            pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
            osp$append_status_parameter (osc$status_parameter_delimiter,
                  p_path_string^.value (1, p_path_string^.size), status);
          IFEND;
          EXIT /simulate_allocation/;
        IFEND;

        IF best_volume > 0 THEN
          new_subfile_count := new_subfile_count + 1;
          new_subfile_list_p^ [new_subfile_count].recorded_vsn :=
                dest_volume_list_p^ [best_volume]^.recorded_vsn;
          new_subfile_list_p^ [new_subfile_count].byte_address := current_byte_address;

          IF remaining_space_to_allocate > most_space_available THEN
            new_subfile_list_p^ [new_subfile_count].allocated_length := most_space_available;
            current_byte_address := current_byte_address + most_space_available;
            remaining_space_to_allocate := remaining_space_to_allocate - most_space_available;
            dest_volume_list_p^ [best_volume]^.mass_storage_available :=
                  dest_volume_list_p^ [best_volume]^.mass_storage_available - most_space_available;
          ELSE
            new_subfile_list_p^ [new_subfile_count].allocated_length :=
                  file_info.total_allocated_length - current_byte_address;
            dest_volume_list_p^ [best_volume]^.mass_storage_available :=
                  dest_volume_list_p^ [best_volume]^.mass_storage_available -
                  new_subfile_list_p^ [new_subfile_count].allocated_length;
            remaining_space_to_allocate := 0;
          IFEND;
        IFEND;

      WHILEND /allocate_space/;

    /return_old_subfiles/
      FOR subfile_index := 1 TO UPPERBOUND(old_subfile_list) DO
        FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.set_volume_list_p^) DO
          IF move_object_info_p^.set_volume_list_p^ [volume_index].recorded_vsn =
                old_subfile_list [subfile_index].recorded_vsn THEN
            move_object_info_p^.set_volume_list_p^ [volume_index].mass_storage_available :=
                  move_object_info_p^.set_volume_list_p^ [volume_index].mass_storage_available +
                  old_subfile_list [subfile_index].allocated_length;
            CYCLE /return_old_subfiles/;
          IFEND;
        FOREND;
      FOREND /return_old_subfiles/;

      NEXT temp_subfile_list_p: [1 .. new_subfile_count] IN
            move_object_info_p^.move_status.volume_list_storage_p;
      IF temp_subfile_list_p = NIL THEN
        IF p_cycle_number = NIL THEN
          PUSH p_fs_path;
          pfp$convert_pf_path_to_fs_path (path, p_fs_path^, fs_path_size);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'catalog',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, p_fs_path^ (1, fs_path_size), status);
        ELSE
          PUSH p_path_string;
          pfp$convert_cycle_path_to_strng (path, p_cycle_number^, p_path_string^);
          osp$set_status_abnormal (pfc$permanent_file_manager_id, pfe$movc_subfile_list_seq_size, 'file',
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter,
                p_path_string^.value (1, p_path_string^.size), status);
        IFEND;
        EXIT /simulate_allocation/;
      ELSE
        move_object_info_p^.move_status.new_subfile_list_p := temp_subfile_list_p;
      IFEND;

      FOR subfile_index := 1 TO new_subfile_count DO
        move_object_info_p^.move_status.new_subfile_list_p^ [subfile_index] :=
              new_subfile_list_p^ [subfile_index];
      FOREND;

      move_object_info_p^.move_status.move_successful := TRUE;
      move_object_info_p^.move_status.allocated_size := file_info.total_allocated_length;
      move_object_info_p^.move_status.data_residence := pfc$unreleasable_data;
      move_object_info_p^.move_status.ms_class := fmd_header.requested_class;

    END /simulate_allocation/;

    IF NOT status.normal AND (new_subfile_count > 0) THEN
    /return_allocated_space/
      FOR subfile_index := 1 TO new_subfile_count DO
        FOR volume_index := 1 TO UPPERBOUND (dest_volume_list_p^) DO
          IF dest_volume_list_p^ [volume_index]^.recorded_vsn =
                new_subfile_list_p^ [subfile_index].recorded_vsn THEN
            dest_volume_list_p^ [volume_index]^.mass_storage_available :=
                  dest_volume_list_p^ [volume_index]^.mass_storage_available +
                  new_subfile_list_p^ [subfile_index].allocated_length;
            CYCLE /return_allocated_space/;
          IFEND;
        FOREND;
      FOREND /return_allocated_space/;
    IFEND;

  PROCEND simulate_move_object;
?? OLDTITLE ??
?? NEWTITLE := ' update_available_space_info', EJECT ??

  PROCEDURE update_available_space_info
    (    move_object_info_p: ^pft$move_object_info;
     VAR status: ost$status);

    VAR
      i: integer,
      mass_storage_available: integer;

    IF move_object_info_p = NIL THEN
      RETURN;
    IFEND;

    IF move_object_info_p^.set_volume_list_p = NIL THEN
      RETURN;
    IFEND;

    IF move_object_info_p^.perform_move THEN
      FOR i := 1 TO UPPERBOUND (move_object_info_p^.set_volume_list_p^) DO
        IF move_object_info_p^.set_volume_list_p^[i].available THEN
          dmp$calculate_remaining_space (move_object_info_p^.set_volume_list_p^ [i].logical_unit_number,
                mass_storage_available, status);
          IF status.normal THEN
            move_object_info_p^.set_volume_list_p^ [i].mass_storage_available := mass_storage_available;
          ELSE
            RETURN;
          IFEND;
        IFEND;
      FOREND;
    IFEND;

    move_object_info_p^.update_available_space_total := 0;

  PROCEND update_available_space_info;
?? OLDTITLE ??
?? NEWTITLE := ' update_move_object_info', EJECT ??

  PROCEDURE update_move_object_info
    (    move_object_info_p: ^pft$move_object_info;
         object_type: pft$object_types;
         fmd_header: pft$fmd_header;
         p_old_subfile_list: ^pft$subfile_list;
         p_new_subfile_list: ^pft$subfile_list;
         file_info: dmt$file_information;
         destination_file_info: dmt$file_information;
     VAR status: ost$status);

    CONST
      allocation_unit = 16384,
      fudge_factor = 4 * allocation_unit;

    VAR
      subfile_index: ost$positive_integers,
      volume_index: ost$positive_integers;

    status.normal := TRUE;

    IF move_object_info_p = NIL THEN
      RETURN;
    IFEND;

  /update_info/
    BEGIN
      IF move_object_info_p^.move_status.move_successful AND
            (move_object_info_p^.move_status.data_residence = pfc$offline_data) THEN
        move_object_info_p^.overall_statistics.cycles_released :=
              move_object_info_p^.overall_statistics.cycles_released + 1;
        move_object_info_p^.overall_statistics.bytes_released :=
              move_object_info_p^.overall_statistics.bytes_released + file_info.total_allocated_length;

        FOR subfile_index := 1 TO UPPERBOUND (p_old_subfile_list^) DO

        /update_released_info/
          FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.set_volume_list_p^) DO
            IF move_object_info_p^.set_volume_list_p^ [volume_index].recorded_vsn =
                  p_old_subfile_list^ [subfile_index].recorded_vsn THEN
              move_object_info_p^.set_volume_list_p^ [volume_index].bytes_released :=
                    move_object_info_p^.set_volume_list_p^ [volume_index].bytes_released +
                    p_old_subfile_list^ [subfile_index].allocated_length;

              IF subfile_index = 1 THEN
                move_object_info_p^.set_volume_list_p^ [volume_index].cycles_released :=
                      move_object_info_p^.set_volume_list_p^ [volume_index].cycles_released + 1;
              IFEND;
              EXIT /update_released_info/;
            IFEND;
          FOREND /update_released_info/;
        FOREND;
        IF fmd_header.requested_class <> rmc$unspecified_file_class THEN
          move_object_info_p^.class_statistics [fmd_header.requested_class].cycles_released :=
                move_object_info_p^.class_statistics [fmd_header.requested_class].cycles_released + 1;
          move_object_info_p^.class_statistics [fmd_header.requested_class].bytes_released :=
                move_object_info_p^.class_statistics [fmd_header.requested_class].bytes_released +
                file_info.total_allocated_length;
        IFEND;

        EXIT /update_info/;
      IFEND;

      IF move_object_info_p^.move_status.move_successful THEN
        move_object_info_p^.overall_statistics.objects_moved :=
              move_object_info_p^.overall_statistics.objects_moved + 1;

        move_object_info_p^.overall_statistics.bytes_moved :=
              move_object_info_p^.overall_statistics.bytes_moved +
              destination_file_info.total_allocated_length;

        move_object_info_p^.update_available_space_total :=
              move_object_info_p^.update_available_space_total + destination_file_info.total_allocated_length;

        FOR subfile_index := 1 TO UPPERBOUND (p_old_subfile_list^) DO

        /update_old_subfile_info/
          FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.set_volume_list_p^) DO
            IF move_object_info_p^.set_volume_list_p^ [volume_index].recorded_vsn =
                  p_old_subfile_list^ [subfile_index].recorded_vsn THEN
              move_object_info_p^.set_volume_list_p^ [volume_index].bytes_moved_from :=
                    move_object_info_p^.set_volume_list_p^ [volume_index].bytes_moved_from +
                    p_old_subfile_list^ [subfile_index].allocated_length;

              IF move_object_info_p^.move_bytes_threshold > 0 THEN
                IF move_object_info_p^.set_volume_list_p^ [volume_index].bytes_moved_from >=
                      (move_object_info_p^.move_bytes_threshold - fudge_factor) THEN
                  move_object_info_p^.set_volume_list_p^ [volume_index].move_bytes_threshold_exceeded := TRUE;
                IFEND;
              IFEND;

              IF subfile_index = 1 THEN
                IF object_type = pfc$catalog_object THEN
                  move_object_info_p^.set_volume_list_p^ [volume_index].catalogs_moved_from :=
                        move_object_info_p^.set_volume_list_p^ [volume_index].catalogs_moved_from + 1;
                ELSE
                  move_object_info_p^.set_volume_list_p^ [volume_index].cycles_moved_from :=
                        move_object_info_p^.set_volume_list_p^ [volume_index].cycles_moved_from + 1;
                IFEND;
              IFEND;
              EXIT /update_old_subfile_info/;
            IFEND;
          FOREND /update_old_subfile_info/;
        FOREND;

        FOR subfile_index := 1 TO UPPERBOUND (p_new_subfile_list^) DO

        /update_new_subfile_info/
          FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.set_volume_list_p^) DO
            IF move_object_info_p^.set_volume_list_p^ [volume_index].recorded_vsn =
                  p_new_subfile_list^ [subfile_index].recorded_vsn THEN
              move_object_info_p^.set_volume_list_p^ [volume_index].bytes_moved_to :=
                    move_object_info_p^.set_volume_list_p^ [volume_index].bytes_moved_to +
                    p_new_subfile_list^ [subfile_index].allocated_length;

              IF subfile_index = 1 THEN
                IF object_type = pfc$catalog_object THEN
                  move_object_info_p^.set_volume_list_p^ [volume_index].catalogs_moved_to :=
                        move_object_info_p^.set_volume_list_p^ [volume_index].catalogs_moved_to + 1;
                ELSE
                  move_object_info_p^.set_volume_list_p^ [volume_index].cycles_moved_to :=
                        move_object_info_p^.set_volume_list_p^ [volume_index].cycles_moved_to + 1;
                IFEND;
              IFEND;
              EXIT /update_new_subfile_info/;
            IFEND;
          FOREND /update_new_subfile_info/;
        FOREND;

        move_object_info_p^.class_statistics [fmd_header.requested_class].objects_moved :=
              move_object_info_p^.class_statistics [fmd_header.requested_class].objects_moved + 1;
        move_object_info_p^.class_statistics [fmd_header.requested_class].bytes_moved :=
              move_object_info_p^.class_statistics [fmd_header.requested_class].bytes_moved +
              file_info.total_allocated_length;

      ELSE

        CASE move_object_info_p^.move_status.reason_for_move_failure OF
        = pfc$cycle_busy =
          move_object_info_p^.overall_statistics.objects_not_moved :=
                move_object_info_p^.overall_statistics.objects_not_moved + 1;
          move_object_info_p^.overall_statistics.cycle_busy :=
                move_object_info_p^.overall_statistics.cycle_busy + 1;
        = pfc$insufficient_space =
          move_object_info_p^.overall_statistics.objects_not_moved :=
                move_object_info_p^.overall_statistics.objects_not_moved + 1;
          move_object_info_p^.overall_statistics.insufficient_space :=
                move_object_info_p^.overall_statistics.insufficient_space + 1;
        = pfc$no_available_space =
          move_object_info_p^.overall_statistics.objects_not_moved :=
                move_object_info_p^.overall_statistics.objects_not_moved + 1;
          move_object_info_p^.overall_statistics.no_available_space :=
                move_object_info_p^.overall_statistics.no_available_space + 1;
        = pfc$io_error =
          move_object_info_p^.overall_statistics.objects_not_moved :=
                move_object_info_p^.overall_statistics.objects_not_moved + 1;
          move_object_info_p^.overall_statistics.unrecovered_read_error :=
                move_object_info_p^.overall_statistics.unrecovered_read_error + 1;
        = pfc$data_released =
          move_object_info_p^.overall_statistics.cycles_released :=
                move_object_info_p^.overall_statistics.cycles_released + 1;
        = pfc$unexpected_abort =
          move_object_info_p^.overall_statistics.objects_not_moved :=
                move_object_info_p^.overall_statistics.objects_not_moved + 1;
          move_object_info_p^.overall_statistics.abnormal_status :=
                move_object_info_p^.overall_statistics.abnormal_status + 1;
        ELSE
        CASEND;

        IF fmd_header.requested_class <> rmc$unspecified_file_class THEN

          CASE move_object_info_p^.move_status.reason_for_move_failure OF
          = pfc$cycle_busy =
            move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved + 1;
            move_object_info_p^.class_statistics [fmd_header.requested_class].cycle_busy :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].cycle_busy + 1;
          = pfc$insufficient_space =
            move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved + 1;
            move_object_info_p^.class_statistics [fmd_header.requested_class].insufficient_space :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].insufficient_space + 1;
          = pfc$no_available_space =
            move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved + 1;
            move_object_info_p^.class_statistics [fmd_header.requested_class].no_available_space :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].no_available_space + 1;
          = pfc$io_error =
            move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved + 1;
            move_object_info_p^.class_statistics [fmd_header.requested_class].unrecovered_read_error :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].unrecovered_read_error +
                  1;
          = pfc$data_released =
            move_object_info_p^.class_statistics [fmd_header.requested_class].cycles_released :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].cycles_released + 1;
          = pfc$unexpected_abort =
            move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].objects_not_moved + 1;
            move_object_info_p^.class_statistics [fmd_header.requested_class].abnormal_status :=
                  move_object_info_p^.class_statistics [fmd_header.requested_class].abnormal_status + 1;
          ELSE
          CASEND;
        IFEND;
      IFEND;
    END /update_info/;

    IF move_object_info_p^.update_available_space_total > pfc$update_device_info_limit THEN
      update_available_space_info (move_object_info_p, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
    IFEND;

  PROCEND update_move_object_info;
?? OLDTITLE ??
?? NEWTITLE := ' validate_volume_threshold', EJECT ??

  PROCEDURE validate_volume_threshold
    (    move_object_info_p: ^pft$move_object_info);

    CONST
      allocation_unit = 16384,
      fudge_factor = 4 * allocation_unit;

    VAR
      set_threshold_exceeded: boolean,
      source_volume_p: ^pft$mo_volume,
      subfile_index: ost$positive_integers,
      volume_index: ost$positive_integers;

    IF move_object_info_p^.move_bytes_threshold = 0 THEN
      RETURN;
    IFEND;

    IF move_object_info_p^.move_status.old_subfile_list_p = NIL THEN
      RETURN;
    IFEND;

    IF move_object_info_p^.source_volume_list_p = NIL THEN
      RETURN;
    IFEND;

  /validate_threshold/
    FOR subfile_index := 1 TO UPPERBOUND (move_object_info_p^.move_status.old_subfile_list_p^) DO
      source_volume_p := NIL;

    /locate_source_volume/
      FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.source_volume_list_p^) DO
        IF move_object_info_p^.source_volume_list_p^ [volume_index]^.recorded_vsn =
              move_object_info_p^.move_status.old_subfile_list_p^ [subfile_index].recorded_vsn THEN
          source_volume_p := move_object_info_p^.source_volume_list_p^ [volume_index];
          EXIT /locate_source_volume/;
        IFEND;
      FOREND /locate_source_volume/;

      IF source_volume_p <> NIL THEN
        IF source_volume_p^.bytes_moved_from > move_object_info_p^.move_bytes_threshold THEN
          move_object_info_p^.move_status.move_successful := FALSE;
          move_object_info_p^.move_status.reason_for_move_failure := pfc$volume_threshold_exceeded;
          EXIT /validate_threshold/;
        IFEND;

        IF (move_object_info_p^.move_status.old_subfile_list_p^ [subfile_index].allocated_length +
              source_volume_p^.bytes_moved_from) > (move_object_info_p^.move_bytes_threshold + fudge_factor)
              THEN
          move_object_info_p^.move_status.move_successful := FALSE;
          move_object_info_p^.move_status.reason_for_move_failure := pfc$volume_threshold_exceeded;
          EXIT /validate_threshold/;
        IFEND;
      IFEND;
    FOREND /validate_threshold/;

    IF move_object_info_p^.move_status.reason_for_move_failure = pfc$volume_threshold_exceeded THEN
      set_threshold_exceeded := TRUE;

    /locate_threshold/
      FOR volume_index := 1 TO UPPERBOUND (move_object_info_p^.source_volume_list_p^) DO
        IF NOT move_object_info_p^.source_volume_list_p^ [volume_index]^.move_bytes_threshold_exceeded THEN
          set_threshold_exceeded := FALSE;
          EXIT /locate_threshold/;
        IFEND;
      FOREND /locate_threshold/;

      IF set_threshold_exceeded THEN
        move_object_info_p^.move_status.move_successful := FALSE;
        move_object_info_p^.move_status.reason_for_move_failure := pfc$set_threshold_exceeded;
      IFEND;
    IFEND;

  PROCEND validate_volume_threshold;
?? OLDTITLE ??
?? NEWTITLE := ' verify_volume_residence', EJECT ??

  PROCEDURE verify_volume_residence
    (    sfid: gft$system_file_identifier;
         volume_list_p: ^pft$mo_volume_list_p;
     VAR resides_on_volumes: boolean;
     VAR status: ost$status);


    VAR
      file_info: dmt$file_information,
      fmd_header: pft$fmd_header,
      p_physical_fmd: ^pft$physical_fmd,
      p_subfile_list: ^pft$subfile_list,
      stored_fmd_size: dmt$stored_fmd_size,
      subfile_index: ost$positive_integers,
      volume_index: ost$positive_integers;

    dmp$get_stored_fmd_size (sfid, stored_fmd_size, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    dmp$get_file_info (sfid, file_info, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    PUSH p_physical_fmd: [[REP stored_fmd_size OF cell]];
    dmp$get_stored_fmd (sfid, p_physical_fmd^.fmd, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    dmp$get_stored_fmd_header_info (^p_physical_fmd^.fmd, fmd_header, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    PUSH p_subfile_list: [1 .. fmd_header.number_of_subfiles];
    dmp$get_stored_fmd_subfile_list (^p_physical_fmd^.fmd, file_info.total_allocated_length,
          p_subfile_list, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    resides_on_volumes := TRUE;
  /check_subfiles/
    FOR subfile_index := 1 TO UPPERBOUND (p_subfile_list^) DO
      FOR volume_index := 1 TO UPPERBOUND (volume_list_p^) DO
        IF p_subfile_list^ [subfile_index].recorded_vsn =
              volume_list_p^ [volume_index]^.recorded_vsn THEN
          CYCLE /check_subfiles/;
        IFEND;
      FOREND;
      resides_on_volumes := FALSE;
      EXIT /check_subfiles/;
    FOREND /check_subfiles/;

  PROCEND verify_volume_residence;
?? OLDTITLE ??
MODEND pfm$r2_move_object;
