*copyc osd$default_pragmats
?? RIGHT := 110 ??
??
NEWTITLE := 'NOS/VE File Manager: Job Recovery' ??
MODULE fmm$job_recovery;
?? NEWTITLE := 'Global Declarations' ??
{
{  This module contains the driving procedure for recovery of files
{  following a system crash in which jobs are recovered.
{

  CONST
    one_second = 1000 {milliseconds};

  VAR
    fmv$fatal_tape_reserve_error: [XDCL] boolean := FALSE,
    fmv$recovered_pf_count: [XDCL]  0 .. 0ffffff(16) := 0,
    fmv$trimmed_pf_count: [XDCL] 0 .. 0ffffff(16) := 0,
    fmv$trimmed_tape_count: [XDCL] 0 .. 0ffffff(16) := 0,
    fmv$trimmed_file_count: [XDCL] 0 .. 0ffffff(16) := 0;

?? PUSH (LISTEXT := ON) ??
*copyc clp$construct_path_handle_name
*copyc dfe$error_condition_codes
*copyc dfv$file_server_debug_enabled
*copyc dme$tape_errors
*copyc dmp$detach_server_file
*copyc dmp$get_tape_volume_information
*copyc dmp$get_tape_volume_list
*copyc fmc$entry_assigned
*copyc fmc$test_jr_constants
*copyc fmp$get_path_string
*copyc fmp$lock_path_table
*copyc fmp$unlock_path_table
*copyc nac$null_connection_id
*copyc fme$file_management_errors
*copyc fmk$keypoints
*copyc fmt$cycle_description
*copyc fmt$cycle_description_unit
*copyc fmv$initial_cdu_pointer
*copyc fmv$path_table_lock
*copyc rmv$requested_volume_attributes
*copyc iop$create_rvl_entry
*copyc iop$set_sfid_in_rvl
*copyc osc$unseen_mail_condition
*copyc ose$job_recovery_exceptions
*copyc osp$append_status_integer
*copyc osp$initialize_signature_lock
*copyc osp$log_job_recovery_message
*copyc osp$log_job_recovery_status
*copyc osp$recoverable_system_error
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc osp$test_sig_lock
*copyc osp$test_signature_lock
*copyc oss$job_paged_literal
*copyc osv$job_pageable_heap
*copyc pmp$convert_binary_unique_name
*copyc pmp$get_pseudo_mainframe_id
*copyc pfe$internal_error_conditions
*copyc pfp$catalog_access_retry_wait
*copyc pfp$check_apfid_location
*copyc pfp$complete_job_recovery
*copyc pfp$initialize_job_recovery
*copyc pfp$reattach_permanent_file
*copyc pfp$reattach_reserved_cycles
*copyc pfp$relink_server_file
*copyc pfp$return_permanent_file
*copyc pfp$terminate_server_apfid
*copyc pmp$continue_to_cause
*copyc pmp$disestablish_cond_handler
*copyc pmp$establish_condition_handler
*copyc pmp$get_microsecond_clock
*copyc rmp$recover_job_tape_table
*copyc stp$recover_jobs_sets
*copyc syp$hang_if_job_jrt_set
*copyc syv$debug_job_recovery
  { DAH kludge

  PROCEDURE [XREF] syp$clear_job_recovery_test (t: zzzz;
        option: 0 .. 255);

  TYPE
    zzzz = (job, system);

*copyc syp$change_access_state
*copyc syp$invalidate_open_sfid
*copyc syp$pop_inhibit_job_recovery
*copyc syp$push_inhibit_job_recovery
*copyc syp$replace_sfid
?? POP ??
?? TITLE := ' FMP$RECOVER_JOB_FILES', EJECT ??
*copyc fmh$recover_job_files

  PROCEDURE [XDCL, #GATE] fmp$recover_job_files
    (VAR status: ost$status);

    VAR
      abort_conditions: [STATIC, READ, oss$job_paged_literal] pmt$condition := [pmc$condition_combination,
        [pmc$system_conditions, {pmc$block_exit_processing,} pmc$user_defined_condition,
        mmc$segment_access_condition]],

      abort_descriptor_area: pmt$established_handler;
{  The block_exit condition is currenltly commented out because it causes
{  an unending recursive condition on the EXIT statement in the condition
{  handler.  Processing for the block_exit condition needs to be added.



    VAR
      job_severely_damaged: boolean,
      display_status: ost$status,
      ignored_status: ost$status,
      mainframe_id: pmt$binary_mainframe_id,
      recover_all_files_status: ost$status,
      reservation_status: ost$status,
      pf_completion_status: ost$status;

?? NEWTITLE := 'RECOVERY_ABORT_HANDLER', EJECT ??

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

      { This procedure is established to catch unexpected conditions during the
      { job file recovery. If this condition is invoked the status of
      { ose$job_severely_damaged will be returned.

      VAR
        display_status: ost$status,
        condition_status: ost$status,
        construction_status: ost$status,
        ignored_status: ost$status;

      handler_status.normal := TRUE;

{ System unstep condition must be ignored since it causes job recovery to fail.

      IF (condition.selector = pmc$user_defined_condition)
{   } AND ((condition.user_condition_name = 'SYSTEM_UNSTEP_RESUME')
{       } OR (condition.user_condition_name = osc$unseen_mail_condition)) THEN

        RETURN;
      IFEND;

{ DISPLAY THE REASON FOR THE CONDITION
      osp$log_job_recovery_message (' Condition occurred in fmp$recover_job_files', display_status);
      osp$set_status_from_condition (amc$access_method_id, condition, save_area, condition_status,
            construction_status);
      IF construction_status.normal THEN
        osp$log_job_recovery_status (condition_status, display_status);
      ELSE
        osp$log_job_recovery_status (construction_status, display_status);
      IFEND;
      osp$set_status_abnormal (amc$access_method_id, ose$job_severely_damaged, ' Condition handler invoked',
            status);
      IF (condition.selector = pmc$user_defined_condition) AND (condition.user_condition_name =
        'OSC$JOB_RECOVERY') THEN
        {Stop previous recovery attempt, allows current to continue
        pmp$continue_to_cause (pmc$execute_standard_procedure, handler_status);
        osp$set_status_abnormal (amc$access_method_id, fme$multiple_job_recoveries, '', status);
      IFEND;
      pmp$disestablish_cond_handler (abort_conditions, ignored_status);
      EXIT fmp$recover_job_files;

    PROCEND recovery_abort_handler;
?? OLDTITLE ??
?? EJECT ??

    pmp$establish_condition_handler (abort_conditions, ^recovery_abort_handler, ^abort_descriptor_area,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    fmv$fatal_tape_reserve_error := FALSE;
    fmv$trimmed_pf_count := 0;
    fmv$trimmed_tape_count := 0;
    fmv$trimmed_file_count := 0;
    fmv$recovered_pf_count := 0;
    pmp$get_pseudo_mainframe_id (mainframe_id);

    stp$recover_jobs_sets (status);
    job_severely_damaged := NOT status.normal;

    IF NOT job_severely_damaged THEN
      check_path_table_lock (status);
      job_severely_damaged := NOT status.normal;
    IFEND;

    IF NOT job_severely_damaged THEN
      pfp$initialize_job_recovery (pfc$attached_pf_in_job_recovery, status);
      job_severely_damaged := (NOT status.normal) AND (status.condition = ose$job_severely_damaged);
    IFEND;

    IF NOT job_severely_damaged THEN
      recover_all_files (mainframe_id, recover_all_files_status);
      job_severely_damaged := (NOT recover_all_files_status.normal) AND (recover_all_files_status.condition =
            ose$job_severely_damaged);
    IFEND;

    IF NOT job_severely_damaged THEN
      pfp$complete_job_recovery (mainframe_id, pf_completion_status);
      IF status.normal THEN
        IF pf_completion_status.normal THEN
          status := recover_all_files_status;
        ELSE
          osp$log_job_recovery_status (recover_all_files_status, display_status);
          status := pf_completion_status;
        IFEND;
      ELSE
        osp$log_job_recovery_status (recover_all_files_status, display_status);
        osp$log_job_recovery_status (pf_completion_status, display_status);
      IFEND;
      job_severely_damaged := (NOT pf_completion_status.normal) AND (pf_completion_status.condition =
            ose$job_severely_damaged);
    IFEND;

    IF NOT job_severely_damaged THEN
      IF fmv$fatal_tape_reserve_error THEN
        osp$set_status_abnormal (amc$access_method_id, fme$tape_resource_not_recovered,
              '', reservation_status);
      ELSE
        reservation_status.normal := TRUE;
      IFEND;
      IF status.normal THEN
        status := reservation_status;
      ELSE
        osp$log_job_recovery_status (reservation_status, display_status);
      IFEND;
    IFEND;

    pmp$disestablish_cond_handler (abort_conditions, ignored_status);

  PROCEND fmp$recover_job_files;
?? TITLE := 'PROCEDURE check_path_table_lock', EJECT ??

  PROCEDURE check_path_table_lock (VAR status: ost$status);

{  This routine verifies that there are NO file manager global locks set.
{ The occurrence of a global lock set, will indicate that an error has
{ occurred in file manager, and that Rollback has not worked correctly.

    VAR
      lock_status: ost$signature_lock_status;

    status.normal := TRUE;
    osp$test_signature_lock (fmv$path_table_lock, lock_status);
    IF lock_status <> osc$sls_not_locked THEN
      osp$set_status_abnormal (amc$access_method_id, ose$path_table_locked,
        ' Path Table locked: task_id:', status);
      osp$append_status_integer (osc$status_parameter_delimiter, fmv$path_table_lock.lock_id, 16, FALSE,
            status);
      RETURN;
    IFEND;

  PROCEND check_path_table_lock;
?? TITLE := '  RECOVER_ALL_FILES ', EJECT ??

  PROCEDURE recover_all_files (mainframe_id: pmt$binary_mainframe_id;
     VAR status: ost$status);

{  This procedure assumes that the path_table can be read, and that
{  the permanent file manager may read its tables.
{  This traverses the path table, removing any tapes, and attempts
{    reattaching any permanent file.
{  Errors as they occur are logged, and a summary status condition is returned.
{

    CONST
      return_ring = 2;

    VAR
      cdu: ^fmt$cycle_description_unit,
      current_volume_number: amt$volume_number,
      current_vsns: rmt$volume_descriptor,
      cycle_description: ^fmt$cycle_description,
      density: rmt$density,
      display_status: ost$status,
      display_string: string (180),
      file_status: ost$status,
      i: integer,
      ignored_status: ost$status,
      job_has_tapes_assigned: boolean,
      label_type: amt$label_type,
      length: integer,
      local_status: ost$status,
      new_sfid: gft$system_file_identifier,
      number_of_volumes: amt$volume_number,
      old_sfid: gft$system_file_identifier,
      p_volume_list: ^rmt$volume_list,
      path_handle: fmt$path_handle,
      path_handle_name: fst$path_handle_name,
      pf_reattached: boolean,
      requested_volume_attributes: iot$requested_volume_attributes,
      share_selections: pft$share_selections,
      tape_class: rmt$tape_class,
      usage_selections: pft$usage_selections,
      volume_overflow_allowed: boolean,
      write_ring: rmt$write_ring;

    status.normal := TRUE;
    cdu := fmv$initial_cdu_pointer;
    rmp$recover_job_tape_table (job_has_tapes_assigned, fmv$fatal_tape_reserve_error);

    WHILE (cdu <> NIL) DO

    /loop_through_cdu/
      FOR i := 1 TO #SIZE(cdu^.entry_assignment^) DO
        IF (cdu^.entry_assignment^ (i) = fmc$entry_assigned) THEN
          cycle_description := ^cdu^.entries^ [i];
          IF cycle_description^.attached_file THEN
            CASE cycle_description^.device_class OF
            = rmc$magnetic_tape_device =
              IF cycle_description^.permanent_file THEN
                #UNCHECKED_CONVERSION (cycle_description^.attached_access_modes, usage_selections);
                #UNCHECKED_CONVERSION (cycle_description^.attached_share_modes, share_selections);
                syp$push_inhibit_job_recovery;
              /reattach_permanent_file_1/
                WHILE TRUE DO
                  pfp$reattach_permanent_file (cycle_description^.apfid, cycle_description^.device_class,
                        cycle_description^.system_file_label.descriptive_label.internal_cycle_name,
                        mainframe_id, usage_selections, share_selections, new_sfid, file_status);
                  IF file_status.normal OR (file_status.condition <> pfe$catalog_access_retry) THEN
                    EXIT /reattach_permanent_file_1/;
                  ELSE
                    syp$pop_inhibit_job_recovery;
                    pfp$catalog_access_retry_wait ('PFP$REATTACH_PERMANENT_FILE');
                    syp$push_inhibit_job_recovery;
                  IFEND;
                WHILEND /reattach_permanent_file_1/;
                pf_reattached := file_status.normal;
                IF NOT file_status.normal THEN
                  STRINGREP (display_string, length, 'Unable to recover an attached tape file.');
                  osp$log_job_recovery_message (display_string (1, length), display_status);
                  osp$log_job_recovery_status (file_status, display_status);
                  cycle_description^.attached_file := FALSE;
                  fmv$trimmed_pf_count := fmv$trimmed_pf_count + 1;
                  CYCLE /loop_through_cdu/;
                IFEND;
                syp$pop_inhibit_job_recovery;
              IFEND;

              IF NOT fmv$fatal_tape_reserve_error THEN
                dmp$get_tape_volume_information (cycle_description^.system_file_id, number_of_volumes,
                      current_volume_number, current_vsns, density, write_ring, requested_volume_attributes,
                      volume_overflow_allowed, label_type, file_status);
                IF file_status.normal THEN
                  PUSH p_volume_list: [1 .. number_of_volumes];
                  dmp$get_tape_volume_list (cycle_description^.system_file_id, p_volume_list, file_status);
                  IF file_status.normal THEN
                    REPEAT
                      iop$create_rvl_entry (cycle_description^.system_file_id, density,
                            cycle_description^.system_file_label.descriptive_label.internal_cycle_name,
                            cycle_description^.path_handle, requested_volume_attributes,
                            p_volume_list^, write_ring, file_status);
                      IF NOT file_status.normal AND
                            (file_status.condition = dme$unable_to_lock_tape_table) THEN
                        pmp$wait (one_second, one_second);
                      IFEND;
                    UNTIL file_status.normal OR (file_status.condition <> dme$unable_to_lock_tape_table);
                  IFEND;
                IFEND;
              IFEND;

              IF fmv$fatal_tape_reserve_error OR job_has_tapes_assigned OR
                    NOT file_status.normal THEN

{ Currently a job will not recover if tapes were assigned at the time of the system failure.

                fmv$trimmed_tape_count := fmv$trimmed_tape_count + 1;
                STRINGREP (display_string, length, ' Deleting a tape file ');
                osp$log_job_recovery_message (display_string (1, length), display_status);
              IFEND;
            = rmc$mass_storage_device =
              IF cycle_description^.permanent_file THEN
                #UNCHECKED_CONVERSION (cycle_description^.attached_access_modes, usage_selections);
                #UNCHECKED_CONVERSION (cycle_description^.attached_share_modes, share_selections);
                syp$push_inhibit_job_recovery;
              /reattach_permanent_file_2/
                WHILE TRUE DO
                  pfp$reattach_permanent_file (cycle_description^.apfid, cycle_description^.device_class,
                        cycle_description^.system_file_label.descriptive_label.internal_cycle_name,
                        mainframe_id, usage_selections, share_selections, new_sfid, file_status);
                  IF file_status.normal OR (file_status.condition <> pfe$catalog_access_retry) THEN
                    EXIT /reattach_permanent_file_2/;
                  ELSE
                    syp$pop_inhibit_job_recovery;
                    pfp$catalog_access_retry_wait ('PFP$REATTACH_PERMANENT_FILE');
                    syp$push_inhibit_job_recovery;
                  IFEND;
                WHILEND /reattach_permanent_file_2/;
                pf_reattached := file_status.normal;
                old_sfid := cycle_description^.system_file_id;
                IF file_status.normal THEN
                  IF cycle_description^.apfid.family_location = pfc$local_mainframe THEN
                    syp$replace_sfid (old_sfid, new_sfid, mmc$sas_allow_access, file_status);
                  ELSE { Server mainframe - inhibit access until server job recovery
                    syp$replace_sfid (old_sfid, new_sfid, mmc$sas_inhibit_access, file_status);
                  IFEND;
                ELSE
                  syp$invalidate_open_sfid (old_sfid, ignored_status);
                IFEND;
                IF file_status.normal THEN
                  cycle_description^.system_file_id := new_sfid;
                  fmv$recovered_pf_count := fmv$recovered_pf_count + 1;
                ELSE
                  STRINGREP (display_string, length, ' Unable to recover an attached file ');
                  osp$log_job_recovery_message (display_string (1, length), display_status);
                  osp$log_job_recovery_status (file_status, display_status);
                  IF pf_reattached THEN
                    osp$log_job_recovery_message (' Detaching reattached permanent file', display_status);
                    pfp$return_permanent_file (cycle_description^.apfid, new_sfid,
                          cycle_description^.device_class, usage_selections, ignored_status);
                    osp$log_job_recovery_status (ignored_status, display_status);
                  IFEND;
                  cycle_description^.attached_file := FALSE;
                  fmv$trimmed_pf_count := fmv$trimmed_pf_count + 1;
                IFEND;
                syp$pop_inhibit_job_recovery;
                IF (fmv$recovered_pf_count = 5) THEN
                  { Test job recovery conditions within job recovery
                  IF (fmc$tjr_recover_all_files IN syv$test_jr_job) THEN
                    syp$clear_job_recovery_test (job, fmc$tjr_recover_all_files);
                    WHILE TRUE DO
                      pmp$wait (one_second, one_second);
                    WHILEND;
                  IFEND;
                  IF fmc$tjr_recovery_abort IN syv$test_jr_job THEN
                    { Induce segment condition
                    cycle_description := NIL;
                    cycle_description^.attached_file := FALSE;
                  IFEND;
                IFEND;
              IFEND;
            = rmc$network_device =
              cycle_description^.global_file_information^.device_dependent_info.
                    network_connection_id := nac$null_connection_id;
              IF cycle_description^.global_file_information^.device_dependent_info.
                network_global_file_information^.file_state = nac$switch_offered THEN
                cycle_description^.global_file_information^.device_dependent_info.
                      network_global_file_information^.file_state := nac$system_recovery_switched;
              ELSEIF cycle_description^.global_file_information^.device_dependent_info.
                network_global_file_information^.file_state = nac$nominal_conn_switch_offer THEN
                cycle_description^.global_file_information^.device_dependent_info.
                      network_global_file_information^.file_state := nac$system_recovery_switchd_nom;
              ELSE
                cycle_description^.global_file_information^.device_dependent_info.
                      network_global_file_information^.file_state := nac$system_recovery;
              IFEND;
              IF NOT cycle_description^.global_file_information^.device_dependent_info.
                  network_global_file_information^.connect.valid_start_down_time THEN
                pmp$get_microsecond_clock (cycle_description^.global_file_information^.
                      device_dependent_info.network_global_file_information^.connect.start_down_time,
                      ignored_status);
                cycle_description^.global_file_information^.device_dependent_info.
                    network_global_file_information^.connect.valid_start_down_time := TRUE;
              IFEND;
            ELSE
            CASEND;
          IFEND;
        IFEND; {entry assigned}
      FOREND /loop_through_cdu/;
      cdu := cdu^.next_cycle_description_unit;
    WHILEND;

    IF fmv$trimmed_pf_count > 0 THEN
      osp$set_status_abnormal (amc$access_method_id, fme$not_all_pfs_recovered, '', status);
      osp$append_status_integer (osc$status_parameter_delimiter, fmv$trimmed_pf_count, 10, FALSE, status);
    ELSEIF fmv$trimmed_tape_count > 0 THEN
      osp$set_status_abnormal (amc$access_method_id, fme$tape_files_not_recovered, '  ', status);
      osp$append_status_integer (osc$status_parameter_delimiter, fmv$trimmed_tape_count, 10, FALSE, status);
    ELSEIF fmv$trimmed_file_count > 0 THEN
      osp$set_status_abnormal (amc$access_method_id, fme$not_all_files_recovered, '  ', status);
      osp$append_status_integer (osc$status_parameter_delimiter, fmv$trimmed_file_count, 10, FALSE, status);
    IFEND;

    IF status.normal THEN
      pfp$reattach_reserved_cycles (mainframe_id, status);
      IF NOT status.normal THEN
        osp$set_status_abnormal (amc$access_method_id, fme$not_all_pfs_recovered, '', status);
        osp$append_status_integer (osc$status_parameter_delimiter, {Unknown} 1, 10, FALSE, status);
      IFEND;
    IFEND;

  PROCEND recover_all_files;
?? TITLE := ' fmp$recover_server_files', EJECT ??
*copyc fmh$recover_server_files
?? EJECT ??

  PROCEDURE [XDCL, #GATE] fmp$recover_server_files
    (    server_mainframe_id: pmt$binary_mainframe_id;
     VAR status: ost$status);


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

{ This procedure is established to catch unexpected conditions during the
{ server job file recovery. If this condition is invoked the status of
{ ose$job_severely_damaged will be returned.  The job will
{ propably go to the nether region.

      VAR
        display_status: ost$status,
        condition_status: ost$status,
        construction_status: ost$status,
        ignored_status: ost$status;

      handler_status.normal := TRUE;
      { DISPLAY THE REASON FOR THE CONDITION
      osp$log_job_recovery_message (' Condition occurred in fmp$recover_server_files', display_status);
      osp$set_status_from_condition (amc$access_method_id, condition, save_area, condition_status,
            construction_status);
      IF construction_status.normal THEN
        osp$log_job_recovery_status (condition_status, display_status);
      ELSE
        osp$log_job_recovery_status (construction_status, display_status);
      IFEND;
      osp$set_status_abnormal (amc$access_method_id, ose$job_severely_damaged, ' Condition handler invoked',
            status);
      pmp$disestablish_cond_handler (abort_conditions, ignored_status);
      IF lock_status.normal THEN
        fmp$unlock_path_table;
      IFEND;
      EXIT fmp$recover_server_files;
    PROCEND recovery_abort_handler;


    VAR
      abort_conditions: [STATIC, READ, oss$job_paged_literal] pmt$condition :=
            [pmc$condition_combination, [pmc$system_conditions,
            {pmc$block_exit_processing,} pmc$user_defined_condition, mmc$segment_access_condition]],
      abort_descriptor_area: pmt$established_handler;

{  The block_exit condition is currenltly commented out because it causes
{  an unending recursive condition on the EXIT statement in the condition
{  handler.  Processing for the block_exit condition needs to be added.

?? EJECT ??

    VAR
      ignored_status: ost$status,
      lock_status: ost$status;

    lock_status.normal := TRUE;
{   osp$test_sig_lock (fmv$path_table_lock, lock_status);
{   IF lock_status <> osc$sls_locked_by_current_task THEN
       { The above IF check is a KLUDGE because of the sequence
       { fmp$process_pt_request (locks table)
       {   pfp$resolve_path
       {      server job recovery
       {        fmp$recover_server_files
       { In this sequence the path table is readable despite the lock.
      fmp$lock_path_table (lock_status);
{   IFEND;
    pmp$establish_condition_handler (abort_conditions, ^recovery_abort_handler, ^abort_descriptor_area,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    fmv$trimmed_pf_count := 0;
    fmv$recovered_pf_count := 0;

    recover_all_server_files (server_mainframe_id, status);
    pmp$disestablish_cond_handler (abort_conditions, ignored_status);
    IF lock_status.normal THEN
      fmp$unlock_path_table;
    IFEND;
  PROCEND fmp$recover_server_files;
?? TITLE := '  RECOVER_ALL_SERVER_FILES ', EJECT ??

  PROCEDURE recover_all_server_files
    (    server_mainframe_id: pmt$binary_mainframe_id;
     VAR status: ost$status);

    VAR
      correct_mainframe: boolean,
      cdu: ^fmt$cycle_description_unit,
      cycle_description: ^fmt$cycle_description,
      display_status: ost$status,
      file_status: ost$status,
      gfn_name: ost$name,
      i: integer,
      length: integer,
      new_sfid: gft$system_file_identifier,
      path_string: fst$path,
      path_size: fst$path_size;

    status.normal := TRUE;
    cdu := fmv$initial_cdu_pointer;

  /loop_though_all_cdus/
    WHILE (cdu <> NIL) DO

    /loop_through_cdu/
      FOR i := 1 TO #SIZE (cdu^.entry_assignment^) DO
        IF (cdu^.entry_assignment^ (i) = fmc$entry_assigned) THEN
          cycle_description := ^cdu^.entries^ [i];
          IF cycle_description^.attached_file AND cycle_description^.permanent_file THEN
            pfp$check_apfid_location (server_mainframe_id, cycle_description^.apfid, correct_mainframe);
            IF correct_mainframe THEN
              syp$push_inhibit_job_recovery;
              pfp$relink_server_file (cycle_description^.apfid,
                    cycle_description^.system_file_label.descriptive_label.internal_cycle_name,
                    cycle_description^.system_file_id, cycle_description^.device_class,
                    cycle_description^.apfid, new_sfid, file_status);
              { No matter what replace the apfid and sfid.
              { Permanent files will return the appropriate sfid in normal and abnormal cases.
              { Should the 're-attach' fail, depend on server cleanup to detach the file on the server.
              IF cycle_description^.device_class = rmc$mass_storage_device THEN
                IF file_status.normal THEN
                  syp$change_access_state (cycle_description^.system_file_id, mmc$sas_allow_access, status);
                  cycle_description^.system_file_id := new_sfid;
                  fmv$recovered_pf_count := fmv$recovered_pf_count + 1;
                ELSE
                  cycle_description^.system_file_id := new_sfid;
                  pmp$convert_binary_unique_name (
                        cycle_description^.system_file_label.descriptive_label.internal_cycle_name,
                        gfn_name, display_status);
                  STRINGREP (path_string, length, 'Unable to recover server file.', gfn_name);
                  osp$log_job_recovery_message (path_string (1, length), display_status);
                  osp$log_job_recovery_status (file_status, display_status);
                  path_string := 'dog';
                  path_size := 3;
                  fmp$get_path_string (cycle_description^.path_handle, {lock_path_table} FALSE,
                        path_string, path_size, display_status);
                  osp$log_job_recovery_message (path_string (1, path_size), display_status);
                  IF (file_status.condition = dfe$server_not_active) OR
                        (file_status.condition =  dfe$server_has_terminated) THEN
                    { The state of the server has changed since this process started.
                    { Allow higher code to wait, or terminate server access.
                    syp$pop_inhibit_job_recovery;
                    RETURN;
                  IFEND;
                  syp$change_access_state (cycle_description^.system_file_id, mmc$sas_terminate_access,
                        status);
                  IF dfv$file_server_debug_enabled AND syv$debug_job_recovery THEN
                    osp$recoverable_system_error ('Could not relink server file.', ^file_status);
                  IFEND;
                  fmv$trimmed_pf_count := fmv$trimmed_pf_count + 1;
                IFEND;
                IF NOT status.normal THEN
                  { This procedure should never have failed.
                  IF dfv$file_server_debug_enabled THEN
                    osp$recoverable_system_error ('Could not change access state.', ^status);
                  IFEND;
                  osp$log_job_recovery_message ('Unable to change attached server file access state.',
                        display_status);
                  osp$log_job_recovery_status (status, display_status);
                IFEND;
              IFEND;
              syp$pop_inhibit_job_recovery;

              IF (fmv$recovered_pf_count = 5) THEN
                { Test job recovery conditions within job recovery
                IF (fmc$tjr_recover_all_files IN syv$test_jr_job) THEN
                  syp$clear_job_recovery_test (job, fmc$tjr_recover_all_files);

                /hang_forever/
                  WHILE TRUE DO
                    pmp$wait (one_second, one_second);
                  WHILEND /hang_forever/;
                IFEND;
                IF fmc$tjr_recovery_abort IN syv$test_jr_job THEN
                  { Induce segment condition
                  cycle_description := NIL;
                  cycle_description^.attached_file := FALSE;
                IFEND;
              IFEND; { fmv$recovered_pf_count = 5}

            IFEND; { Permanent file }
          IFEND; { Correct mainframe}
        IFEND; { Entry assigned }
      FOREND /loop_through_cdu/;
      cdu := cdu^.next_cycle_description_unit;
    WHILEND /loop_though_all_cdus/;

    IF fmv$trimmed_pf_count > 0 THEN
      osp$set_status_abnormal (amc$access_method_id, fme$not_all_pfs_recovered, '', status);
      osp$append_status_integer (osc$status_parameter_delimiter, fmv$trimmed_pf_count, 10, FALSE, status);
    IFEND;
  PROCEND recover_all_server_files;
?? TITLE := ' fmp$terminate_server_files', EJECT ??
*copyc fmh$terminate_server_files
?? EJECT ??

  PROCEDURE [XDCL, #GATE] fmp$terminate_server_files
    (    server_mainframe_id: pmt$binary_mainframe_id;
     VAR status: ost$status);

    VAR
      correct_mainframe: boolean,
      cdu: ^fmt$cycle_description_unit,
      cycle_description: ^fmt$cycle_description,
      display_status: ost$status,
      gfn_name: ost$name,
      i: integer,
      ignore_attached_for_write: boolean,
      ignore_eoi: amt$file_byte_address,
      ignore_server_sfid: gft$system_file_identifier,
      ignore_status: ost$status,
      length: integer,
      lock_status: ost$status,
      path_string: fst$path,
      path_size: fst$path_size;

    { fmv$trimmed_pf_count is provided solely for debugging.
    fmv$trimmed_pf_count := 0;
    lock_status.normal := TRUE;
{   osp$test_sig_lock (fmv$path_table_lock, lock_status);
{   IF lock_status <> osc$sls_locked_by_current_task THEN
      fmp$lock_path_table (lock_status);
{   IFEND;
    status.normal := TRUE;
    cdu := fmv$initial_cdu_pointer;

  /loop_though_all_cdus/
    WHILE (cdu <> NIL) DO

    /loop_through_cdu/
      FOR i := 1 TO #SIZE (cdu^.entry_assignment^) DO
        IF (cdu^.entry_assignment^ (i) = fmc$entry_assigned) THEN
          cycle_description := ^cdu^.entries^ [i];
          IF cycle_description^.attached_file AND (cycle_description^.device_class =
                rmc$mass_storage_device) AND cycle_description^.permanent_file THEN
            pfp$check_apfid_location (server_mainframe_id, cycle_description^.apfid, correct_mainframe);
            IF correct_mainframe THEN
              pfp$terminate_server_apfid (cycle_description^.apfid);
              syp$change_access_state (cycle_description^.system_file_id, mmc$sas_terminate_access, status);
              IF dfv$file_server_debug_enabled AND (NOT status.normal) THEN
                osp$recoverable_system_error (' Could not replace server sfid', ^status);
              IFEND;
{ Clean up the "dangling" file_descriptor_entry.
              dmp$detach_server_file (cycle_description^.system_file_id, {flush_pages=} FALSE,
                    {unconditional_detach=} TRUE, ignore_attached_for_write, ignore_eoi, ignore_server_sfid,
                    ignore_status);
              pmp$convert_binary_unique_name (
                    cycle_description^.system_file_label.descriptive_label.internal_cycle_name,
                    gfn_name, display_status);
              STRINGREP (path_string, length, 'Terminating  server file ', gfn_name);
              osp$log_job_recovery_message (path_string (1, length), display_status);
              fmv$trimmed_pf_count := fmv$trimmed_pf_count + 1;
              path_string := 'dog';
              path_size := 3;
              fmp$get_path_string (cycle_description^.path_handle, { Lock_path_table} FALSE,
                  path_string, path_size, display_status);
              osp$log_job_recovery_message (path_string (1, path_size), display_status);
            IFEND; { Permanent file }
          IFEND; { Correct mainframe}
        IFEND; { Entry assigned }
      FOREND /loop_through_cdu/;
      cdu := cdu^.next_cycle_description_unit;
    WHILEND /loop_though_all_cdus/;

    IF lock_status.normal THEN
      fmp$unlock_path_table;
    IFEND;
  PROCEND fmp$terminate_server_files;

MODEND fmm$job_recovery;

