?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Logging: Global Log Manager' ??
MODULE lgm$global_log_manager;

{ PURPOSE:
{   This module contains the code used to manage the global logs.
{
{ DESIGN:
{   The global logs are permanent files that are opened during deadstart and added to the job template so
{   that each job inherits access to the logs (each job is not required to attach and open them).  Information
{   about each global log is kept in the log's corresponding log control descriptor (LCD).
{
{   Access to a log is interlocked via a mainframe signature lock (contained in the log's LCD) and all global
{   log accesses eventually find their way to procedures in this module.  There are file entries that appear
{   in the $LOCAL catalog for each job that represent the global logs, but these files entries have a FAP
{   associated with them that calls the interfaces in this module.
{
{   The maximum size and critical flag for each log are defined as system attributes that have their values
{   copied into the appropriate LCD.  The global log manager uses these attributes to make sure that disk
{   space for the log is always preallocated and that the appropriate action is taken when the system is not
{   able to record an entry in a global log (e.g., the disks are full or a disk goes down).

?? NEWTITLE := 'Global Declarations Referenced by This Module.', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dmt$error_condition_codes
*copyc dsc$system_log_file_size
*copyc lgc$default_preallocation_size
*copyc lge$corrupted_log
*copyc lge$end_of_log
*copyc lge$incorrect_move_length
*copyc lge$log_cycles_do_not_match
*copyc lge$log_not_available
*copyc lgt$critical_log_control_desc
*copyc lgt$entry_info
*copyc lgt$log_attribute_entry
*copyc lgt$log_read_activity
*copyc osd$virtual_address
*copyc oss$mainframe_pageable
*copyc oss$mainframe_paged_literal
*copyc pmt$global_binary_logs
*copyc pmt$global_logs
*copyc pmt$log_msg_origin
*copyc pmt$log_msg_text
*copyc pmt$logs
*copyc pmt$system_log_entry
?? POP ??
*copyc clp$trimmed_string_size
*copyc dpp$put_critical_message
*copyc dmp$attach_device_file
*copyc dmp$create_device_file
*copyc dmp$destroy_device_file
*copyc dmp$open_file
*copyc dmp$set_eoi
*copyc dmp$trim_file
*copyc gfp$get_segment_sfid
*copyc i#build_adaptable_seq_pointer
*copyc i#current_sequence_position
*copyc i#move
*copyc jmp$update_job_template_sdt
*copyc lgp$add_critical_log_entry
*copyc lgp$add_log_entry
*copyc lgp$get_critical_log_entry
*copyc lgp$get_critical_read_info
*copyc lgp$get_log_entry
*copyc lgp$get_log_read_information
*copyc lgp$get_previous_crit_log_size
*copyc lgp$get_previous_log_entry_size
*copyc mmp$change_seg_inheritance_r1
*copyc mmp$validate_segment_number
*copyc mmp$write_modified_pages
*copyc osp$clear_mainframe_sig_lock
*copyc osp$fatal_system_error
*copyc osp$initialize_sig_lock
*copyc osp$monitor_fault_to_status
*copyc osp$set_mainframe_sig_lock
*copyc osp$set_status_abnormal
*copyc osp$system_error
*copyc pmp$get_job_names
*copyc pmp$get_time
*copyc syp$disestablish_cond_handler
*copyc syp$establish_condition_handler
*copyc dmv$system_device_information
*copyc dpv$critical_messages
*copyc dpv$critical_msgs_need_logging
*copyc lgv$critical_log_attributes
*copyc lgv$global_log_attributes
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module.', EJECT ??

{ The following translation table is used to remove the control codes from an ascii log entry before it is
{ placed in the log.  Unlike OSV$CONTROL_CODES_TO_QUEST_MARK, this table allows the top 128 ASCII charcters to
{ get through.

  VAR
    lgv$control_codes_to_quest_mark: [XDCL, #GATE, READ, oss$mainframe_paged_literal] string (256) :=
          '????????????' CAT '???????????????????? !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU' CAT
          'VWXYZ[\]^_`abcdefghijkl' CAT 'mnopqrstuvwxyz{|}~?' CAT $CHAR (128) CAT $CHAR (129) CAT
          $CHAR (130) CAT $CHAR (131) CAT $CHAR (132) CAT $CHAR (133) CAT $CHAR (134) CAT $CHAR (135) CAT
          $CHAR (136) CAT $CHAR (137) CAT $CHAR (138) CAT $CHAR (139) CAT $CHAR (140) CAT $CHAR (141) CAT
          $CHAR (142) CAT $CHAR (143) CAT $CHAR (144) CAT $CHAR (145) CAT $CHAR (146) CAT $CHAR (147) CAT
          $CHAR (148) CAT $CHAR (149) CAT $CHAR (150) CAT $CHAR (151) CAT $CHAR (152) CAT $CHAR (153) CAT
          $CHAR (154) CAT $CHAR (155) CAT $CHAR (156) CAT $CHAR (157) CAT $CHAR (158) CAT $CHAR (159) CAT
          $CHAR (160) CAT $CHAR (161) CAT $CHAR (162) CAT $CHAR (163) CAT $CHAR (164) CAT $CHAR (165) CAT
          $CHAR (166) CAT $CHAR (167) CAT $CHAR (168) CAT $CHAR (169) CAT $CHAR (170) CAT $CHAR (171) CAT
          $CHAR (172) CAT $CHAR (173) CAT $CHAR (174) CAT $CHAR (175) CAT $CHAR (176) CAT $CHAR (177) CAT
          $CHAR (178) CAT $CHAR (179) CAT $CHAR (180) CAT $CHAR (181) CAT $CHAR (182) CAT $CHAR (183) CAT
          $CHAR (184) CAT $CHAR (185) CAT $CHAR (186) CAT $CHAR (187) CAT $CHAR (188) CAT $CHAR (189) CAT
          $CHAR (190) CAT $CHAR (191) CAT $CHAR (192) CAT $CHAR (193) CAT $CHAR (194) CAT $CHAR (195) CAT
          $CHAR (196) CAT $CHAR (197) CAT $CHAR (198) CAT $CHAR (199) CAT $CHAR (200) CAT $CHAR (201) CAT
          $CHAR (202) CAT $CHAR (203) CAT $CHAR (204) CAT $CHAR (205) CAT $CHAR (206) CAT $CHAR (207) CAT
          $CHAR (208) CAT $CHAR (209) CAT $CHAR (210) CAT $CHAR (211) CAT $CHAR (212) CAT $CHAR (213) CAT
          $CHAR (214) CAT $CHAR (215) CAT $CHAR (216) CAT $CHAR (217) CAT $CHAR (218) CAT $CHAR (219) CAT
          $CHAR (220) CAT $CHAR (221) CAT $CHAR (222) CAT $CHAR (223) CAT $CHAR (224) CAT $CHAR (225) CAT
          $CHAR (226) CAT $CHAR (227) CAT $CHAR (228) CAT $CHAR (229) CAT $CHAR (230) CAT $CHAR (231) CAT
          $CHAR (232) CAT $CHAR (233) CAT $CHAR (234) CAT $CHAR (235) CAT $CHAR (236) CAT $CHAR (237) CAT
          $CHAR (238) CAT $CHAR (239) CAT $CHAR (240) CAT $CHAR (241) CAT $CHAR (242) CAT $CHAR (243) CAT
          $CHAR (244) CAT $CHAR (245) CAT $CHAR (246) CAT $CHAR (247) CAT $CHAR (248) CAT $CHAR (249) CAT
          $CHAR (250) CAT $CHAR (251) CAT $CHAR (252) CAT $CHAR (253) CAT $CHAR (254) CAT $CHAR (255);

?? FMT (FORMAT := OFF) ??
  VAR
    lgv$global_log_ctl: [XDCL, #GATE, oss$mainframe_pageable] array [pmt$global_logs] of
          lgt$log_control_descriptor := [
          [*, pmc$account_log,       0, NIL, NIL, lgc$maximum_log_size,
                lgc$default_preallocation_size, FALSE, 0, FALSE],
          [*, pmc$engineering_log,   0, NIL, NIL, lgc$maximum_log_size,
                lgc$default_preallocation_size, FALSE, 0, FALSE],
          [*, pmc$history_log,       0, NIL, NIL, lgc$maximum_log_size,
                lgc$default_preallocation_size, FALSE, 0, FALSE],
          [*, pmc$security_log,      0, NIL, NIL, lgc$maximum_log_size,
                lgc$default_preallocation_size, FALSE, 0, FALSE],
          [*, pmc$statistic_log,     0, NIL, NIL, lgc$maximum_log_size,
                lgc$default_preallocation_size, FALSE, 0, FALSE],
          [*, pmc$system_log,        0, NIL, NIL, lgc$maximum_log_size,
                lgc$default_preallocation_size, FALSE, 0, FALSE]];

  VAR
    lgv$critical_log_ctl: [XDCL, #GATE, oss$mainframe_pageable] lgt$critical_log_control_desc := [
          *, 0, NIL, NIL, lgc$maximum_log_size,
          lgc$default_preallocation_size, FALSE, 0, FALSE];
?? FMT (FORMAT := ON) ??

  VAR
    lgv$log_names: [XDCL, #GATE, READ, oss$mainframe_paged_literal] array [pmt$logs] of
          ost$name := ['$JOB_ACCOUNT_LOG', '$JOB_STATISTIC_LOG', '$ACCOUNT_LOG', '$ENGINEERING_LOG',
          '$HISTORY_LOG', '$SECURITY_LOG', '$STATISTIC_LOG', '$SYSTEM_LOG', '$JOB_LOG'];

  VAR
    lgv$critical_log_name: [XDCL, #GATE, READ, oss$mainframe_paged_literal] ost$name :=
          '$CRITICAL_WINDOW_LOG';

  VAR
    lgv$origin_codes: [XDCL, #GATE, READ, oss$mainframe_paged_literal] array [pmt$log_msg_origin] of
          string (2) := ['CI', 'SY', 'PR', 'CS', 'RC'];

  VAR
    lgv$recovery_log_sfid: [XDCL, #GATE, oss$mainframe_pageable] gft$system_file_identifier;

?? OLDTITLE ??
?? NEWTITLE := 'find_end_of_log', EJECT ??

  PROCEDURE find_end_of_log
    (    log_name: ost$name;
     VAR sequence_pointer: ^SEQ ( * );
     VAR trailing_log_entry_header_p: ^lgt$log_entry_header;
     VAR status: ost$status);

    VAR
      log_entry_p: ^lgt$log_entry,
      previous_log_entry_header_p: ^lgt$log_entry_header;

    status.normal := TRUE;

{ Get the first log entry header.

    RESET sequence_pointer;
    NEXT trailing_log_entry_header_p IN sequence_pointer;
    IF trailing_log_entry_header_p = NIL THEN
      osp$set_status_abnormal ('LG', lge$corrupted_log, log_name, status);
      RETURN;
    IFEND;
    trailing_log_entry_header_p^.previous_size := 0;

{ Find the end of the log.

    WHILE trailing_log_entry_header_p^.current_size <> 0 DO

{ Get the next log entry.

      NEXT log_entry_p: [[REP trailing_log_entry_header_p^.current_size OF cell]] IN sequence_pointer;
      IF log_entry_p = NIL THEN
        osp$set_status_abnormal ('LG', lge$corrupted_log, log_name, status);
        RETURN;
      IFEND;

{ Get the next log entry header.

      previous_log_entry_header_p := trailing_log_entry_header_p;
      NEXT trailing_log_entry_header_p IN sequence_pointer;
      IF trailing_log_entry_header_p = NIL THEN
        osp$set_status_abnormal ('LG', lge$corrupted_log, log_name, status);
        RETURN;
      IFEND;

{ If the log entry header is not consistent with the previous log entry header, the previous log entry header
{ is used as the end of the log.

      IF trailing_log_entry_header_p^.previous_size <> previous_log_entry_header_p^.current_size THEN
        RESET sequence_pointer TO log_entry_p;
        trailing_log_entry_header_p := previous_log_entry_header_p;
        trailing_log_entry_header_p^.current_size := 0;
        RETURN;
      IFEND;
    WHILEND;

  PROCEND find_end_of_log;
?? OLDTITLE ??
?? NEWTITLE := 'handle_lost_entry', EJECT ??
{ PURPOSE:
{   Deal with the loss of a log entry in the manner defined by the site.

  PROCEDURE handle_lost_entry
    (    log_control_descriptor_p: ^lgt$log_control_descriptor;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      message_length: integer,
      message_string: ost$string;

    IF log_control_descriptor_p^.critical_log THEN

{ If this is a critical log, the the system must be terminated when a log entry is lost.

      message_string.value := 'Unable to record messages in ';
      message_string.value (clp$trimmed_string_size (message_string.value) + 2, * ) :=
            lgv$log_names [log_control_descriptor_p^.log];
      message_string.size := clp$trimmed_string_size (message_string.value);
      message_string.value (message_string.size + 1) := '.';
      message_string.size := message_string.size + 1;
      osp$fatal_system_error (message_string.value (1, message_string.size), ^status);
    ELSE

{ If this is not a critical log and the log data pointer is not NIL, increment the lost message count in the
{ log control descriptor and tell the operator the first time a message is lost (or every 1000 messages).

      log_control_descriptor_p^.lost_message_count := log_control_descriptor_p^.lost_message_count + 1;
      IF (log_control_descriptor_p^.log_data <> NIL) AND
            (log_control_descriptor_p^.lost_message_count = 1) OR
            ((log_control_descriptor_P^.lost_message_count MOD 1000) = 0) THEN
        message_string.value := 'Losing messages sent to ';
        message_string.value (clp$trimmed_string_size (message_string.value) + 2, * ) :=
              lgv$log_names [log_control_descriptor_p^.log];
        message_string.size := clp$trimmed_string_size (message_string.value);
        message_string.value (message_string.size + 1) := '.';
        message_string.size := message_string.size + 1;
        dpp$put_critical_message (message_string.value (1, message_string.size), ignore_status);
        IF NOT status.normal THEN
          IF status.condition = lge$log_full THEN
            stringrep(message_string.value, message_length,
                  ' The ', lgv$log_names [log_control_descriptor_p^.log] (1,
                  clp$trimmed_string_size (lgv$log_names [log_control_descriptor_p^.log])),
                  ' is full, execute the TERMINATE_LOG command to clear the log.');
          ELSEIF status.condition = dme$unable_to_alloc_all_space THEN
            stringrep(message_string.value, message_length,
                  ' The system set is out of mass storage class K (system permanent file)',
                  ' space.  Logging cannot occur without class K space.  Please make ',
                  ' more class K space available by deleting files on the class K devices ',
                  ' or by adding class K to another device on the system set.');
          ELSE

{ An unexpected status occurred, display the condition in the critical window.

            stringrep(message_string.value, message_length,
                  ' Logging to ', lgv$log_names [log_control_descriptor_p^.log] (1,
                  clp$trimmed_string_size (lgv$log_names [log_control_descriptor_p^.log])),
                  ' failed with status: ', status.condition,
                  ', execute DISPLAY_VALUE $STATUS_CODE_NAME({condition}) to see the status code');
          IFEND;
          dpp$put_critical_message (message_string.value (1, message_length), ignore_status);
        IFEND;
      IFEND;
      status.normal := TRUE;
    IFEND;

  PROCEND handle_lost_entry;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$add_entry_global_binary_log', EJECT ??
*copy lgh$add_entry_global_binary_log

  PROCEDURE [XDCL, #GATE] lgp$add_entry_global_binary_log
    (    global_binary_log: pmt$global_binary_logs;
         entry_p: ^lgt$log_entry;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      length: integer,
      msg: string(osc$max_string_size),
      log_control_descriptor_p: ^lgt$log_control_descriptor;

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Make sure that the log interlock is cleared in the event of an error.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        local_status: ost$status,
        length: integer,
        msg: string(osc$max_string_size);

      osp$monitor_fault_to_status (monitor_fault, save_area, local_status);
      handle_lost_entry (log_control_descriptor_p, local_status);
      osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
      EXIT lgp$add_entry_global_binary_log;

    PROCEND condition_handler;
?? OLDTITLE, EJECT ??
    status.normal := TRUE;

{ Get a pointer to the appropriate log control descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [global_binary_log];
    #SPOIL (log_control_descriptor_p);

{ Interlock the log.

    osp$set_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$establish_condition_handler (^condition_handler);

{ Add the entry to the log.  If everything works correctly, reset the lost message counter in the log
{ control descriptor.  If an error occurs, handle the loss of the entry in the manner defined by site
{ for this log.

    lgp$add_log_entry (entry_p, log_control_descriptor_p, status);
    IF status.normal THEN
      log_control_descriptor_p^.lost_message_count := 0;
    ELSE
      handle_lost_entry (log_control_descriptor_p, status);
    IFEND;

{ Clear the log interlock.

    osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$disestablish_cond_handler;

  PROCEND lgp$add_entry_global_binary_log;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$add_entry_to_critical_log', EJECT ??
*copy lgh$add_entry_to_critical_log

  PROCEDURE [XDCL, #GATE] lgp$add_entry_to_critical_log
    (    text: pmt$log_msg_text;
     VAR status: ost$status);

    VAR
      dummy_sdte_p: ^mmt$segment_descriptor,
      dummy_sdtxe_p: ^mmt$segment_descriptor_extended,
      log_control_descriptor_p: ^lgt$critical_log_control_desc,
      critical_log_entry_p: ^pmt$log_msg_text,
      system_supplied_name: jmt$system_supplied_name,
      text_size: lgt$log_entry_size,
      user_supplied_name: jmt$user_supplied_name;

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Make sure that the log interlock is cleared in the event of an error.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        local_status: ost$status;

      osp$monitor_fault_to_status (monitor_fault, save_area, local_status);
      log_control_descriptor_p^.lost_message_count := log_control_descriptor_p^.lost_message_count + 1;
      osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
      EXIT lgp$add_entry_to_critical_log;

    PROCEND condition_handler;
?? NEWTITLE := 'update_critical_messages', EJECT ??

{ PURPOSE:
{   This procedure updates the critical message variable so the message can be logged in the critical log.

  PROCEDURE update_critical_messages (
    message: string(*);
    size: integer);

    VAR
      msg_index: 1..16,
      prev_msg_index: 1..16;

    msg_index := 1;
    While (msg_index < 16) AND (dpv$critical_messages [msg_index].size <> 0) DO
      msg_index := msg_index + 1;
    WHILEND;
    IF msg_index < 16 THEN
      dpv$critical_messages [msg_index].value := message;
      dpv$critical_messages [msg_index].size := size;
    ELSE
      msg_index := 2;
      prev_msg_index := 1;
      WHILE msg_index < 16 DO
        dpv$critical_messages [prev_msg_index].value := dpv$critical_messages [msg_index].value;
        dpv$critical_messages [prev_msg_index].size := dpv$critical_messages [msg_index].size;
        msg_index := msg_index + 1;
        prev_msg_index := prev_msg_index + 1;
      WHILEND;
      dpv$critical_messages [15].value := message;
      dpv$critical_messages [15].size := size;
    IFEND;
    dpv$critical_msgs_need_logging := TRUE;
  PROCEND update_critical_messages;
?? OLDTITLE ??
?? OLDTITLE, EJECT ??

    status.normal := TRUE;

{ Get a pointer to the critical log control descriptor.

    log_control_descriptor_p := ^lgv$critical_log_ctl;
    #SPOIL (log_control_descriptor_p);

{ Validate that you can write into segment 18(16) (critical window log), device management tasks
{ cannot write into this segment (it does not exist in these tasks).

    mmp$validate_segment_number ({segment_number =} 18(16), dummy_sdte_p, dummy_sdtxe_p, status);
    IF NOT status.normal THEN
      update_critical_messages (text, STRLENGTH(text));
      RETURN;
    IFEND;

{ Interlock the log.

    osp$set_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$establish_condition_handler (^condition_handler);

{ Format the critical window log entry.

    text_size := STRLENGTH (text);
    PUSH critical_log_entry_p: [text_size];

    #TRANSLATE (lgv$control_codes_to_quest_mark, text, critical_log_entry_p^);

{ Add the entry to the log.  If everything works correctly, reset the lost message counter in the log
{ control descriptor.  If an error occurs, handle the loss of the entry in the manner defined by site
{ for this log.

    lgp$add_critical_log_entry (#SEQ (critical_log_entry_p^), log_control_descriptor_p, status);
    IF status.normal THEN
      log_control_descriptor_p^.lost_message_count := 0;
    ELSE
      log_control_descriptor_p^.lost_message_count := log_control_descriptor_p^.lost_message_count + 1;
    IFEND;

{ Clear the log interlock.

    osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$disestablish_cond_handler;

  PROCEND lgp$add_entry_to_critical_log;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$add_entry_to_system_log', EJECT ??
*copy lgh$add_entry_to_system_log

  PROCEDURE [XDCL, #GATE] lgp$add_entry_to_system_log
    (    origin: pmt$log_msg_origin;
         text: pmt$log_msg_text;
     VAR log_time: ost$time;
     VAR status: ost$status);

    VAR
      ignore_status: ost$status,
      log_control_descriptor_p: ^lgt$log_control_descriptor,
      length: integer,
      msg: string(osc$max_string_size),
      system_log_entry_p: ^pmt$system_log_entry,
      system_supplied_name: jmt$system_supplied_name,
      text_size: lgt$log_entry_size,
      user_supplied_name: jmt$user_supplied_name;

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Make sure that the log interlock is cleared in the event of an error.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        ignore_status: ost$status,
        length: integer,
        local_status: ost$status,
        msg: string(osc$max_string_size);

      osp$monitor_fault_to_status (monitor_fault, save_area, local_status);
      handle_lost_entry (log_control_descriptor_p, local_status);
      osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
      EXIT lgp$add_entry_to_system_log;

    PROCEND condition_handler;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;

{ Get a pointer to the appropriate log control descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [pmc$system_log];
    #SPOIL (log_control_descriptor_p);

{ Interlock the log.

    osp$set_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$establish_condition_handler (^condition_handler);

  /log_locked/
    BEGIN

{ Get the time stamp and job name for the log message.

      pmp$get_time (osc$millisecond_time, log_time, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

      pmp$get_job_names (user_supplied_name, system_supplied_name, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

{ Format the system log entry.

      text_size := lgc$maximum_log_entry_size - #SIZE (pmt$system_log_entry: [0]);
      IF STRLENGTH (text) < text_size THEN
        text_size := STRLENGTH (text);
      IFEND;
      PUSH system_log_entry_p: [text_size];

      system_log_entry_p^.time := log_time.millisecond;
      system_log_entry_p^.delimiter_1 (1) := '.';
      system_log_entry_p^.job_sequence_number := system_supplied_name;
      system_log_entry_p^.delimiter_2 (1) := '.';
      system_log_entry_p^.origin := lgv$origin_codes [origin];
      system_log_entry_p^.delimiter_3 (1) := '.';
      #TRANSLATE (lgv$control_codes_to_quest_mark, text, system_log_entry_p^.text);

{ Add the entry to the log.  If everything works correctly, reset the lost message counter in the log
{ control descriptor.  If an error occurs, handle the loss of the entry in the manner defined by site
{ for this log.

      lgp$add_log_entry (#SEQ (system_log_entry_p^), log_control_descriptor_p, status);
      IF status.normal THEN
        log_control_descriptor_p^.lost_message_count := 0;
      ELSE
        handle_lost_entry (log_control_descriptor_p, status);
      IFEND;
    END /log_locked/;

{ Clear the log interlock.

    osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$disestablish_cond_handler;

  PROCEND lgp$add_entry_to_system_log;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_critical_log_read_info', EJECT ??
*copy lgh$get_critical_log_read_info

  PROCEDURE [XDCL, #GATE] lgp$get_critical_log_read_info
     (   entry_count_from_end_of_log: ost$segment_length;
     VAR log_cycle: lgt$log_cycle;
     VAR log_data: ^SEQ ( * );
     VAR ending_offset: amt$file_byte_address;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$critical_log_control_desc;

    status.normal := TRUE;

{ Get a pointer to the critical window log control descriptor.

    log_control_descriptor_p := ^lgv$critical_log_ctl;

{ Get the appropriate values from the log control descriptor.

    lgp$get_critical_read_info (log_control_descriptor_p, entry_count_from_end_of_log, log_cycle,
          log_data, ending_offset, status);

  PROCEND lgp$get_critical_log_read_info;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_entry_from_critical_log', EJECT ??
*copy lgh$get_entry_from_critical_log

  PROCEDURE [XDCL, #GATE] lgp$get_entry_from_critical_log
     (   log_cycle: lgt$log_cycle;
     VAR log_data: ^SEQ ( * );
     VAR log_entry_size: lgt$log_entry_size;
     VAR log_entry: lgt$log_entry;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$critical_log_control_desc;

    status.normal := TRUE;

{ Get a pointer to the critical window log control descriptor.

    log_control_descriptor_p := ^lgv$critical_log_ctl;

{ Get a copy of the next log entry.

    lgp$get_critical_log_entry (log_cycle, log_control_descriptor_p, log_data, log_entry_size,
          log_entry, status);

  PROCEND lgp$get_entry_from_critical_log;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_entry_from_global_log', EJECT ??
*copy lgh$get_entry_from_global_log

  PROCEDURE [XDCL, #GATE] lgp$get_entry_from_global_log
    (    global_log: pmt$global_logs;
         log_cycle: lgt$log_cycle;
     VAR log_data: ^SEQ ( * );
     VAR log_entry_size: lgt$log_entry_size;
     VAR log_entry: lgt$log_entry;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$log_control_descriptor;

    status.normal := TRUE;

{ Get a pointer to the appropriate log control descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [global_log];

{ Get a copy of the next log entry.

    lgp$get_log_entry (log_cycle, log_control_descriptor_p, log_data, log_entry_size, log_entry, status);

  PROCEND lgp$get_entry_from_global_log;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_global_log_read_info', EJECT ??
*copy lgh$get_global_log_read_info

  PROCEDURE [XDCL, #GATE] lgp$get_global_log_read_info
    (    global_log: pmt$global_logs;
         entry_count_from_end_of_log: ost$segment_length;
     VAR log_cycle: lgt$log_cycle;
     VAR log_data: ^SEQ ( * );
     VAR ending_offset: amt$file_byte_address;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$log_control_descriptor;

    status.normal := TRUE;

{ Get a pointer to the appropriate log control descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [global_log];

{ Get the appropriate values from the log control descriptor.

    lgp$get_log_read_information (log_control_descriptor_p, entry_count_from_end_of_log, log_cycle, log_data,
          ending_offset, status);

  PROCEND lgp$get_global_log_read_info;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_critical_previous_size', EJECT ??

  PROCEDURE [XDCL, #GATE] lgp$get_critical_previous_size
    (    log_cycle: lgt$log_cycle;
     VAR log_data: ^SEQ ( * );
     VAR previous_size: lgt$log_entry_size;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$critical_log_control_desc;

    status.normal := TRUE;

{ Get a pointer to the critical window log control descriptor.

    log_control_descriptor_p := ^lgv$critical_log_ctl;

{ Get the size of the previous log entry.

    lgp$get_previous_crit_log_size (log_cycle, log_control_descriptor_p, log_data, previous_size, status);

  PROCEND lgp$get_critical_previous_size;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_global_previous_size', EJECT ??

  PROCEDURE [XDCL, #GATE] lgp$get_global_previous_size
    (    global_log: pmt$global_logs;
         log_cycle: lgt$log_cycle;
     VAR log_data: ^SEQ ( * );
     VAR previous_size: lgt$log_entry_size;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$log_control_descriptor;

    status.normal := TRUE;

{ Get a pointer to the appropriate log control descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [global_log];

{ Get the size of the previous log entry.

    lgp$get_previous_log_entry_size (log_cycle, log_control_descriptor_p, log_data, previous_size, status);

  PROCEND lgp$get_global_previous_size;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$initialize_critical_log_lcd', EJECT ??
*copy lgh$initialize_critical_log_lcd

  PROCEDURE [XDCL, #GATE] lgp$initialize_critical_log_lcd
     (   log: ^SEQ ( * );
     VAR status: ost$status);

    VAR
      ending_offset: amt$file_byte_address,
      log_control_descriptor_p: ^lgt$critical_log_control_desc,
      log_entry_p: ^lgt$log_entry,
      log_entry_header_p: ^lgt$log_entry_header,
      previous_log_entry_header_p: ^lgt$log_entry_header,
      sequence_pointer: ^SEQ ( * );

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Return an error to the caller if a condition occurs.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      osp$monitor_fault_to_status (monitor_fault, save_area, status);
      EXIT lgp$initialize_critical_log_lcd;

    PROCEND condition_handler;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;

{ Get a pointer to the critical window log control descriptor.

    log_control_descriptor_p := ^lgv$critical_log_ctl;

    syp$establish_condition_handler (^condition_handler);

{ Find the end of the log.

    sequence_pointer := log;
    find_end_of_log (lgv$critical_log_name, sequence_pointer, log_entry_header_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    ending_offset := i#current_sequence_position (sequence_pointer);

{ Initialize the critical window log control descriptor fields.

    osp$initialize_sig_lock (log_control_descriptor_p^.lock);
    log_control_descriptor_p^.log_cycle := LOWERVALUE (log_control_descriptor_p^.log_cycle);
    i#build_adaptable_seq_pointer (#RING (sequence_pointer), #SEGMENT (sequence_pointer),
          #OFFSET (sequence_pointer), ending_offset, ending_offset, log_control_descriptor_p^.log_data);
    log_control_descriptor_p^.trailing_log_entry_header_p := log_entry_header_p;
    log_control_descriptor_p^.maximum_size := lgv$critical_log_attributes.maximum_size * 1000000;
    log_control_descriptor_p^.preallocation_size := lgv$critical_log_attributes.preallocation_size;
    log_control_descriptor_p^.lost_message_count := 0;

{ If the log is more than 75% full, do not set the critical log indicator.  The operator will be required to
{ terminate the log before deadstart completes and terminate log will set the critical flag if necessary.

    IF ending_offset > ((log_control_descriptor_p^.maximum_size * 3) DIV 4) THEN
      log_control_descriptor_p^.critical_log := FALSE;
    ELSE
      log_control_descriptor_p^.critical_log := lgv$critical_log_attributes.critical;
    IFEND;

    syp$disestablish_cond_handler;

{ Add the log segment to the job template.

    jmp$update_job_template_sdt (log, status);

  PROCEND lgp$initialize_critical_log_lcd;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$initialize_global_log_lcd', EJECT ??
*copy lgh$initialize_global_log_lcd

  PROCEDURE [XDCL, #GATE] lgp$initialize_global_log_lcd
    (    global_log: pmt$global_logs;
         log: ^SEQ ( * );
     VAR status: ost$status);

    VAR
      ending_offset: amt$file_byte_address,
      log_control_descriptor_p: ^lgt$log_control_descriptor,
      log_entry_p: ^lgt$log_entry,
      log_entry_header_p: ^lgt$log_entry_header,
      previous_log_entry_header_p: ^lgt$log_entry_header,
      sequence_pointer: ^SEQ ( * );

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Return an error to the caller if a condition occurs.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      osp$monitor_fault_to_status (monitor_fault, save_area, status);
      EXIT lgp$initialize_global_log_lcd;

    PROCEND condition_handler;
?? OLDTITLE, EJECT ??

    status.normal := TRUE;

{ Get a pointer to the log control descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [global_log];

    syp$establish_condition_handler (^condition_handler);

{ Find the end of the log.

    sequence_pointer := log;
    find_end_of_log (lgv$log_names [global_log], sequence_pointer, log_entry_header_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    ending_offset := i#current_sequence_position (sequence_pointer);

{ Initialize the log control descriptor fields.

    osp$initialize_sig_lock (log_control_descriptor_p^.lock);
    log_control_descriptor_p^.log := global_log;
    log_control_descriptor_p^.log_cycle := LOWERVALUE (log_control_descriptor_p^.log_cycle);
    i#build_adaptable_seq_pointer (#RING (sequence_pointer), #SEGMENT (sequence_pointer),
          #OFFSET (sequence_pointer), ending_offset, ending_offset, log_control_descriptor_p^.log_data);
    log_control_descriptor_p^.trailing_log_entry_header_p := log_entry_header_p;
    log_control_descriptor_p^.maximum_size := lgv$global_log_attributes [global_log].maximum_size * 1000000;
    log_control_descriptor_p^.preallocation_size := lgv$global_log_attributes [global_log].preallocation_size;
    log_control_descriptor_p^.lost_message_count := 0;

{ If the log is more than 75% full, do not set the critical log indicator.  The operator will be required to
{ terminate the log before deadstart completes and terminate log will set the critical flag if necessary.

    IF ending_offset > ((log_control_descriptor_p^.maximum_size * 3) DIV 4) THEN
      log_control_descriptor_p^.critical_log := FALSE;
    ELSE
      log_control_descriptor_p^.critical_log := lgv$global_log_attributes [global_log].critical;
    IFEND;

    syp$disestablish_cond_handler;

{ Add the log segment to the job template.

    jmp$update_job_template_sdt (log, status);

  PROCEND lgp$initialize_global_log_lcd;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$release_critical_log_space', EJECT ??
*copy lgh$release_critical_log_space

  PROCEDURE [XDCL, #GATE] lgp$release_critical_log_space
     (   log_cycle: lgt$log_cycle;
         first_log_entry_header_p: ^lgt$log_entry_header;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$critical_log_control_desc,
      log_entry_header: ^lgt$log_entry_header,
      system_file_id: gft$system_file_identifier,
      new_eoi: ost$segment_offset,
      move_length: ost$relative_pointer;

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Make sure that the log interlock is cleared in the event of an error.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
      osp$monitor_fault_to_status (monitor_fault, save_area, status);
      EXIT lgp$release_critical_log_space;

    PROCEND condition_handler;
?? OLDTITLE, EJECT ??
    status.normal := TRUE;

{ Get a pointer to the critical window log control descriptor.

    log_control_descriptor_p := ^lgv$critical_log_ctl;
    #SPOIL (log_control_descriptor_p);

{ Interlock the log.

    osp$set_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$establish_condition_handler (^condition_handler);

  /log_locked/
    BEGIN

{ Verify that the specified log cycle matches the actual log cycle.

      IF log_cycle <> log_control_descriptor_p^.log_cycle THEN
        osp$set_status_abnormal ('LG', lge$log_cycles_do_not_match, lgv$critical_log_name, status);
        EXIT /log_locked/;
      IFEND;

{ If the first log entry header pointer is not NIL move the log entries that need to be saved to the
{ beginning.  Otherwise set up the log to contain only the first log entry header (an empty log).

      IF first_log_entry_header_p <> NIL THEN

{ Compute the amount of data that must be moved (i.e., the log entries that have been added since log
{ termination began).

        move_length := i#current_sequence_position (log_control_descriptor_p^.log_data) -
              #OFFSET (first_log_entry_header_p);
        IF move_length < #SIZE (lgt$log_entry_header) THEN
          osp$set_status_abnormal ('LG', lge$incorrect_move_length, lgv$critical_log_name, status);
          EXIT /log_locked/;
        IFEND;

{ Reset the previous size entry in the first log entry header.

        first_log_entry_header_p^.previous_size := 0;

{ Move the data to the beginning of the log.

        i#move (first_log_entry_header_p, log_control_descriptor_p^.log_data, move_length);

{ Force the updated pages to disk.

        mmp$write_modified_pages (log_control_descriptor_p^.log_data,
              i#current_sequence_position (log_control_descriptor_p^.log_data), osc$wait, status);
        IF NOT status.normal THEN
          EXIT /log_locked/;
        IFEND;

{ Construct a new log data pointer that points to a sequence that matches the amount of data left in the log.

        i#build_adaptable_seq_pointer (#RING (log_control_descriptor_p^.log_data),
              #SEGMENT (log_control_descriptor_p^.log_data), #OFFSET (log_control_descriptor_p^.log_data),
              { size = } move_length, { current position = } move_length, log_control_descriptor_p^.log_data);

{ Construct a pointer to the trailing log entry header.

        log_control_descriptor_p^.trailing_log_entry_header_p :=
              #ADDRESS (#RING (log_control_descriptor_p^.log_data),
              #SEGMENT (log_control_descriptor_p^.log_data), move_length - #SIZE (lgt$log_entry_header));
      ELSE

{ Set up the log data sequence to be an empty log.

        move_length := #SIZE (lgt$log_entry_header);
        i#build_adaptable_seq_pointer (#RING (log_control_descriptor_p^.log_data),
              #SEGMENT (log_control_descriptor_p^.log_data), #OFFSET (log_control_descriptor_p^.log_data),
              { size = } move_length, { current position = } 0, log_control_descriptor_p^.log_data);
        RESET log_control_descriptor_p^.log_data;
        NEXT log_control_descriptor_p^.trailing_log_entry_header_p IN log_control_descriptor_p^.log_data;
        IF log_control_descriptor_p^.trailing_log_entry_header_p = NIL THEN
          osp$set_status_abnormal ('LG', lge$corrupted_log, lgv$critical_log_name, status);
          EXIT /log_locked/;
        IFEND;
        log_control_descriptor_p^.trailing_log_entry_header_p^.previous_size := 0;
        log_control_descriptor_p^.trailing_log_entry_header_p^.current_size := 0;
      IFEND;

{ Release the unneeded disk space.

      new_eoi := move_length + 1;

      gfp$get_segment_sfid (log_control_descriptor_p^.log_data, system_file_id, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

      dmp$set_eoi (system_file_id, new_eoi, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

      dmp$trim_file (system_file_id, new_eoi, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

{ Make sure the maximum size and critical log flags are set to the correct values.

      log_control_descriptor_p^.maximum_size := lgv$critical_log_attributes.maximum_size * 1000000;
      log_control_descriptor_p^.critical_log := lgv$critical_log_attributes.critical;

{ Reset the lost message count and log full indicator.

      log_control_descriptor_p^.lost_message_count := 0;
      log_control_descriptor_p^.log_full := FALSE;

{ Increment the log cycle (wrapping to zero if necessary).

      IF log_control_descriptor_p^.log_cycle = lgc$maximum_log_cycle THEN
        log_control_descriptor_p^.log_cycle := 0;
      ELSE
        log_control_descriptor_p^.log_cycle := log_control_descriptor_p^.log_cycle + 1;
      IFEND;

    END /log_locked/;

{ Clear the log interlock.

    osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$disestablish_cond_handler;

  PROCEND lgp$release_critical_log_space;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$release_global_log_space', EJECT ??
*copy lgh$release_global_log_space

  PROCEDURE [XDCL, #GATE] lgp$release_global_log_space
    (    global_log: pmt$global_logs;
         log_cycle: lgt$log_cycle;
         first_log_entry_header_p: ^lgt$log_entry_header;
     VAR status: ost$status);

    VAR
      log_control_descriptor_p: ^lgt$log_control_descriptor,
      log_entry_header: ^lgt$log_entry_header,
      system_file_id: gft$system_file_identifier,
      new_eoi: ost$segment_offset,
      move_length: ost$relative_pointer;

?? NEWTITLE := 'condition_handler', EJECT ??

{ PURPOSE:
{   Make sure that the log interlock is cleared in the event of an error.

    PROCEDURE condition_handler
      (    monitor_fault: ost$monitor_fault;
           save_area: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
      osp$monitor_fault_to_status (monitor_fault, save_area, status);
      EXIT lgp$release_global_log_space;

    PROCEND condition_handler;
?? OLDTITLE, EJECT ??
    status.normal := TRUE;

{ Get a pointer to the log control_descriptor.

    log_control_descriptor_p := ^lgv$global_log_ctl [global_log];
    #SPOIL (log_control_descriptor_p);

{ Interlock the log.

    osp$set_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$establish_condition_handler (^condition_handler);

  /log_locked/
    BEGIN

{ Verify that the specified log cycle matches the actual log cycle.

      IF log_cycle <> log_control_descriptor_p^.log_cycle THEN
        osp$set_status_abnormal ('LG', lge$log_cycles_do_not_match, lgv$log_names [global_log], status);
        EXIT /log_locked/;
      IFEND;

{ If the first log entry header pointer is not NIL move the log entries that need to be saved to the
{ beginning.  Otherwise set up the log to contain only the first log entry header (an empty log).

      IF first_log_entry_header_p <> NIL THEN

{ Compute the amount of data that must be moved (i.e., the log entries that have been added since log
{ termination began).

        move_length := i#current_sequence_position (log_control_descriptor_p^.log_data) -
              #OFFSET (first_log_entry_header_p);
        IF move_length < #SIZE (lgt$log_entry_header) THEN
          osp$set_status_abnormal ('LG', lge$incorrect_move_length, lgv$log_names [global_log], status);
          EXIT /log_locked/;
        IFEND;

{ Reset the previous size entry in the first log entry header.

        first_log_entry_header_p^.previous_size := 0;

{ Move the data to the beginning of the log.

        i#move (first_log_entry_header_p, log_control_descriptor_p^.log_data, move_length);

{ Force the updated pages to disk.

        mmp$write_modified_pages (log_control_descriptor_p^.log_data,
              i#current_sequence_position (log_control_descriptor_p^.log_data), osc$wait, status);
        IF NOT status.normal THEN
          EXIT /log_locked/;
        IFEND;

{ Construct a new log data pointer that points to a sequence that matches the amount of data left in the log.

        i#build_adaptable_seq_pointer (#RING (log_control_descriptor_p^.log_data),
              #SEGMENT (log_control_descriptor_p^.log_data), #OFFSET (log_control_descriptor_p^.log_data),
              { size = } move_length, { current position = } move_length, log_control_descriptor_p^.log_data);

{ Construct a pointer to the trailing log entry header.

        log_control_descriptor_p^.trailing_log_entry_header_p :=
              #ADDRESS (#RING (log_control_descriptor_p^.log_data),
              #SEGMENT (log_control_descriptor_p^.log_data), move_length - #SIZE (lgt$log_entry_header));
      ELSE

{ Set up the log data sequence to be an empty log.

        move_length := #SIZE (lgt$log_entry_header);
        i#build_adaptable_seq_pointer (#RING (log_control_descriptor_p^.log_data),
              #SEGMENT (log_control_descriptor_p^.log_data), #OFFSET (log_control_descriptor_p^.log_data),
              { size = } move_length, { current position = } 0, log_control_descriptor_p^.log_data);
        RESET log_control_descriptor_p^.log_data;
        NEXT log_control_descriptor_p^.trailing_log_entry_header_p IN log_control_descriptor_p^.log_data;
        IF log_control_descriptor_p^.trailing_log_entry_header_p = NIL THEN
          osp$set_status_abnormal ('LG', lge$corrupted_log, lgv$log_names [log_control_descriptor_p^.log],
                status);
          EXIT /log_locked/;
        IFEND;
        log_control_descriptor_p^.trailing_log_entry_header_p^.previous_size := 0;
        log_control_descriptor_p^.trailing_log_entry_header_p^.current_size := 0;
      IFEND;

{ Release the unneeded disk space.

      new_eoi := move_length + 1;

      gfp$get_segment_sfid (log_control_descriptor_p^.log_data, system_file_id, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

      dmp$set_eoi (system_file_id, new_eoi, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

      dmp$trim_file (system_file_id, new_eoi, status);
      IF NOT status.normal THEN
        EXIT /log_locked/;
      IFEND;

{ Make sure the maximum size and critical log flags are set to the correct values.

      log_control_descriptor_p^.maximum_size := lgv$global_log_attributes [global_log].maximum_size * 1000000;
      log_control_descriptor_p^.critical_log := lgv$global_log_attributes [global_log].critical;

{ Reset the lost message count and log full indicator.

      log_control_descriptor_p^.lost_message_count := 0;
      log_control_descriptor_p^.log_full := FALSE;

{ Increment the log cycle (wrapping to zero if necessary).

      IF log_control_descriptor_p^.log_cycle = lgc$maximum_log_cycle THEN
        log_control_descriptor_p^.log_cycle := 0;
      ELSE
        log_control_descriptor_p^.log_cycle := log_control_descriptor_p^.log_cycle + 1;
      IFEND;

    END /log_locked/;

{ Clear the log interlock.

    osp$clear_mainframe_sig_lock (log_control_descriptor_p^.lock);
    syp$disestablish_cond_handler;

  PROCEND lgp$release_global_log_space;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] lgp$setup_recovery_logging', EJECT ??

{ PURPOSE:
{   The purpose of this request is to provide an environment in which system level logging may take place
{   prior to the availablility of permanent files.  This environment is established during system recovery.
{   The environment established by this request does not support system level binary logging.

  PROCEDURE [XDCL, #GATE] lgp$setup_recovery_logging
    (VAR status: ost$status);

    VAR
      file_attributes: array [1 .. 1] of dmt$new_device_file_attribute,
      log_time: ost$time,
      recorded_vsn: rmt$recorded_vsn,
      segment_pointer: mmt$segment_pointer,
      user_supplied_name: ost$name;

    status.normal := TRUE;

{ Open the device file used to hold the recovery log.

    user_supplied_name := 'LGF$SYSTEM_LOG';
    recorded_vsn := dmv$system_device_recorded_vsn;
    file_attributes [1].keyword := dmc$file_limit;
    file_attributes [1].limit := UPPERVALUE (amt$file_limit);

    dmp$attach_device_file (recorded_vsn, user_supplied_name, lgv$recovery_log_sfid, status);
    IF status.normal THEN
      segment_pointer.kind := mmc$sequence_pointer;
      dmp$open_file (lgv$recovery_log_sfid, 3, 3, mmc$sar_write_extend, mmc$as_random,
            segment_pointer, status);
    IFEND;

{ If an error occured while opening the device file, attempt to recreate the device file.  If the device file
{ cannot be recreated, deadstart will be allowed to continue without the recovery log being available.

    IF NOT status.normal THEN
      dmp$destroy_device_file (recorded_vsn, user_supplied_name, {ignore} status);
      status.normal := TRUE;
      dmp$create_device_file (user_supplied_name, recorded_vsn, ^file_attributes, dsc$system_log_file_size,
            lgv$recovery_log_sfid, status);
      IF NOT status.normal THEN
        status.normal := TRUE;
        RETURN;
      IFEND;
      dmp$open_file (lgv$recovery_log_sfid, 3, 3, mmc$sar_write_extend, mmc$as_random,
            segment_pointer, status);
      IF NOT status.normal THEN
        status.normal := TRUE;
        RETURN;
      IFEND;
    IFEND;
    mmp$change_seg_inheritance_r1 (#SEGMENT (segment_pointer.cell_pointer), 1, mmc$si_share_segment, status);

{ Initialize the log control descriptor.  The log control descriptor for the system log is used for the
{ recovery log.

    osp$initialize_sig_lock (lgv$global_log_ctl [pmc$system_log].lock);
    lgv$global_log_ctl [pmc$system_log].log_data := segment_pointer.seq_pointer;
    RESET lgv$global_log_ctl [pmc$system_log].log_data;

    find_end_of_log (user_supplied_name, lgv$global_log_ctl [pmc$system_log].
          log_data, lgv$global_log_ctl [pmc$system_log].trailing_log_entry_header_p, status);

  PROCEND lgp$setup_recovery_logging;
?? OLDTITLE ??
MODEND lgm$global_log_manager;
