?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE File Server: Recovery Services' ??
MODULE dfm$recovery_services;
?? NEWTITLE := '  Global Declarations Reference by this Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dfc$partially_rebuilt_fde_eoi
*copyc dfc$test_jr_constants
*copyc dfe$mm_recovery_errors
*copyc dft$image_file_id
*copyc dft$server_lifetime
*copyc dft$served_family_table_index
*copyc dft$server_state
*copyc dft$server_descriptor
*copyc gfc$constants
*copyc gft$file_descriptor_entry
*copyc gft$system_file_identifier
*copyc mmt$rb_ring1_server_seg_request
*copyc osd$integer_limits
*copyc ost$status
?? POP ??
*copyc dfi$core_log_display
*copyc dfp$expand_image_file
*copyc dfp$fetch_served_family_info
*copyc dfp$fetch_server_state
*copyc dfp$get_next_image_block
*copyc dfp$get_served_file_desc_p
*copyc dfp$uncomplement_gfn
*copyc dpp$put_critical_message
*copyc gfp$get_fde_p
*copyc gfp$lock_fde
*copyc gfp$scan_all_fdes
*copyc gfp$unlock_fde_p
*copyc i#call_monitor
*copyc mmp$mm_move_mod_server_page
*copyc mme$condition_codes
*copyc osp$convert_to_real_model_num
*copyc osp$set_status_abnormal
*copyc osp$system_error
*copyc osv$page_size
*copyc pmp$delay
*copyc syp$core_hang_if_system_jrt_set
*copyc dfv$file_server_debug_enabled
*copyc syv$debug_job_recovery
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL, #GATE] dfp$deactivate_server_files', EJECT ??

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

    CONST
      one_second = 1000;

    VAR
      family_server_state: dft$server_state,
      files_attempted: ost$non_negative_integers,
      file_count: ost$non_negative_integers,
      files_not_deactivated: ost$non_negative_integers,
      ignore_status: ost$status,
      p_fde: gft$file_desc_entry_p,
      pages_not_deleted: integer,
      pass_number: 0 .. 5,
      real_model_number: ost$processor_model_number,
      scan_control: gft$scan_all_fdes_state,
      server_descriptor_p: dft$server_descriptor_p,
      sfid: gft$system_file_identifier,
      st: string (100),
      stl: integer;


    pass_number := 0;

    REPEAT {until_all_deactivated}
      file_count := 0;
      files_attempted := 0;
      files_not_deactivated := 0;
      sfid.residence := gfc$tr_system;

      gfp$scan_all_fdes (gfc$tr_system, scan_control, p_fde);
      WHILE p_fde <> NIL DO

      /deactivate_server_file_block/
        BEGIN

          IF p_fde^.media <> gfc$fm_served_file THEN
            EXIT /deactivate_server_file_block/;
          IFEND;

          gfp$lock_fde (p_fde);

          dfp$get_served_file_desc_p (p_fde, server_descriptor_p);
          IF server_descriptor_p^.header.purged THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          IFEND;

          IF p_fde^.media <> gfc$fm_served_file THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          IFEND;

          dfp$get_served_file_desc_p (p_fde, server_descriptor_p);
          IF server_descriptor_p^.header.server_mainframe_id <> server_mainframe_id THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          IFEND;

          IF (server_descriptor_p^.header.file_state = dfc$awaiting_recovery) OR
             (server_descriptor_p^.header.file_state = dfc$terminated) THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          IFEND;

          dfp$fetch_server_state (server_descriptor_p, family_server_state);
          CASE family_server_state OF
          = dfc$terminated, dfc$deleted =

{ Family left over from a previous lifetime.

            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          = dfc$deactivated =

{ Normal case.

          ELSE
            osp$convert_to_real_model_num (server_mainframe_id.model_number, real_model_number);
            STRINGREP (st, stl, 'Model', real_model_number, ', S/N', server_mainframe_id.serial_number: 16);
            osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated, st (1, stl), status);
            gfp$unlock_fde_p (p_fde);
            RETURN;
          CASEND;

          file_count := file_count + 1;

{ Now see if there are pages to deal with

          IF p_fde^.asti = 0 THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          IFEND;

          IF p_fde^.attach_count = 0 THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /deactivate_server_file_block/;
          IFEND;

          sfid.file_hash := p_fde^.file_hash;
          sfid.file_entry_index := (#OFFSET (p_fde) - gfc$fde_table_base) DIV gfc$fde_size;

{ The FDE is left locked during the monitor request (located in the procedure below) to prevent asynchronous
{ detachment/deletion of a server file during deactivation.  Monitor mode locks a different lock during its
{ processing.  The job mode lock will be cleared upon return to this procedure.

          files_attempted := files_attempted + 1;
          deact_term_server_file (sfid, mmc$ssr1_flush_delete_seg_sfid, pages_not_deleted, status);
          gfp$unlock_fde_p (p_fde);
          IF NOT status.normal THEN
            IF dfv$file_server_debug_enabled THEN
              STRINGREP (st, stl, ' File not deactivated: SFID = ', sfid.file_entry_index:#(16),
                    '(16), Pages = ', pages_not_deleted);
              core_log_display (st (1, stl));
              dpp$put_critical_message (st (1, stl), ignore_status);
            IFEND;
            IF status.condition = dfe$server_pages_not_deleted THEN
              files_not_deactivated := files_not_deactivated + 1;
              status.normal := TRUE;
            ELSE
              RETURN;
            IFEND;
          IFEND;
        END /deactivate_server_file_block/;

        gfp$scan_all_fdes (gfc$tr_null_residence, scan_control, p_fde);
      WHILEND;

{!    The following four lines should be moved out of the REPEAT/UNTIL when debugging is complete.

      STRINGREP (st, stl, file_count, ' Server_File(s) found - Attempted deactivation on ', files_attempted);
      dpp$put_critical_message (st (1, stl), ignore_status);
      core_log_display (st (1, stl));
      STRINGREP (st, stl, files_not_deactivated, ' Server_File(s) NOT deactivated');
      dpp$put_critical_message (st (1, stl), ignore_status);
      core_log_display (st (1, stl));

      pass_number := pass_number + 1;
      IF files_not_deactivated <> 0 THEN
        pmp$delay (10 * one_second, ignore_status);
      IFEND;

    UNTIL (files_not_deactivated = 0) OR (pass_number = 5);

    IF files_not_deactivated <> 0 THEN
      STRINGREP (st, stl, files_not_deactivated);
      osp$set_status_abnormal (dfc$file_server_id, dfe$server_file_not_deactivated, st (1, stl), status);
      RETURN;
    IFEND;

  PROCEND dfp$deactivate_server_files;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL, #GATE] dfp$terminate_server_files', EJECT ??

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

    VAR
      family_server_state: dft$server_state,
      files_attempted: ost$non_negative_integers,
      file_count: ost$non_negative_integers,
      files_not_terminated: ost$non_negative_integers,
      ignore_status: ost$status,
      pages_not_deleted: integer,
      p_fde: gft$file_desc_entry_p,
      real_model_number: ost$processor_model_number,
      scan_control: gft$scan_all_fdes_state,
      server_descriptor_p: dft$server_descriptor_p,
      sfid: gft$system_file_identifier,
      st: string (100),
      stl: integer;


    REPEAT {until_all_terminated}
      files_attempted := 0;
      file_count := 0;
      files_not_terminated := 0;
      sfid.residence := gfc$tr_system;

      gfp$scan_all_fdes (gfc$tr_system, scan_control, p_fde);
      WHILE p_fde <> NIL DO

      /terminate_server_file_block/
        BEGIN

          IF p_fde^.media <> gfc$fm_served_file THEN
            EXIT /terminate_server_file_block/;
          IFEND;

          gfp$lock_fde (p_fde);

          dfp$get_served_file_desc_p (p_fde, server_descriptor_p);
          IF server_descriptor_p^.header.purged THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /terminate_server_file_block/;
          IFEND;

          IF p_fde^.media <> gfc$fm_served_file THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /terminate_server_file_block/;
          IFEND;

          IF server_descriptor_p^.header.server_mainframe_id <> server_mainframe_id THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /terminate_server_file_block/;
          IFEND;

          dfp$fetch_server_state (server_descriptor_p, family_server_state);
          IF (family_server_state <> dfc$terminated) AND (family_server_state <> dfc$deleted) THEN
            osp$convert_to_real_model_num (server_mainframe_id.model_number, real_model_number);
            STRINGREP (st, stl, 'Model', real_model_number, ', S/N', server_mainframe_id.serial_number: 16);
            gfp$unlock_fde_p (p_fde);
            osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated, st (1, stl), status);
            osp$system_error ('Unexpected status: family_server_state <> dfc$terminated/awar', ^status);
          IFEND;

          server_descriptor_p^.header.file_state := dfc$terminated;
          file_count := file_count + 1;

{ Now check the state of the pages.

          IF p_fde^.asti = 0 THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /terminate_server_file_block/;
          IFEND;

          IF p_fde^.attach_count = 0 THEN
            gfp$unlock_fde_p (p_fde);
            EXIT /terminate_server_file_block/;
          IFEND;

          sfid.file_hash := p_fde^.file_hash;
          sfid.file_entry_index := (#OFFSET (p_fde) - gfc$fde_table_base) DIV gfc$fde_size;

{ The FDE is left locked during the monitor request (located in the procedure below) to prevent asynchronous
{ detachment/deletion of a server file during termination.  Monitor mode locks a different lock during its
{ processing.  The job mode lock will be cleared upon return to this procedure.

          files_attempted := files_attempted + 1;
          deact_term_server_file (sfid, mmc$ssr1_free_delete_seg_sfid, pages_not_deleted, status);
          gfp$unlock_fde_p (p_fde);
          IF NOT status.normal THEN
            IF dfv$file_server_debug_enabled THEN
              STRINGREP (st, stl, ' File not terminated: SFID = ', sfid.file_entry_index:#(16),
                    '(16), Pages = ', pages_not_deleted);
              core_log_display (st (1, stl));
              dpp$put_critical_message (st (1, stl), ignore_status);
            IFEND;
            IF status.condition = dfe$server_pages_not_deleted THEN
              files_not_terminated := files_not_terminated + 1;
              status.normal := TRUE;
            ELSE
              RETURN;
            IFEND;
          IFEND;
        END /terminate_server_file_block/;

        gfp$scan_all_fdes (gfc$tr_null_residence, scan_control, p_fde);
      WHILEND;

{!    The following four lines should be moved out of the REPEAT/UNTIL when debugging is complete.

      STRINGREP (st, stl, file_count, ' Server_File(s) found - Attempted termination on ', files_attempted);
      dpp$put_critical_message (st (1, stl), ignore_status);
      core_log_display (st (1, stl));
      STRINGREP (st, stl, files_not_terminated, ' Server_File(s) NOT terminated');
      dpp$put_critical_message (st (1, stl), ignore_status);
      core_log_display (st (1, stl));

    UNTIL files_not_terminated = 0;

  PROCEND dfp$terminate_server_files;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL, #GATE] dfp$r1_timeout_server_files', EJECT ??
{
{   The purpose of this procedure is to 'timeout' server files for
{ a particular server.  This involves marking all the files as awaiting
{ recovery, saving all modified shared pages for the files, and removing
{ all read shared pages for the files.
{ The should closely follow the code in dfm$Manage_image with respect to
{ writing the server image file.

  PROCEDURE [XDCL, #GATE] dfp$r1_timeout_server_files
    (    server_mainframe_id: pmt$binary_mainframe_id;
         p_server_state : ^dft$server_state;
     VAR image_file_id: dft$image_file_id;
     VAR status: ost$status);

    VAR
      family_server_state: dft$server_state,
      file_count: ost$non_negative_integers,
      file_page_count: integer,
      ignore_status: ost$status,
      p_fde: gft$file_desc_entry_p,
      scan_control: gft$scan_all_fdes_state,
      server_descriptor_p: dft$server_descriptor_p,
      sfid: gft$system_file_identifier,
      space_available_for_image: boolean,
      space_available_status: ost$status,
      st: string (100),
      stl: integer,
      total_page_count: integer,
      total_pages_removed: integer;

    file_count := 0;
    total_page_count := 0;
    total_pages_removed :=  0;
    space_available_for_image := TRUE;
    sfid.residence := gfc$tr_system;

    gfp$scan_all_fdes (gfc$tr_system, scan_control, p_fde);
    WHILE p_fde <> NIL DO

    /timeout_server_file_block/
      BEGIN
        IF p_fde^.media <> gfc$fm_served_file THEN
          EXIT /timeout_server_file_block/;
        IFEND;

        IF p_server_state^ <> dfc$awaiting_recovery THEN
          osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated, '', status);

{ State change has occurred to go to terminated. Get out of here.

          RETURN;
        IFEND;

        gfp$lock_fde (p_fde);

        dfp$get_served_file_desc_p (p_fde, server_descriptor_p);
        IF server_descriptor_p^.header.purged THEN
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        IF p_fde^.media <> gfc$fm_served_file THEN
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        IF server_descriptor_p^.header.server_mainframe_id <> server_mainframe_id THEN
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        dfp$fetch_server_state (server_descriptor_p, family_server_state);
        CASE family_server_state OF
        = dfc$terminated, dfc$deleted =

{ Family left over from a previous lifetime.

          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        = dfc$awaiting_recovery =
          ELSE
          gfp$unlock_fde_p (p_fde);
          osp$system_error ('Unexpected status: family_server_state <> awaiting_recovery', NIL);
          RETURN;
        CASEND;

        IF server_descriptor_p^.header.file_state = dfc$terminated THEN
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        file_count := file_count + 1;
        sfid.file_hash := p_fde^.file_hash;
        sfid.file_entry_index := (#OFFSET (p_fde) - gfc$fde_table_base) DIV gfc$fde_size;
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, ' File ', file_count, ' awaiting recovery - SFID = ',
                sfid.file_entry_index:#(16), '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;

        server_descriptor_p^.header.file_state := dfc$awaiting_recovery;
        IF p_fde^.attach_count = 0 THEN
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        IF p_fde^.eoi_byte_address = dfc$partially_rebuilt_fde_eoi THEN
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        IF p_fde^.attached_in_write_count = 0 THEN
          IF p_fde^.asti <> 0 THEN
            remove_server_file_pages (sfid, p_fde);
          IFEND;
          gfp$unlock_fde_p (p_fde);
          EXIT /timeout_server_file_block/;
        IFEND;

        IF space_available_for_image THEN
          save_server_file_pages (sfid, p_fde, p_server_state, image_file_id, file_page_count, status);
          IF status.normal THEN
            total_page_count := total_page_count + file_page_count;
          ELSEIF (status.condition = dfe$no_space_for_server_pages) THEN
            space_available_for_image := FALSE;
            space_available_status := status;
          IFEND;
        IFEND;

        gfp$unlock_fde_p (p_fde);
      END /timeout_server_file_block/;

      gfp$scan_all_fdes (gfc$tr_null_residence, scan_control, p_fde);
    WHILEND;

    STRINGREP (st, stl, file_count, ' Server_File(s) set to Awaiting_Recovery');
    dpp$put_critical_message (st (1, stl), ignore_status);
    core_log_display (st (1, stl));

    STRINGREP (st, stl, total_page_count, ' Server Page(s) saved ');
    dpp$put_critical_message (st (1, stl), ignore_status);
    core_log_display (st (1, stl));

    STRINGREP (st, stl, ' Server image size: ', #OFFSET(image_file_id.
         p_current_eoi):#(16), '(16) bytes');
    dpp$put_critical_message (st (1, stl), ignore_status);
    core_log_display (st (1, stl));

    IF NOT space_available_for_image THEN
      status := space_available_status;
    IFEND;
  PROCEND dfp$r1_timeout_server_files;
?? OLDTITLE ??
?? NEWTITLE := '  deact_term_server_file', EJECT ??

  PROCEDURE deact_term_server_file
    (    system_file_id: gft$system_file_identifier;
         request: mmt$server_segment_request;
     VAR pages_not_deleted: integer;
     VAR status: ost$status);

    VAR
      rb_ring1_server_seg_request: mmt$rb_ring1_server_seg_request;


    status.normal := TRUE;
    pages_not_deleted := 0;
    rb_ring1_server_seg_request.reqcode := syc$rc_ring1_server_seg_request;
    rb_ring1_server_seg_request.request := request;
    rb_ring1_server_seg_request.sfid := system_file_id;
    rb_ring1_server_seg_request.pages_not_deleted := 0;

    i#call_monitor (#LOC (rb_ring1_server_seg_request), #SIZE (rb_ring1_server_seg_request));

    IF rb_ring1_server_seg_request.pages_not_deleted <> 0 THEN
      pages_not_deleted := rb_ring1_server_seg_request.pages_not_deleted;
      osp$set_status_abnormal (dfc$file_server_id, dfe$server_pages_not_deleted, '', status);
    IFEND;

  PROCEND deact_term_server_file;
?? EJECT ??
{
{   This procedure is used during timeout processing to remove pages for files that
{ are merely being read. The mmp$mm_move_mod_server_page interface will
{ remove all pages that are being read even if there are no modified pages.

  PROCEDURE remove_server_file_pages
    (    sfid: gft$system_file_identifier;
         p_fde: gft$file_desc_entry_p);

    VAR
      byte_offset: ost$segment_offset,
      p_dummy_page: ^array [1 .. * ] of char,
      ignore_status: ost$status,
      image_offset: ost$segment_offset,
      st: string (100),
      status: ost$status,
      stl: integer;

    status.normal := TRUE;

    IF p_fde^.asti = 0 THEN
      RETURN;
    IFEND;

{ The following lines of code are (kind of) scary.  If the system is screwed up and we actually end up moving
{ a modified page, rather than removing the unmodified pages, we could really mess up the ring 1 stack.
{ It's happened.
{ Really.

    PUSH p_dummy_page: [1 .. osv$page_size];
    p_dummy_page^ [1] := 'a';

  /remove_all_pages/
    WHILE TRUE DO
      mmp$mm_move_mod_server_page (sfid, p_dummy_page, byte_offset, status);
      IF status.normal THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'UNEXPECTED NORMAL STATUS: SFID = ', sfid.file_entry_index:#(16), '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        osp$system_error ('Unexpected status: file not attached in write and server page moved', NIL);
      ELSEIF status.condition = mme$no_pages_found_for_move THEN

{ Normal, expected status for this call.

        status.normal := TRUE;
        RETURN;
      ELSEIF status.condition = mme$io_active_on_move_page THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'IO ACTIVE: SFID = ', sfid.file_entry_index:#(16), '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        pmp$delay (10000, ignore_status);
      ELSEIF status.condition = mme$page_table_full THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'Page table full: SFID = ', sfid.file_entry_index:#(16), '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        pmp$delay (10000, ignore_status);
      ELSE
        STRINGREP (st, stl, 'Unexpected error: SFID = ', sfid.file_entry_index:#(16),
              '(16), status.condition = ', status.condition:#(16), '(16)');
        core_log_display (st (1, stl));
        dpp$put_critical_message (st (1, stl), ignore_status);
        osp$system_error ('Unexpected status: remove_server_file_pages', NIL);
        RETURN;
      IFEND;
    WHILEND /remove_all_pages/;

  PROCEND remove_server_file_pages;
?? EJECT ??
{  This procedure follows the same basic algorithm as in dfm$manage_image.
{  This procedure assumes the system file table has been locked prior to this
{   call.
{  This procedure saves all pages for the file into the server image file.
{  Even if there are not pages the eoi for the file needs to be sent to the
{  server to be updated over there.

  PROCEDURE save_server_file_pages
    (    sfid: gft$system_file_identifier;
         p_fde: gft$file_desc_entry_p;
         p_server_state: ^dft$server_state;
     VAR image_file_id: dft$image_file_id;
     VAR page_count: integer;
     VAR status: ost$status);

    VAR
      byte_offset: ost$segment_offset,
      ignore_status: ost$status,
      image_offset: ost$segment_offset,
      p_page_header: ^dft$image_page_header,
      p_file_header: ^dft$image_file_header,
      st: string (100),
      stl: integer;

    page_count := 0;
    NEXT p_file_header IN image_file_id.p_current_block_seq;
    IF p_file_header = NIL THEN
      dfp$get_next_image_block (image_file_id, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;
      NEXT p_file_header IN image_file_id.p_current_block_seq;
    IFEND;

    p_file_header^.file_completed := FALSE;
    dfp$uncomplement_gfn (p_fde^.global_file_name, p_file_header^.global_file_name);
    p_file_header^.eoi_byte_address := p_fde^.eoi_byte_address;
    p_file_header^.page_count := 0;
    p_file_header^.highest_file_offset := 0;
    image_file_id.p_current_block_header^.file_count := image_file_id.p_current_block_header^.file_count + 1;
    status.normal := TRUE;
    IF dfv$file_server_debug_enabled THEN
      STRINGREP (st, stl, 'SFID = ', sfid.file_entry_index:#(16), '(16), ',
            p_fde^.global_file_name.hour, ':', p_fde^.global_file_name.minute, ':',
            p_fde^.global_file_name.second,
            ', Seq# = ', p_fde^.global_file_name.sequence_number);
      core_log_display (st (1, stl));
      dpp$put_critical_message (st (1, stl), ignore_status);
    IFEND;

    IF p_fde^.asti = 0 THEN
      p_file_header^.file_completed := TRUE;
      RETURN;
    IFEND;

   syp$core_hang_if_system_jrt_set (dfc$tjr_halt_save_server_image);

  /copy_all_pages/
    WHILE TRUE DO
      IF p_server_state^ <> dfc$awaiting_recovery THEN
        { State change has occurred to go to terminated. Get out of here.
         osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated, '', status);
         RETURN;
      IFEND;
      dfp$expand_image_file (image_file_id, status);
      IF NOT status.normal THEN
        IF (status.condition = dfe$no_space_for_server_pages) THEN
         { If we mark this file as not complete it will be terminated on the
         {    the next activation from the awaiting recovery state.
         {    Even despite this error the files pages are still in memory.
         { If terminate_system occurs all files for the server will be terminated if we
         {    were not not able to save pages.
         { If the client crashes the pages are still in memory and will be recovered
         {    at that time is there is sufficient disk space on the client.
           p_file_header^.file_completed := TRUE;
        IFEND;
        RETURN;
      IFEND;
      mmp$mm_move_mod_server_page (sfid, image_file_id.p_current_eoi, byte_offset,
            status);
      IF status.normal THEN
        image_offset := #OFFSET (image_file_id.p_current_eoi);
        image_file_id.p_current_eoi := #ADDRESS (#RING (image_file_id.p_current_eoi),
              #SEGMENT (image_file_id.p_current_eoi), #OFFSET (image_file_id.p_current_eoi) + osv$page_size);
        image_file_id.p_image_header^.current_eoi := #OFFSET (image_file_id.p_current_eoi);
        NEXT p_page_header IN image_file_id.p_current_block_seq;
        IF p_page_header = NIL THEN
         dfp$get_next_image_block (image_file_id, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
          NEXT p_page_header IN image_file_id.p_current_block_seq;
        IFEND;
        p_page_header^.file_offset := byte_offset;
        p_page_header^.image_offset := image_offset;
        image_file_id.p_current_block_header^.page_count :=
              image_file_id.p_current_block_header^.page_count + 1;
        page_count := page_count + 1;
        p_file_header^.page_count := p_file_header^.page_count + 1;
        IF byte_offset > p_file_header^.highest_file_offset THEN
          p_file_header^.highest_file_offset := byte_offset;
        IFEND;
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'SFID', sfid.file_entry_index:#(16), '(16): pg #',
                p_file_header^.page_count, ', offset', byte_offset:#(16), '(16), image', image_offset:#(16),
                '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        CYCLE /copy_all_pages/;
      ELSEIF status.condition = mme$io_active_on_move_page THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'IO ACTIVE: SFID = ', sfid.file_entry_index:#(16), '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        pmp$delay (10000, ignore_status);
        CYCLE /copy_all_pages/;
      ELSEIF status.condition = mme$page_table_full THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'Page table full: SFID = ', sfid.file_entry_index:#(16), '(16)');
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        pmp$delay (10000, ignore_status);
        CYCLE /copy_all_pages/;
      ELSEIF status.condition = mme$no_pages_found_for_move THEN
        IF dfv$file_server_debug_enabled THEN
          STRINGREP (st, stl, 'File Complete: SFID = ', sfid.file_entry_index:#(16), '(16), Highest offset: ',
               p_file_header^.highest_file_offset);
          core_log_display (st (1, stl));
          dpp$put_critical_message (st (1, stl), ignore_status);
        IFEND;
        status.normal := TRUE;
        EXIT /copy_all_pages/;
      ELSE
        STRINGREP (st, stl, 'Unexpected error: SFID = ', sfid.file_entry_index:#(16),
              '(16), status.condition = ', status.condition:#(16), '(16)');
        core_log_display (st (1, stl));
        dpp$put_critical_message (st (1, stl), ignore_status);
        RETURN;
      IFEND;
    WHILEND /copy_all_pages/;

    p_file_header^.file_completed := TRUE;
  PROCEND save_server_file_pages;
?? OLDTITLE, OLDTITLE ??
MODEND dfm$recovery_services;
