?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Logging: Get Next Statistic Interfaces' ??
MODULE lgm$get_next_statistic;

{ PURPOSE:
{   This module contains the gated interfaces used to access the local and global logs.

?? NEWTITLE := 'Global Declarations Referenced by This Module.', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc lge$corrupted_statistic
*copyc lge$end_of_log
*copyc lge$statistic_buffer_required
*copyc lgt$log_entry
*copyc lgt$log_entry_size
*copyc ost$caller_identifier
*copyc sft$statistic_buffer
*copyc sft$statistic_header
*copyc sft$counters
*copyc sft$descriptive_data
?? POP ??
*copyc i#move
*copyc lgp$get_next_log_entry
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
?? OLDTITLE, EJECT ??
?? NEWTITLE := '[XDCL, #GATE] lgp$get_next_statistic', EJECT ??
*copyc lgh$get_next_statistic

  PROCEDURE [XDCL, #GATE] lgp$get_next_statistic
    (    log_file_identifier: lgt$log_file_identifier;
         statistic_buffer_p: ^sft$statistic_buffer;
     VAR statistic_header_p: ^sft$statistic_header;
     VAR counters_p: sft$counters;
     VAR descriptive_data_p: ^sft$descriptive_data;
     VAR status: ost$status);

    VAR
      caller_identifier: ost$caller_identifier,
      local_log_data: ^SEQ ( * ),
      log_entry_p: ^lgt$log_entry,
      log_entry_size: lgt$log_entry_size;

    status.normal := TRUE;
    #CALLER_ID (caller_identifier);

{ Get the next statistic from the log.

    lgp$get_next_log_entry (log_file_identifier, statistic_buffer_p, log_entry_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

{ Parse the statistic to get a pointer to the statistic header, counters and descriptive data.

    lgp$parse_statistic (log_entry_p, statistic_header_p, counters_p, descriptive_data_p, status);
    IF NOT status.normal THEN
      IF (status.condition = lge$statistic_buffer_required) AND (statistic_buffer_p <> NIL) THEN
        i#move (log_entry_p, statistic_buffer_p, #SIZE (log_entry_p^));
        lgp$parse_statistic (statistic_buffer_p, statistic_header_p, counters_p, descriptive_data_p,
               status);
      ELSE
        RETURN;
      IFEND;
    IFEND;

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

  PROCEDURE [XDCL, #GATE] lgp$parse_statistic
    (    log_entry_p: ^lgt$log_entry;
     VAR statistic_header_p: ^sft$statistic_header;
     VAR counters_p: sft$counters;
     VAR descriptive_data_p: ^sft$descriptive_data;
     VAR status: ost$status);

    VAR
      local_log_entry_p: ^lgt$log_entry;

?? NEWTITLE := 'parse_obsolete_statistic', EJECT ??
{ PURPOSE:
{   Converts an obsolete statistic to match the current statistic format and returns pointers to the
{   components of the statistic.

    PROCEDURE parse_obsolete_statistic
      (    log_entry_p: ^lgt$log_entry;
       VAR statistic_header_p: ^sft$statistic_header;
       VAR counters_p: sft$counters;
       VAR descriptive_data: ^sft$descriptive_data;
       VAR status: ost$status);

      TYPE
        sft$obsolete_statistic_header = record
          date_time: ost$date_time,
          statistic_code: sft$statistic_code,
          job_name: jmt$system_supplied_name,
          task_id: ost$global_task_id,
          number_of_counters: 0 .. 255,
          descriptive_data_size: 0 .. 255,
        recend;

      VAR
        local_log_entry_p: ^lgt$log_entry,
        obsolete_statistic_buffer_p: ^sft$statistic_buffer,
        obsolete_statistic_header_p: ^sft$obsolete_statistic_header,
        obsolete_statistic_counters_p: sft$counters,
        obsolete_statistic_desc_data_p: ^sft$descriptive_data;

      status.normal := TRUE;

{ Make sure log entry is in a sequence that matches the size of the obsolete statistic buffer.

      IF #SIZE (log_entry_p^) < #SIZE (sft$statistic_buffer) THEN
        osp$set_status_abnormal ('LG', lge$statistic_buffer_required, 'LGP$PARSE_STATISTIC', status);
        RETURN;
      IFEND;

      local_log_entry_p := log_entry_p;
      RESET local_log_entry_p;
      PUSH obsolete_statistic_buffer_p;
      obsolete_statistic_buffer_p^ := log_entry_p^;
      RESET obsolete_statistic_buffer_p;

{ Get a pointer to the obsolete statistic header.

      NEXT obsolete_statistic_header_p IN obsolete_statistic_buffer_p;
      IF obsolete_statistic_header_p = NIL THEN
        osp$set_status_condition (lge$corrupted_statistic, status);
        RETURN;
      IFEND;

{ Translate the obsolete statistic header into the current format for the statistic header.

      NEXT statistic_header_p IN local_log_entry_p;
      IF statistic_header_p = NIL THEN
        osp$set_status_condition (lge$corrupted_statistic, status);
        RETURN;
      IFEND;
      statistic_header_p^.version := sfc$statistic_version;
      statistic_header_p^.date_time := obsolete_statistic_header_p^.date_time;
      statistic_header_p^.statistic_code := obsolete_statistic_header_p^.statistic_code;
      statistic_header_p^.job_name := obsolete_statistic_header_p^.job_name;
      statistic_header_p^.task_id := obsolete_statistic_header_p^.task_id;
      statistic_header_p^.number_of_counters := obsolete_statistic_header_p^.number_of_counters;
      statistic_header_p^.descriptive_data_size := obsolete_statistic_header_p^.descriptive_data_size;

{ Get a pointer to the counters (if there are any).

      IF statistic_header_p^.number_of_counters <> 0 THEN
        NEXT obsolete_statistic_counters_p: [1 .. statistic_header_p^.number_of_counters] IN
              obsolete_statistic_buffer_p;
        IF obsolete_statistic_counters_p = NIL THEN
          osp$set_status_condition (lge$corrupted_statistic, status);
          RETURN;
        IFEND;
        NEXT counters_p: [1 .. statistic_header_p^.number_of_counters] IN local_log_entry_p;
        IF counters_p = NIL THEN
          osp$set_status_condition (lge$corrupted_statistic, status);
          RETURN;
        IFEND;
        counters_p^ := obsolete_statistic_counters_p^;
      ELSE
        counters_p := NIL;
      IFEND;

{ Get a pointer to the descriptive data.

      IF statistic_header_p^.descriptive_data_size <> 0 THEN
        NEXT obsolete_statistic_desc_data_p: [statistic_header_p^.descriptive_data_size] IN
              obsolete_statistic_buffer_p;
        IF obsolete_statistic_desc_data_p = NIL THEN
          osp$set_status_condition (lge$corrupted_statistic, status);
          RETURN;
        IFEND;
        NEXT descriptive_data_p: [statistic_header_p^.descriptive_data_size] IN local_log_entry_p;
        IF descriptive_data_p = NIL THEN
          osp$set_status_condition (lge$corrupted_statistic, status);
          RETURN;
        IFEND;
        descriptive_data_p^ := obsolete_statistic_desc_data_p^;
      ELSE
        descriptive_data_p := NIL;
      IFEND;

    PROCEND parse_obsolete_statistic;
?? OLDTITLE, EJECT ??
    status.normal := TRUE;
    local_log_entry_p := log_entry_p;
    RESET local_log_entry_p;

{ Get a pointer to the statistic header.  If the log entry is not large enough to hold a statistic header
{ it must be an old style statistic.

    NEXT statistic_header_p IN local_log_entry_p;
    IF (statistic_header_p = NIL) OR (statistic_header_p^.version <> sfc$statistic_version) THEN
      parse_obsolete_statistic (log_entry_p, statistic_header_p, counters_p, descriptive_data_p, status);
    ELSE

{ Get a pointer to the counters (if there are any).

      IF statistic_header_p^.number_of_counters <> 0 THEN
        NEXT counters_p: [1 .. statistic_header_p^.number_of_counters] IN local_log_entry_p;
        IF counters_p = NIL THEN
          osp$set_status_condition (lge$corrupted_statistic, status);
          RETURN;
        IFEND;
      ELSE
        counters_p := NIL;
      IFEND;

{ Get a pointer to the descriptive data.

      IF statistic_header_p^.descriptive_data_size <> 0 THEN
        NEXT descriptive_data_p: [statistic_header_p^.descriptive_data_size] IN local_log_entry_p;
        IF descriptive_data_p = NIL THEN
          osp$set_status_condition (lge$corrupted_statistic, status);
          RETURN;
        IFEND;
      ELSE
        descriptive_data_p := NIL;
      IFEND;
    IFEND;

  PROCEND lgp$parse_statistic;
?? OLDTITLE ??
MODEND lgm$get_next_statistic;
