?? RIGHT := 110 ??
*copy osd$default_pragmats
?? NEWTITLE := 'NOS/VE Device Management' ??
MODULE dmm$recover_mainframe;
?? RIGHT := 110 ??

{ PURPOSE:
{
{   The purpose of this module is to activate and recover mass storage volumes.
{
{ DESIGN:
{
{   When a volume is activated, it is logged in for recovery or production
{   based on whether recovery is required.  Procedure dmp$recover_mainframe
{   recovers all volumes in the active volume table that are logged in for
{   recovery.  Once recovery is complete, the volume's login type is switched
{   from recovery to production.  During deadstart, an image will be used if
{   it is available.
{
{   Procedure dmp$get_volume_active brings a volume online, activates it and
{   recovers it by calling dmp$recover_mainframe if dmp$recover_mainframe has
{   been called before.  The first call to dmp$recover_mainframe occurs during
{   deadstart after the initial configuration is activated.  Thus, all volumes
{   that are activated initially during deadstart are all recovered as a
{   group.  Subsequently recovery of of a volume occurs as it is activated.

?? PUSH (LISTEXT := ON) ??
?? NEWTITLE := '  Common Decks', EJECT ??
*copyc dmt$error_condition_codes
*copyc dmt$old_image_pointers
*copyc dpt$critical_window_date_time
*copyc gft$scan_all_fdes_state
*copyc ost$status
?? POP ??
*copyc i#build_adaptable_array_ptr
*copyc i#build_adaptable_seq_pointer
*copyc clp$put_job_output
*copyc cmp$get_element_name_via_lun
*copyc cmp$search_active_volume_table
*copyc dmp$activate_volume
*copyc dmp$add_to_sorted_dfl
*copyc dmp$attach_device_file
*copyc dmp$close_file
*copyc dmp$detach_device_file
*copyc dmp$evacuate_active_device_log
*copyc dmp$evacuate_old_device_log
*copyc dmp$fixup_fmd_allocated_length
*copyc dmp$get_disk_file_descriptor_p
*copyc dmp$get_fau_entry
*copyc dmp$get_level_1_ptr
*copyc dmp$get_level_2_ptr
*copyc dmp$get_physical_attributes
*copyc dmp$open_dflt
*copyc dmp$open_directory
*copyc dmp$open_login_table
*copyc dmp$recover_file
*copyc dmp$recover_volume
*copyc dmp$retrieve_allocation_info
*copyc dmp$return_dat_entries
*copyc dmp$return_dfl_entries
*copyc dmp$return_mat_space
*copyc dmp$search_login_table
*copyc dmp$search_vol_directory_name
*copyc dmp$set_eoi
*copyc dmp$start_volume_production
*copyc dmp$take_volume_offline
*copyc dmp$volume_online
*copyc dsp$fetch_list_block
*copyc dsp$get_nve_image_description
*copyc dsp$store_list_block
*copyc gfp$count_all_fdes_in_image
*copyc gfp$get_fde_p
*copyc gfp$scan_all_fdes_in_image
*copyc osp$get_status_condition_string
*copyc osp$set_status_abnormal
*copyc pmp$binary_to_ascii_fit
*copyc pmp$convert_binary_unique_name
*copyc pmp$get_date
*copyc pmp$get_legible_date_time
*copyc pmp$get_time
*copyc pmp$log_ascii
*copyc syp$set_mainframe_recovered
*copyc dmv$active_volume_table
*copyc dmv$allocation_log
*copyc dmv$display_recovery_messages
*copyc dmv$ds_msg_update_interval
*copyc dmv$mainframe_recovered
*copyc dmv$system_device_information
*copyc dsv$actual_deadstart_phase
*copyc gfv$null_sfid
*copyc osv$deadstart_phase
*copyc syv$detailed_critical_displays
*copyc syv$job_recovery_option

*if $true(osv$ff_debug_code)

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

*ifend
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    second = 1000000;

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

  PROCEDURE [XDCL, #GATE] dmp$get_old_image_pointers
    (VAR old_image_pointers: dmt$old_image_pointers;
     VAR image_available: boolean);

    VAR
      descriptor: dst$nve_image_descriptor,
      old_wired_segment: ost$segment,
      p_image_pointers: ^dmt$old_image_pointers,
      p_list_block: ^SEQ ( * ),
      paa: ^^cell;

    image_available := FALSE;
    old_image_pointers.old_image_status := dmc$old_image_not_available;
    old_image_pointers.old_allocation_log_info := NIL;
    old_image_pointers.p_avt_pointer := NIL;
    old_image_pointers.old_wired_segment := 0;
    dsp$get_nve_image_description (descriptor);

    IF (descriptor.rcv_mainframe_wired_segment <> NIL) AND (osv$deadstart_phase = osc$recovery_deadstart) THEN
      dsp$fetch_list_block (dsc$device_management, p_list_block);
      IF (p_list_block <> NIL) AND (#SIZE (p_list_block^) = #SIZE (old_image_pointers)) THEN
        old_wired_segment := #SEGMENT (descriptor.rcv_mainframe_wired_segment);
        i#build_adaptable_seq_pointer (1, old_wired_segment, #OFFSET (p_list_block), #SIZE (p_list_block^), 0,
              p_list_block);
        RESET p_list_block;
        NEXT p_image_pointers IN p_list_block;
        old_image_pointers := p_image_pointers^;
        old_image_pointers.old_wired_segment := old_wired_segment;
        old_image_pointers.old_allocation_log_info := #ADDRESS (1, old_wired_segment,
              #OFFSET (old_image_pointers.old_allocation_log_info));
        old_image_pointers.p_avt_pointer := #ADDRESS (1, old_wired_segment,
              #OFFSET (old_image_pointers.p_avt_pointer));
        image_available := old_image_pointers.old_image_status = dmc$old_image_available;
      IFEND;
    IFEND;

  PROCEND dmp$get_old_image_pointers;
?? TITLE := '  dmp$get_volume_active', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$get_volume_active
    (    lun: iot$logical_unit;
         pid: cmt$product_identification;
     VAR status: ost$status);

    VAR
      avt_entry_not_found: boolean,
      element_name: cmt$element_name,
      ignore_status: ost$status,
      message: string (dpc$date_time_size + 40),
      p_physical_attributes: ^dmt$physical_device_attributes,
      recorded_vsn: rmt$recorded_vsn,
      search_key: dmt$avt_search_key;

?? NEWTITLE := '  p$put_job_output_message', EJECT ??

    PROCEDURE p$put_job_output_message
      (    lun: iot$logical_unit;
           message1: string ( * <= 40);
           vsn: string ( * <= rmc$recorded_vsn_size);
           min_detailed_crit_display_value: syt$detailed_critical_displays);

      CONST
        c$max_displayed_element_name = 18;

      VAR
        date: ost$date,
        date_time_string: dpt$critical_window_date_time,
        i: integer,
        ignore_status: ost$status,
        local_element_name: string (c$max_displayed_element_name),
        message_line: string (80),
        time: ost$time;

      IF syv$detailed_critical_displays < min_detailed_crit_display_value THEN
        RETURN; {----->
      IFEND;

      time.time_format := osc$hms_time;
      pmp$get_time (time.time_format, time, ignore_status);
      date.date_format := osc$mdy_date;
      pmp$get_date (date.date_format, date, ignore_status);
      date_time_string.string_part := ' ';
      date_time_string.hms := time.hms;
      date_time_string.mdy := date.mdy;

      IF lun = 0 THEN
        local_element_name := element_name;
        IF element_name (c$max_displayed_element_name) <> ' ' THEN
          local_element_name (c$max_displayed_element_name - 1, 2) := '..';
        IFEND;

        STRINGREP (message_line, i, ' ', message1, ' ', element_name, ' as ', vsn, ' at ',
              date_time_string.string_part);
      ELSE
        STRINGREP (message_line, i, ' ', date_time_string.string_part, ' LUN= ', lun, ' ', message1, ' ',
              vsn);
      IFEND;
      clp$put_job_output (message_line (1, i), ignore_status);

    PROCEND p$put_job_output_message;
?? OLDTITLE ??
?? EJECT ??

    status.normal := TRUE;

    IF lun = dmv$system_device_lun THEN
      RETURN; {----->
    IFEND;

    p$put_job_output_message (lun, 'DMP$GET_VOLUME_ACTIVE Enter', '', syc$dcd_trace_vol_act_deact_2);

    PUSH p_physical_attributes: [1 .. 8];
    p_physical_attributes^ [1].keyword := dmc$bytes_per_mau;
    p_physical_attributes^ [2].keyword := dmc$cylinders_per_device;
    p_physical_attributes^ [3].keyword := dmc$maus_per_cylinder;
    p_physical_attributes^ [4].keyword := dmc$maus_per_dau;
    p_physical_attributes^ [5].keyword := dmc$sectors_per_mau;
    p_physical_attributes^ [6].keyword := dmc$sectors_per_track;
    p_physical_attributes^ [7].keyword := dmc$flaw_map_locations;
    p_physical_attributes^ [8].keyword := dmc$pda_max_label_size;

    cmp$get_element_name_via_lun (lun, element_name, ignore_status);
    IF NOT ignore_status.normal THEN
      element_name := '';
    IFEND;

    dmp$get_physical_attributes (pid, p_physical_attributes, status);
    IF status.normal THEN
      dmp$volume_online (lun, p_physical_attributes, status);
      IF status.normal THEN
        search_key.value := dmc$search_avt_by_lun;
        search_key.logical_unit_number := lun;
        cmp$search_active_volume_table (search_key, recorded_vsn, avt_entry_not_found);
        IF NOT avt_entry_not_found THEN
          p$put_job_output_message (0 {= no lun} , 'ACTIVATING', recorded_vsn, syc$dcd_no_detailed_screen);
        IFEND;
        dmp$activate_volume (lun, status);
        IF NOT status.normal THEN
          dmp$take_volume_offline (lun, ignore_status);
        IFEND;
      IFEND;
    IFEND;

    { If mainframe recovery has already occurred, it must be repeated as each
    { volume is activated so that recovery of the volume can take place.

    IF status.normal AND dmv$mainframe_recovered THEN
      p$put_job_output_message (lun, 'DMP$RECOVER_MAINFRAME', recorded_vsn, syc$dcd_trace_vol_act_deact_2);
      dmp$recover_mainframe (status);
      IF status.normal THEN
        p$put_job_output_message (lun, 'DMP$ADD_TO_SORTED_DFL', recorded_vsn, syc$dcd_trace_vol_act_deact_2);
        dmp$add_to_sorted_dfl (lun, status);
      IFEND;
    IFEND;

    IF syv$detailed_critical_displays >= syc$dcd_trace_vol_act_deact_2 THEN
      p$put_job_output_message (lun, 'DMP$GET_VOLUME_ACTIVE Exit', recorded_vsn,
            syc$dcd_trace_vol_act_deact_2);
    IFEND;

  PROCEND dmp$get_volume_active;
?? TITLE := '  dmp$issue_message_to_ascii_log', EJECT ??

  PROCEDURE [XDCL] dmp$issue_message_to_ascii_log
    (    msg_string: pmt$log_msg_text;
         write_message_to_job_output: boolean);

    VAR
      ignore_status: ost$status;

    IF write_message_to_job_output THEN
      clp$put_job_output (msg_string, ignore_status);
    IFEND;

    pmp$log_ascii (msg_string, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_recovery,
          ignore_status);

  PROCEND dmp$issue_message_to_ascii_log;
?? TITLE := '  dmp$log_abnormal_status', EJECT ??

  PROCEDURE [XDCL] dmp$log_abnormal_status
    (VAR status: ost$status);

    VAR
      condition_string: ost$string,
      current_string_position: integer,
      error_condition_length: integer,
      ignore_status: ost$status,
      msg_string: string (100);

    current_string_position := 2; { otherwise we cut the first character when we output to the console
    msg_string := '';
    osp$get_status_condition_string (status.condition, condition_string, ignore_status);
    msg_string (current_string_position, * ) := condition_string.value (1, condition_string.size);
    current_string_position := current_string_position + condition_string.size + 1;
    msg_string (current_string_position, status.text.size) := status.text.value;
    current_string_position := current_string_position + status.text.size + 1;

    dmp$issue_message_to_ascii_log (msg_string (1, current_string_position), TRUE);

  PROCEND dmp$log_abnormal_status;
?? TITLE := '  dmp$recover_mainframe', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$recover_mainframe
    (VAR status: ost$status);

    VAR
      image_available: boolean,
      msg_string: string (40),
      old_image_pointers: ^dmt$old_image_pointers;

    status.normal := TRUE;

    PUSH old_image_pointers;

    IF dsv$actual_deadstart_phase = osc$recovery_deadstart THEN
      msg_string := '  Recovering without an image file';
    ELSE
      msg_string := '  Recovery not necessary';
    IFEND;

    dmp$get_old_image_pointers (old_image_pointers^, image_available);
    IF image_available THEN
      msg_string := '  Recovering with an image file';
    IFEND;

    pmp$log_ascii (msg_string, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_recovery,
          status);

    clp$put_job_output (msg_string, status);

    return_old_mat_space (old_image_pointers^);

    recover_logs (old_image_pointers^, status);

    IF status.normal THEN
      recover_files (old_image_pointers^, status);
    IFEND;

    IF status.normal THEN
      recover_volumes (status);
    IFEND;

    IF status.normal THEN
      start_volume_production (status);
    IFEND;

    syp$set_mainframe_recovered (TRUE);

    IF NOT status.normal THEN
      dmp$log_abnormal_status (status);
    IFEND;

  PROCEND dmp$recover_mainframe;
?? TITLE := '  dmp$save_recovery_info', EJECT ??

  PROCEDURE [XDCL, #GATE] dmp$save_recovery_info;

    VAR
      old_image_pointers: dmt$old_image_pointers;

    old_image_pointers.old_image_status := dmc$old_image_available;
    old_image_pointers.old_allocation_log_info := ^dmv$allocation_log;
    old_image_pointers.p_avt_pointer := ^dmv$active_volume_table.table_p;
    dsp$store_list_block (dsc$device_management, #SEQ (old_image_pointers));

  PROCEND dmp$save_recovery_info;
?? TITLE := '  get_recovery_id', EJECT ??

  PROCEDURE get_recovery_id
    (    avt_index: dmt$active_volume_table_index;
     VAR mainframe_assigned: dmt$mainframe_assigned);

    VAR
      p_login_table: ^dmt$ms_mainframe_login_table,
      login_index: dmt$login_table_entries,
      status: ost$status;

    mainframe_assigned.log_in_sequence := 0;
    mainframe_assigned.log_in_index := 1;

    dmp$open_login_table (dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_login_table,
          osc$os_ring_1, osc$tsrv_ring, mmc$sar_read, mmc$as_sequential, p_login_table, status);

    IF status.normal THEN
      dmp$search_login_table (p_login_table, dmc$production_login_entry, login_index);

      IF (login_index <> 0) THEN
        mainframe_assigned := p_login_table^.body [login_index].mainframe_assigned;
      IFEND;

      dmp$close_file (p_login_table, status);
    IFEND;

  PROCEND get_recovery_id;
?? TITLE := '  locate_avt_entry', EJECT ??

  PROCEDURE [INLINE] locate_avt_entry
    (    p_avt: ^dmt$active_volume_table_entries;
         internal_vsn: dmt$internal_vsn;
     VAR avt_index: dmt$active_volume_table_index);

    VAR
      index: dmt$active_volume_table_index;

    FOR index := LOWERBOUND (p_avt^) TO UPPERBOUND (p_avt^) DO
      IF NOT p_avt^ [index].entry_available THEN
        IF p_avt^ [index].mass_storage.internal_vsn = internal_vsn THEN
          avt_index := index;
          RETURN; {----->
        IFEND;
      IFEND;
    FOREND;

    avt_index := 0;

  PROCEND locate_avt_entry;
?? TITLE := '  locate_next_volume', EJECT ??

  PROCEDURE [INLINE] locate_next_volume
    (VAR avt_index: dmt$active_volume_table_index);

    WHILE (avt_index < UPPERBOUND (dmv$active_volume_table.table_p^)) DO
      avt_index := avt_index + 1;

      IF NOT dmv$active_volume_table.table_p^ [avt_index].entry_available AND
            dmv$active_volume_table.table_p^ [avt_index].mass_storage.logged_in_for_recovery THEN
        RETURN; {----->
      IFEND;
    WHILEND;

    avt_index := 0;

  PROCEND locate_next_volume;
?? TITLE := '  recover_files', EJECT ??

  PROCEDURE recover_files
    (    old_image_pointers: dmt$old_image_pointers;
     VAR status: ost$status);

    VAR
      avt_index: dmt$active_volume_table_index,
      base: integer,
      clock: integer,
      date: ost$date,
      dfd_p: ^dmt$disk_file_descriptor,
      display_update_interval: integer,
      fde_p: gft$file_desc_entry_p,
      fdes_scanned: integer,
      image_segment: ost$segment,
      local_status: ost$status,
      msg_string: string (81),
      msg_string_length: integer,
      pages_written_total: integer,
      pages_written_new: integer,
      pages_written: integer,
      permanent_files_not_recovered: integer,
      permanent_files_recovered: integer,
      scan_control: gft$scan_all_fdes_state,
      time: ost$time,
      total_fde_count: integer;

?? NEWTITLE := 'P$LOG_ABNORMAL_STATUS', EJECT ??

    PROCEDURE p$log_abnormal_status
      (    global_file_name: ost$binary_unique_name;
       VAR status: ost$status);

      VAR
        condition_string: ost$string,
        current_string_position: integer,
        error_condition_length: integer,
        ignore_status: ost$status,
        msg_string: string (100),
        name: ost$name;

      current_string_position := 2; { otherwise we cut the first character when we output to the console
      msg_string := '';
      pmp$convert_binary_unique_name (global_file_name, name, ignore_status);
      msg_string (current_string_position, osc$max_name_size) := name;
      current_string_position := current_string_position + osc$max_name_size + 1;
      msg_string (current_string_position, 1) := '-';
      current_string_position := current_string_position + 2;
      osp$get_status_condition_string (status.condition, condition_string, ignore_status);
      msg_string (current_string_position, * ) := condition_string.value (1, condition_string.size);
      current_string_position := current_string_position + condition_string.size + 1;
      msg_string (current_string_position, status.text.size) := status.text.value;
      current_string_position := current_string_position + status.text.size + 1;

      dmp$issue_message_to_ascii_log (msg_string (1, current_string_position), TRUE);

    PROCEND p$log_abnormal_status;
?? OLDTITLE ??
?? EJECT ??

    status.normal := TRUE;
    permanent_files_recovered := 0;
    permanent_files_not_recovered := 0;
    pages_written_total := 0;
    pages_written_new := 0;
    pages_written := 0;

    IF old_image_pointers.old_image_status = dmc$old_image_available THEN

      image_segment := old_image_pointers.old_wired_segment;

      base := 0;
      display_update_interval := dmv$ds_msg_update_interval * second;
      fdes_scanned := 0;

      IF dmv$display_recovery_messages THEN

        {We first count all FDEs in use to get the operator an idea of how long recovery may take.
        total_fde_count := gfp$count_all_fdes_in_image (image_segment);
        pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);

        STRINGREP (msg_string, msg_string_length, ' .. Scanning FDEs: Total Number of FDEs in use: ',
              total_fde_count, '   ', time.hms);
        dmp$issue_message_to_ascii_log (msg_string (1, msg_string_length), dmv$display_recovery_messages);

        dmp$issue_message_to_ascii_log (
              '  .. Time   FDEs:  Scanned  Recoverd     Unrec     Total   Pages-Written',
              dmv$display_recovery_messages);
      IFEND;

      gfp$scan_all_fdes_in_image (image_segment, scan_control, fde_p);
      WHILE fde_p <> NIL DO

      /recover_file/
        BEGIN

          IF fde_p^.media <> gfc$fm_mass_storage_file THEN
            EXIT /recover_file/; {----->
          IFEND;

          IF (fde_p^.file_kind <> gfc$fk_job_permanent_file) AND (fde_p^.file_kind <> gfc$fk_catalog) THEN
            EXIT /recover_file/; {----->
          IFEND;

          IF fde_p^.attached_in_write_count < 1 THEN
            EXIT /recover_file/; {----->
          IFEND;

          dmp$get_disk_file_descriptor_p (fde_p, dfd_p);
          IF dfd_p^.purged THEN
            EXIT /recover_file/; {----->
          IFEND;

          dmp$recover_file (fde_p, pages_written, status);
          IF NOT status.normal THEN
            p$log_abnormal_status (fde_p^.global_file_name, status);
            CASE status.condition OF
            = dme$unable_to_attach_for_rec =
              permanent_files_not_recovered := permanent_files_not_recovered + 1;
              status.normal := TRUE;
              EXIT /recover_file/; {----->
            = dme$rf_no_vol_assigned_to_file =
              status.normal := TRUE;
              EXIT /recover_file/; {----->
            ELSE
              status.normal := TRUE;
              EXIT /recover_file/; {----->
            CASEND;
          IFEND;

          pages_written_total := pages_written_total + pages_written;
          permanent_files_recovered := permanent_files_recovered + 1;
        END /recover_file/;

        IF dmv$display_recovery_messages THEN
          fdes_scanned := fdes_scanned + 1;

          clock := #FREE_RUNNING_CLOCK (0);
          IF clock > (base + display_update_interval) THEN
            base := clock;
            pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
            msg_string := ' .. ';
            msg_string (5, 8) := time.hms;
            pmp$binary_to_ascii_fit (fdes_scanned, 10, 7, 7, msg_string (19, 7));
            pmp$binary_to_ascii_fit (permanent_files_recovered, 10, 7, 7, msg_string (29, 7));
            pmp$binary_to_ascii_fit (permanent_files_not_recovered, 10, 7, 7, msg_string (39, 7));
            pmp$binary_to_ascii_fit (total_fde_count, 10, 7, 7, msg_string (49, 7));
            pmp$binary_to_ascii_fit (pages_written_total - pages_written_new, 10, 9, 9, msg_string (63, 9));

            pages_written_new := pages_written_total;
            dmp$issue_message_to_ascii_log (msg_string (1, 78), dmv$display_recovery_messages);
          IFEND;
        IFEND;

        gfp$scan_all_fdes_in_image (0 {segment_number} , scan_control, fde_p);
      WHILEND;

      STRINGREP (msg_string, msg_string_length, permanent_files_recovered);
      msg_string (msg_string_length + 1, 28) := ' PERMANENT FILE(S) RECOVERED';

      dmp$issue_message_to_ascii_log (msg_string (1, 28 + msg_string_length), dmv$display_recovery_messages);

      STRINGREP (msg_string, msg_string_length, permanent_files_not_recovered);
      msg_string (msg_string_length + 1, 32) := ' PERMANENT FILE(S) NOT RECOVERED';

      dmp$issue_message_to_ascii_log (msg_string (1, 32 + msg_string_length), dmv$display_recovery_messages);

      STRINGREP (msg_string, msg_string_length, ' Total Number of Pages Recovered: ', pages_written_total);
      dmp$issue_message_to_ascii_log (msg_string (1, msg_string_length), dmv$display_recovery_messages);


      { Flush device logs for all volumes not being recovered.  This is done to make sure that
      { any files that were attached for recovery get their file table entries deleted before they
      { can interfere with the automatic reconciliation that takes place later between Permanent
      { File Manager and Device Manager. Volumes being recovered shouldn't be done here because
      { they will be flushed as part of their recovery process.

      FOR avt_index := LOWERBOUND (dmv$active_volume_table.table_p^)
            TO UPPERBOUND (dmv$active_volume_table.table_p^) DO
        IF NOT dmv$active_volume_table.table_p^ [avt_index].entry_available AND
              NOT dmv$active_volume_table.table_p^ [avt_index].mass_storage.logged_in_for_recovery AND
              (dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_device_log <> gfv$null_sfid) THEN
          dmp$evacuate_active_device_log (avt_index, local_status);
        IFEND;
      FOREND;
    IFEND;

  PROCEND recover_files;
?? TITLE := '  recover_log', EJECT ??

  PROCEDURE recover_log
    (    old_image_pointers: dmt$old_image_pointers;
         avt_index: dmt$active_volume_table_index;
     VAR status: ost$status);

*if $true(osv$ff_debug_code)

    VAR
      kill_p: ^cell,
      stop: cell;

*ifend

    VAR
      p_login_table: ^dmt$ms_mainframe_login_table,
      lt_entry_index: dmt$login_table_entries,
      close_status: ost$status;

    status.normal := TRUE;

    dmp$open_login_table (dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_login_table,
          osc$os_ring_1, osc$tsrv_ring, mmc$sar_read, mmc$as_sequential, p_login_table, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

  /login_table_open/
    BEGIN

      dmp$search_login_table (p_login_table, dmc$production_login_entry, lt_entry_index);

      IF (lt_entry_index = 0) OR (lt_entry_index = dmv$active_volume_table.table_p^ [avt_index].mass_storage.
            mainframe_assigned.log_in_index) THEN
        EXIT /login_table_open/; {----->
      IFEND;

      IF old_image_pointers.old_image_status = dmc$old_image_available THEN
        recover_log_with_image (old_image_pointers, p_login_table^.body [lt_entry_index].device_log_name,
              avt_index, p_login_table, lt_entry_index, status);
        IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
          IF osv$debug [1] <> 0 THEN
            kill_p := NIL;
            stop := kill_p^;
          IFEND;
*ifend
          EXIT /login_table_open/; {----->
        IFEND;
      ELSE
        recover_log_without_image (p_login_table^.body [lt_entry_index].device_log_name, avt_index,
              p_login_table, lt_entry_index, status);
        IF NOT status.normal THEN
          EXIT /login_table_open/; {----->
        IFEND;
      IFEND;

      IF syv$job_recovery_option <> syc$jre_enabled THEN
        dmp$return_dat_entries (dmv$active_volume_table.table_p^ [avt_index].mass_storage.mainframe_assigned,
              avt_index, dmc$return_all_except_entry, status);
        IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
          IF osv$debug [1] <> 0 THEN
            kill_p := NIL;
            stop := kill_p^;
          IFEND;
*ifend
          EXIT /login_table_open/; {----->
        IFEND;
      IFEND;

      dmp$return_dfl_entries (p_login_table^.body [lt_entry_index].mainframe_assigned, avt_index, status);
      IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
        IF osv$debug [1] <> 0 THEN
          kill_p := NIL;
          stop := kill_p^;
        IFEND;
*ifend
        EXIT /login_table_open/; {----->
      IFEND;

    END /login_table_open/;

    dmp$close_file (p_login_table, close_status);
    IF status.normal THEN
      status := close_status;
    IFEND;

  PROCEND recover_log;
?? TITLE := '  recover_log_with_image', EJECT ??

  PROCEDURE recover_log_with_image
    (    old_image_pointers: dmt$old_image_pointers;
         old_device_log_name: ost$name;
         avt_index: dmt$active_volume_table_index;
         p_login_table: ^dmt$ms_mainframe_login_table;
         lt_entry_index: dmt$login_table_entries;
     VAR status: ost$status);

*if $true(osv$ff_debug_code)

    VAR
      kill_p: ^cell,
      stop: cell;

*ifend

    VAR
      old_log_index: dmt$directory_index,
      old_log_found: boolean,
      p_directory: ^dmt$ms_volume_directory,
      old_log_global_file_name: dmt$global_file_name,
      image_segment: ost$segment,
      old_device_log_sfid: gft$system_file_identifier,
      old_allocation_log: ^dmt$allocation_log_info,
      scan_control: gft$scan_all_fdes_state,
      file_modified: boolean,
      fmd_modified: boolean,
      fde_p: gft$file_desc_entry_p,
      pages_written: integer,
      local_status: ost$status;

    status.normal := TRUE;
    old_log_index := 0;
    old_log_found := FALSE;

    dmp$search_vol_directory_name (old_device_log_name, dmv$active_volume_table.table_p^ [avt_index].
          mass_storage.p_directory, old_log_index, old_log_found, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

    IF NOT old_log_found THEN
      {! Allow recovery of this volume
      {! if it is being added to the mainframe during this deadstart
      dmp$issue_message_to_ascii_log ('OLD LOG NOT FOUND IN DIRECTORY', TRUE);
      RETURN; {----->
    IFEND;

    dmp$open_directory (dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_directory, osc$os_ring_1,
          osc$tsrv_ring, mmc$sar_read, mmc$as_sequential, p_directory, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

    old_log_global_file_name := p_directory^.entries [old_log_index].global_file_name;

    dmp$close_file (p_directory, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

    old_log_found := FALSE;
    image_segment := old_image_pointers.old_wired_segment;

    gfp$scan_all_fdes_in_image (image_segment, scan_control, fde_p);

  /search_for_old_log/
    WHILE fde_p <> NIL DO
      IF fde_p^.global_file_name = old_log_global_file_name THEN
        old_log_found := TRUE;
        EXIT /search_for_old_log/; {----->
      IFEND;
      gfp$scan_all_fdes_in_image (0, scan_control, fde_p);
    WHILEND /search_for_old_log/;

    IF NOT old_log_found THEN
      {! Allow recovery of this volume
      {! if it is being added to the mainframe during this deadstart
      dmp$issue_message_to_ascii_log ('OLD LOG NOT FOUND IN MEMORY IMAGE', TRUE);
      {! Recover log as if no image present to clean up old log
      recover_log_without_image (old_device_log_name, avt_index, p_login_table, lt_entry_index, status);
      RETURN; {----->
    IFEND;

    IF p_login_table^.body [lt_entry_index].recovery_status = dmc$lt_being_recovered THEN
      dmp$recover_file (fde_p, pages_written, status);
      IF NOT status.normal THEN
        CASE status.condition OF
        = dme$rf_no_vol_assigned_to_file =
          status.normal := TRUE;
        = dme$volume_not_online =
          status.normal := TRUE;
        = dme$unknown_device_file =
          status.normal := TRUE;
        = dme$unable_to_attach_for_rec =
          status.normal := TRUE;
        ELSE
*if $true(osv$ff_debug_code)
          IF osv$debug [1] <> 0 THEN
            kill_p := NIL;
            stop := kill_p^;
          IFEND;
*ifend
          RETURN; {----->
        CASEND;
      IFEND;

      dmp$evacuate_active_device_log (avt_index, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;

    IFEND;

    dmp$attach_device_file (dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn,
          p_login_table^.body [lt_entry_index].device_log_name, old_device_log_sfid, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

    IF p_login_table^.body [lt_entry_index].recovery_status = dmc$lt_being_rec_alloc_complete THEN
      old_allocation_log := NIL;
    ELSE
      old_allocation_log := old_image_pointers.old_allocation_log_info;
    IFEND;

  /old_log_attached/
    BEGIN
      update_eoi (old_device_log_sfid, status);

      IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
        IF osv$debug [1] <> 0 THEN
          kill_p := NIL;
          stop := kill_p^;
        IFEND;
*ifend
        EXIT /old_log_attached/; {----->
      IFEND;

      dmp$evacuate_old_device_log (avt_index, p_login_table^.body [lt_entry_index].mainframe_assigned,
            dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_login_table, old_device_log_sfid,
            old_allocation_log, status);
      IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
        IF osv$debug [1] <> 0 THEN
          kill_p := NIL;
          stop := kill_p^;
        IFEND;
*ifend
        EXIT /old_log_attached/; {----->
      IFEND;

    END /old_log_attached/;
    dmp$detach_device_file (old_device_log_sfid, file_modified, fmd_modified, local_status);
    IF (NOT local_status.normal) AND status.normal THEN
      status := local_status;
    IFEND;

  PROCEND recover_log_with_image;
?? TITLE := '  recover_log_without_image', EJECT ??

  PROCEDURE recover_log_without_image
    (    old_device_log_name: ost$name;
         avt_index: dmt$active_volume_table_index;
         p_login_table: ^dmt$ms_mainframe_login_table;
         lt_entry_index: dmt$login_table_entries;
     VAR status: ost$status);

*if $true(osv$ff_debug_code)

    VAR
      kill_p: ^cell,
      stop: cell;

*ifend

    VAR
      allocated_length: amt$file_byte_address,
      close_status: ost$status,
      detach_status: ost$status,
      dfl_index: dmt$device_file_list_index,
      file_modified: boolean,
      fmd_modified: boolean,
      initialized_length: amt$file_byte_address,
      old_device_log_sfid: gft$system_file_identifier,
      old_log_index: dmt$directory_index,
      old_log_found: boolean,
      p_dflt: ^dmt$ms_device_file_list_table,
      p_dfd: ^dmt$disk_file_descriptor,
      p_fde: ^gft$file_descriptor_entry;

    old_log_index := 0;
    old_log_found := FALSE;

    dmp$search_vol_directory_name (old_device_log_name, dmv$active_volume_table.table_p^ [avt_index].
          mass_storage.p_directory, old_log_index, old_log_found, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

    IF NOT old_log_found THEN
      {! Allow recovery of this volume
      {! if it is being added to the mainframe during this deadstart
      dmp$issue_message_to_ascii_log ('OLD LOG NOT FOUND IN DIRECTORY', TRUE);
      RETURN; {----->
    IFEND;

    dmp$attach_device_file (dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn,
          old_device_log_name, old_device_log_sfid, status);
    IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
      IF osv$debug [1] <> 0 THEN
        kill_p := NIL;
        stop := kill_p^;
      IFEND;
*ifend
      RETURN; {----->
    IFEND;

  /old_log_attached/
    BEGIN
      update_eoi (old_device_log_sfid, status);

      IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
        IF osv$debug [1] <> 0 THEN
          kill_p := NIL;
          stop := kill_p^;
        IFEND;
*ifend
        EXIT /old_log_attached/; {----->
      IFEND;

      dmp$evacuate_old_device_log (avt_index, p_login_table^.body [lt_entry_index].mainframe_assigned,
            dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_login_table, old_device_log_sfid, NIL,
            status);

      IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
        IF osv$debug [1] <> 0 THEN
          kill_p := NIL;
          stop := kill_p^;
        IFEND;
*ifend
        EXIT /old_log_attached/; {----->
      IFEND;

      {   Go back through dat and reflect possible length changes caused by transactions
      {   against old log just processed from old log.

      gfp$get_fde_p (old_device_log_sfid, p_fde);

      dmp$get_disk_file_descriptor_p (p_fde, p_dfd);
      dfl_index := p_dfd^.p_fmd^.dfl_index;

      dmp$open_dflt (dmv$active_volume_table.table_p^ [avt_index].mass_storage.p_device_file_list_table,
            osc$os_ring_1, osc$tsrv_ring, mmc$sar_read, mmc$as_sequential, p_dflt, status);
      IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
        IF osv$debug [1] <> 0 THEN
          kill_p := NIL;
          stop := kill_p^;
        IFEND;
*ifend
        EXIT /old_log_attached/; {----->
      IFEND;

    /dflt_open/
      BEGIN
        dmp$retrieve_allocation_info (^p_dflt^.entries [dfl_index], avt_index, allocated_length,
              initialized_length, status);
        IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
          IF osv$debug [1] <> 0 THEN
            kill_p := NIL;
            stop := kill_p^;
          IFEND;
*ifend
          EXIT /dflt_open/; {----->
        IFEND;

        dmp$fixup_fmd_allocated_length (old_device_log_sfid, 1, allocated_length, status);
        IF NOT status.normal THEN
*if $true(osv$ff_debug_code)
          IF osv$debug [1] <> 0 THEN
            kill_p := NIL;
            stop := kill_p^;
          IFEND;
*ifend
          EXIT /dflt_open/; {----->
        IFEND;

        dmp$set_eoi (old_device_log_sfid, initialized_length, status);
      END /dflt_open/;

      dmp$close_file (p_dflt, close_status);

      IF NOT close_status.normal AND status.normal THEN
        status := close_status;
      IFEND;
    END /old_log_attached/;

    dmp$detach_device_file (old_device_log_sfid, file_modified, fmd_modified, detach_status);

    IF NOT detach_status.normal AND status.normal THEN
      status := detach_status;
    IFEND;

  PROCEND recover_log_without_image;
?? TITLE := '  recover_logs', EJECT ??

  PROCEDURE recover_logs
    (    old_image_pointers: dmt$old_image_pointers;
     VAR status: ost$status);

    VAR
      all_logs_recovered: boolean,
      avt_index: dmt$active_volume_table_index,
      base: integer,
      clock: integer,
      date: ost$date,
      display_update_interval: integer,
      force_output_message: boolean,
      local_status: ost$status,
      msg_string: string (81),
      msg_string_length: integer,
      recorded_vsn: rmt$recorded_vsn,
      recovered_volumes_count: integer,
      time: ost$time,
      unrecovered_volumes_count: integer;

    status.normal := TRUE;
    all_logs_recovered := TRUE;
    recovered_volumes_count := 0;
    unrecovered_volumes_count := 0;
    base := 0;
    display_update_interval := dmv$ds_msg_update_interval * second;

    avt_index := 0;
    REPEAT
      locate_next_volume (avt_index);
      force_output_message := FALSE;

      IF (avt_index <> 0) THEN
        recorded_vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn;

        clock := #FREE_RUNNING_CLOCK (0);
        IF clock > (base + display_update_interval) THEN
          base := clock;
          msg_string (1, 20) := ' RECOVERING LOG FOR ';
          msg_string (21, * ) := recorded_vsn;
          pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
          msg_string (36, * ) := time.hms;
          dmp$issue_message_to_ascii_log (msg_string (1, 43), TRUE);
        IFEND;

{Recover_Log
        recover_log (old_image_pointers, avt_index, status);
        IF NOT status.normal THEN
          force_output_message := TRUE;
          unrecovered_volumes_count := unrecovered_volumes_count + 1;
          dmp$log_abnormal_status (status);
          msg_string (1, 28) := '  UNABLE TO RECOVER LOG FOR ';
          msg_string (29, * ) := recorded_vsn;
        ELSE
          recovered_volumes_count := recovered_volumes_count + 1;
          msg_string (1, 20) := ' RECOVERED LOG FOR ';
          msg_string (21, * ) := recorded_vsn;
        IFEND;

        clock := #FREE_RUNNING_CLOCK (0);
        IF force_output_message OR (clock > (base + display_update_interval)) THEN
          base := clock;
          pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
          msg_string (36, * ) := time.hms;
          dmp$issue_message_to_ascii_log (msg_string (1, 43), TRUE);
        IFEND;

        all_logs_recovered := all_logs_recovered AND status.normal;
      IFEND;
    UNTIL (avt_index = 0);

    IF dmv$display_recovery_messages
{ } AND ((unrecovered_volumes_count <> 0) OR (recovered_volumes_count <> 0)) THEN

      pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
      STRINGREP (msg_string, msg_string_length, ' Volume Logs recovered: ', recovered_volumes_count,
            ', Not Recovered: ', unrecovered_volumes_count, '   ', time.hms);
      dmp$issue_message_to_ascii_log (msg_string (1, msg_string_length), TRUE);
    IFEND;

    IF NOT all_logs_recovered THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$unable_to_recover_all_logs,
            'Unable to recover all logs.', status);
    IFEND;

  PROCEND recover_logs;
?? TITLE := '  recover_volumes', EJECT ??

  PROCEDURE recover_volumes
    (VAR status: ost$status);

    VAR
      all_volumes_recovered: boolean,
      avt_index: dmt$active_volume_table_index,
      date: ost$date,
      local_status: ost$status,
      msg_string: string (50),
      recorded_vsn: rmt$recorded_vsn,
      time: ost$time,
      write_message_to_job_output: boolean;

    status.normal := TRUE;
    all_volumes_recovered := TRUE;

    avt_index := 0;
    REPEAT
      locate_next_volume (avt_index);

      IF (avt_index <> 0) THEN
        recorded_vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn;

        msg_string (1, 12) := ' RECOVERING ';
        msg_string (13, * ) := recorded_vsn;
        pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
        msg_string (36, * ) := time.hms;

        dmp$issue_message_to_ascii_log (msg_string, TRUE);

        dmp$recover_volume (avt_index, status);
        IF NOT status.normal THEN
          dmp$log_abnormal_status (status);
          msg_string (1, 20) := '  UNABLE TO RECOVER ';
          msg_string (21, * ) := recorded_vsn;
          write_message_to_job_output := TRUE;
        ELSE
          msg_string (1, * ) := ' RECOVERED ';
          msg_string (13, * ) := recorded_vsn;
          write_message_to_job_output := dmv$display_recovery_messages;
        IFEND;

        pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
        msg_string (36, * ) := time.hms;
        dmp$issue_message_to_ascii_log (msg_string, write_message_to_job_output);

        all_volumes_recovered := all_volumes_recovered AND status.normal;
      IFEND;
    UNTIL (avt_index = 0);

    IF NOT all_volumes_recovered THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$unable_to_recover_all_vols,
            'Unable to recover all volumes.', status);
    IFEND;

  PROCEND recover_volumes;
?? TITLE := '  return_old_mat_space', EJECT ??

  PROCEDURE return_old_mat_space
    (    old_image_pointers: dmt$old_image_pointers);

    VAR
      avt_index: dmt$active_volume_table_index,
      base: integer,
      clock: integer,
      date: ost$date,
      display_update_interval: integer,
      internal_vsn: dmt$internal_vsn,
      local_status: ost$status,
      mainframe_assigned: dmt$mainframe_assigned,
      msg_string: string (50),
      old_avt_index: dmt$active_volume_table_index,
      old_wired_segment: ost$segment,
      p_old_avt: ^dmt$active_volume_table_entries,
      p_old_mat: cyt$adaptable_array_pointer,
      paa: ^^cell,
      recorded_vsn: rmt$recorded_vsn,
      time: ost$time;

    IF (old_image_pointers.old_image_status <> dmc$old_image_available) THEN
      RETURN; {----->
    IFEND;

    p_old_avt := old_image_pointers.p_avt_pointer^;
    old_wired_segment := #SEGMENT (old_image_pointers.p_avt_pointer);
    paa := #LOC (p_old_avt);
    i#build_adaptable_array_ptr (1, old_wired_segment, #OFFSET (p_old_avt), #SIZE (p_old_avt^),
          LOWERBOUND (p_old_avt^), #SIZE (p_old_avt^ [1]), #LOC (paa^));

    base := 0;
    display_update_interval := dmv$ds_msg_update_interval * second;
    avt_index := 0;

    REPEAT
      locate_next_volume (avt_index);

      IF (avt_index <> 0) THEN

        IF dmv$display_recovery_messages THEN
          clock := #FREE_RUNNING_CLOCK (0);
          IF clock > (base + display_update_interval) THEN
            base := clock;
            recorded_vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn;

            msg_string := ' Recovering MAT Space ';
            msg_string (23, * ) := recorded_vsn;
            pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
            msg_string (36, * ) := time.hms;

            dmp$issue_message_to_ascii_log (msg_string, TRUE);
          IFEND;
        IFEND;

        internal_vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.internal_vsn;
        locate_avt_entry (p_old_avt, internal_vsn, old_avt_index);

        IF (old_avt_index <> 0) THEN
          get_recovery_id (avt_index, mainframe_assigned);
          IF (mainframe_assigned = p_old_avt^ [old_avt_index].mass_storage.mainframe_assigned) THEN
            p_old_mat := p_old_avt^ [old_avt_index].mass_storage.p_mat;
            p_old_mat.pointer := #ADDRESS (1, old_wired_segment, #OFFSET (p_old_mat.pointer));
            dmp$return_mat_space (p_old_mat, mainframe_assigned, avt_index, local_status);
          IFEND;
        IFEND;
      IFEND;
    UNTIL (avt_index = 0);

  PROCEND return_old_mat_space;
?? TITLE := '  start_volume_production', EJECT ??

  PROCEDURE start_volume_production
    (VAR status: ost$status);

    VAR
      avt_index: dmt$active_volume_table_index,
      base: integer,
      clock: integer,
      date: ost$date,
      display_update_interval: integer,
      force_output_message: boolean,
      local_status: ost$status,
      msg_string: string (60),
      production_started: boolean,
      time: ost$time,
      vsn: rmt$recorded_vsn,
      write_message_to_job_output: boolean;

    status.normal := TRUE;
    production_started := TRUE;
    base := 0;
    display_update_interval := dmv$ds_msg_update_interval * second;

    avt_index := 0;
    REPEAT
      locate_next_volume (avt_index);
      force_output_message := FALSE;

      IF (avt_index <> 0) THEN
        vsn := dmv$active_volume_table.table_p^ [avt_index].mass_storage.recorded_vsn;

        clock := #FREE_RUNNING_CLOCK (0);
        IF clock > (base + display_update_interval) THEN
          base := clock;
          msg_string (1, 32) := '  Starting production on volume ';
          msg_string (33, * ) := vsn;
          pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
          msg_string (40, * ) := time.hms;
          dmp$issue_message_to_ascii_log (msg_string, dmv$display_recovery_messages);
        IFEND;

        dmp$start_volume_production (avt_index, status);

        IF NOT status.normal THEN
          dmp$log_abnormal_status (status);
          msg_string (1, 39) := '  Unable to start production on volume ';
          msg_string (40, * ) := vsn;
          write_message_to_job_output := TRUE;
          force_output_message := TRUE;
          pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
          msg_string (48, * ) := time.hms;
        ELSE
          msg_string (1, 31) := '  Production started on volume ';
          msg_string (32, * ) := vsn;
          write_message_to_job_output := dmv$display_recovery_messages;
          pmp$get_legible_date_time (osc$mdy_date, date, osc$hms_time, time, local_status);
          msg_string (40, * ) := time.hms;
        IFEND;

        clock := #FREE_RUNNING_CLOCK (0);
        IF force_output_message OR (clock > (base + display_update_interval)) THEN
          base := clock;
          dmp$issue_message_to_ascii_log (msg_string, write_message_to_job_output);
          production_started := production_started AND status.normal;
        IFEND;
      IFEND;
    UNTIL (avt_index = 0);

    IF NOT production_started THEN
      osp$set_status_abnormal (dmc$device_manager_ident, dme$unable_to_recover_all_vols,
            'Unable to start production on all volumes.', status);
    IFEND;

  PROCEND start_volume_production;
?? TITLE := '  update_eoi', EJECT ??

  PROCEDURE update_eoi
    (    sfid: gft$system_file_identifier;
     VAR status: ost$status);

    VAR
      allocated_length: amt$file_byte_address,
      bytes_per_allocation: amt$file_byte_address,
      fau_state: dmt$fau_states,
      initialized_length: amt$file_byte_address,
      level_1_index: dmt$level_1_index,
      level_2_index: dmt$level_2_index,
      offset: amt$file_byte_address,
      p_dfd: ^dmt$disk_file_descriptor,
      p_fde: ^gft$file_descriptor_entry,
      p_level_1: ^dmt$level_1_table,
      p_level_2: ^dmt$level_2_table;

    gfp$get_fde_p (sfid, p_fde);

{!!!!!   Are all callers of this assigned a volume????

    dmp$get_disk_file_descriptor_p (p_fde, p_dfd);
    bytes_per_allocation := p_dfd^.bytes_per_allocation;
    allocated_length := 0;
    initialized_length := 0;
    offset := 0;

    dmp$get_level_1_ptr (p_dfd, p_level_1);
    IF p_level_1 <> NIL THEN
      FOR level_1_index := 0 TO p_dfd^.fat_upper_bound DO
        dmp$get_level_2_ptr (^p_level_1^ [level_1_index], p_level_2);
        IF p_level_2 <> NIL THEN
          FOR level_2_index := 0 TO (p_dfd^.bytes_per_level_2 DIV bytes_per_allocation) - 1 DO
            offset := offset + bytes_per_allocation;
            fau_state := p_level_2^ [level_2_index].state;
            IF (fau_state <> dmc$fau_free) THEN
              allocated_length := allocated_length + bytes_per_allocation;
              IF (fau_state = dmc$fau_initialized) OR (fau_state = dmc$fau_initialized_and_flawed) THEN
                initialized_length := offset;
              IFEND;
            IFEND;
          FOREND;
        ELSE;
          offset := offset + p_dfd^.bytes_per_level_2;
        IFEND;
      FOREND;
    IFEND;

    dmp$fixup_fmd_allocated_length (sfid, 1, allocated_length, status);

    IF status.normal THEN
      dmp$set_eoi (sfid, initialized_length, status);
    IFEND;
  PROCEND update_eoi;
MODEND dmm$recover_mainframe;
