MODULE mod_logfile_server ;
{ Created   5-JUL-1989   MICHIGAN STATE UNIVERSITY, TRIGGER CONTROL SOFTWARE  }
{ Modified 25-OCT-1990   implement mode "SINCE"                               }
{ Modified 25-OCT-1990   records are transefered 15 at a time                 }
{ Modified 26-OCT-1990   implement mode "LAST"                                }
{ Modified 12-JUL-1991   add log server job logfile                           }
{ Modified 18-FEB-1993   use new exception handler routines and flush_to_file }
{ *************************************************************************** }
INCLUDE
  mod_handle_console,
  mod_handle_logfile,
  mod_handle_tracing,
  $FILE_UTILITY,      { from ELN$:RTLOBJECT.OLB                               }
  $GET_MESSAGE_TEXT,  { from ELN$:RTLOBJECT.OLB                               }
  $KERNELMSG ;        { from ELN$:RTLOBJECT.OLB                               }
{ *************************************************************************** }
IMPORT
  find_console_lock,                  {from module MOD_HANDLE_CONSOLE         }

  init_logfile,                       {from module MOD_HANDLE_LOGFILE         }

  trace_info, ON,                     {from module MOD_HANDLE_TRACING         }
  trace_error,                        {from module MOD_HANDLE_TRACING         }
  handle_trc_sys,                     {from module MOD_HANDLE_TRACING         }
  handle_trc_sta,                     {from module MOD_HANDLE_TRACING         }
  handle_trc_err,                     {from module MOD_HANDLE_TRACING         }
  handle_trc_inf,                     {from module MOD_HANDLE_TRACING         }
  inline_time_now,                    {from module MOD_HANDLE_TRACING         }
  init_flush_to_logfile,              {from module MOD_HANDLE_TRACING         }
  set_trc_exc_mode,                   {from module MOD_HANDLE_TRACING         }
  handle_exception,                   {from module MOD_HANDLE_TRACING         }

  FILE$ATTRIBUTES_RECORD,             {from module $FILE_UTILITY              }
  KER$_DUPLICATE,                     {from module $KERNELMSG                 }
  ELN$GET_STATUS_TEXT,                {from module $GET_MESSAGE_TEXT          }
  STATUS$FACILITY,                    {from module $GET_MESSAGE_TEXT          }
  STATUS$SEVERITY,                    {from module $GET_MESSAGE_TEXT          }
  STATUS$IDENT,                       {from module $GET_MESSAGE_TEXT          }
  STATUS$TEXT ;                       {from module $GET_MESSAGE_TEXT          }
{ *************************************************************************** }
  %INCLUDE 'SITE_DEPENDENT.CST/LIST'

{ *************************************************************************** }
PROGRAM log_server ( INPUT, OUTPUT );

CONST
  fixed_length = 132 ;

TYPE

  log_file = 
  PACKED RECORD
    name  : STRING(50) ;
    space1: STRING(1) ;
    mode  : STRING(5) ;
    space2: STRING(1) ;
    value : STRING(23) ;
  END ;    

VAR

  file_attributes     :^FILE$ATTRIBUTES_RECORD ;
  logfile_description : log_file ;
  logfile             : FILE OF STRING(fixed_length) ;
  remote_reader       : FILE OF VARYING_STRING(1980) ;
  record_num          : INTEGER ;
  status              : INTEGER ; {general use status buffer}
  bin_time            : LARGE_INTEGER ;
  buffer              : STRING(1980) ;
  time_now            : STRING(17) ;
  server_logfile      : VARYING_STRING(50) ;

  {the code for the exc.handler function must appear "inside" the procedure }
  {to allow the use of a GOTO statement in exc.handler}
      FUNCTION exchand_server OF TYPE EXCEPTION_HANDLER ; 
      BEGIN  

        set_trc_exc_mode ( TRUE ) ;

        exchand_server := handle_exception ( TAG := 'LOG/EXC%', 
                                        EXC_CODE := signal_args.name ) ;

        handle_trc_err ( TAG := 'LOG/EXC%', 
                     MESSAGE := ' Log Server Abort Reading File ' ) ;

        set_trc_exc_mode ( FALSE ) ;
        GOTO close_link ;

      END ;

BEGIN

  find_console_lock ( CALLER := 'LOG_SERVER' ) ;

  time_now := inline_time_now ;
  server_logfile := logfile_directory + 'LOG_SERVER_' + SUBSTR(time_now,1,2) 
           + SUBSTR(time_now,4,3) + SUBSTR(time_now,10,2) + '.LOG' ;
  trace_info.console  := ON ;   trace_info.logfile  := ON ;
  trace_error.console := ON ;   trace_error.logfile := ON ;
  init_logfile ( NAME := server_logfile, STATUS := status );

  init_flush_to_logfile ;

  {define an exception handler for this process block                    **** }
  ESTABLISH ( exchand_server ) ;

infinite_loop:

  OPEN ( remote_reader, FILE_NAME := log_server_circuit_name,
                          CIRCUIT := CIRCUIT$ACCEPT,
                           STATUS := status ) ;

  IF ( ( status MOD 8 ) <> 1 )
  THEN BEGIN
    handle_trc_err ( TAG := 'LOG/SRV%', MESSAGE := ' Error Opening Link ' ) ; 
    handle_trc_sta ( TAG := 'LOG/SRV%', STATUS := status ) ;
    IF ( status = KER$_DUPLICATE ) {dupl.name}
    THEN BEGIN 
      handle_trc_sys ( TAG := 'LOG/SRV%', MESSAGE := 'Quitting' ) ;
      EXIT ;
    END ;
  END ;

  RESET ( remote_reader ) ; {set read mode and read one message}
  logfile_description::STRING(SIZE(log_file)) := remote_reader^ ;

  REWRITE  ( remote_reader ) ; {set write mode}
  GET_TIME ( bin_time, STATUS := status ) ;
  WRITE    ( remote_reader, 'LOG SERVER OPENING LOG FILE ' 
                           + logfile_description.name 
                           + ' time: ' + TIME_STRING(bin_time) ) ;

  OPEN ( logfile, FILE_NAME := logfile_description.name,
                    HISTORY := HISTORY$READONLY,
              ACCESS_METHOD := ACCESS$DIRECT,
             RECORD_LOCKING := TRUE,
                DISPOSITION := DISPOSITION$SAVE,
                    SHARING := SHARE$READWRITE,
                     APPEND := FALSE,
                  BUFFERING := FALSE,
                 BUFFERSIZE := 4096,
            FILE_ATTRIBUTES := file_attributes,
                     STATUS := status ) ;

  IF ( ( status MOD 8 ) <> 1 )
  THEN BEGIN
    WRITE ( remote_reader, 'open_log_file' + sys_message(status) ) ;
    handle_trc_err ( TAG := 'LOG/SRV%', 
                 MESSAGE := ' Error Opening ' 
                          + logfile_description.name ) ;    
    handle_trc_sta ( TAG := 'LOG/SRV%open_file%', STATUS := status ) ;
    GOTO done_reading_log_file ;
  END ;

  handle_trc_inf ( TAG := 'LOG/SRV%', 
               MESSAGE := ' Log Server Opened ' 
                        + logfile_description.name ) ;    

  WRITE ( remote_reader, '-----------------------------------------------' ) ;

  RESET ( logfile ) ; {Set logfile in read mode and read first record }
  IF ( EOF ( logfile ) <> TRUE )
  THEN BEGIN 
    WRITE ( remote_reader, logfile^ ) ; {Send header line}
    WRITE ( remote_reader, '-----------------------------------------------' ) ;
    GET   ( logfile ) ; {get first real record}
  END ;

  record_num := 1 ;

  IF ( logfile_description.mode = 'LAST' ) 
  THEN BEGIN
    record_num := CONVERT ( INTEGER, logfile_description.value ) ;
    FIND ( logfile, record_num ) ;
  END ;

  IF ( logfile_description.mode = 'SINCE' ) 
  THEN BEGIN

    WRITE ( remote_reader, 'Only Transfer Records Written Since ' 
                          + logfile_description.value ) ;

    handle_trc_inf ( TAG := 'LOG/SRV%', 
                 MESSAGE := ' Searching for Records Written Since '  
                          + logfile_description.value ) ;

    WHILE ( EOF ( logfile ) <> TRUE )
    DO BEGIN
      IF ( SUBSTR(logfile^,110,11) = SUBSTR(logfile_description.value,1,11) )
      THEN GOTO found_requested_day ;
      GET ( logfile ) ;
      record_num := record_num + 1 ;
    END ;
   found_requested_day:

    WHILE ( EOF ( logfile ) <> TRUE )
    DO BEGIN
      IF ( SUBSTR(logfile^,122,11) >= SUBSTR(logfile_description.value,13,11) )
      THEN GOTO found_requested_time ;
      GET ( logfile ) ;
      record_num := record_num + 1 ;
    END ;
   found_requested_time:

  END ;

  IF ( ( record_num > 1 ) AND ( EOF ( logfile ) <> TRUE ) )
  THEN BEGIN
    WRITE ( remote_reader, 'Skip to Record # ' 
                          + CONVERT(STRING,record_num) ) ;
    WRITE ( remote_reader, '-----------------------------------------------' ) ;
    handle_trc_inf ( TAG := 'LOG/SRV%', 
                 MESSAGE := ' Skip to Record # ' 
                          + CONVERT(STRING,record_num) ) ;
  END ;

  WHILE ( EOF ( logfile ) <> TRUE )
  DO BEGIN

    buffer := ' ' ;

    FOR record_num := 1 TO 15  
    DO IF ( EOF ( logfile ) <> TRUE ) 
    THEN BEGIN
      SUBSTR ( buffer, 132*record_num-131, 132 ) := logfile^ ;
      GET ( logfile ) ;
    END ;

    WRITE ( remote_reader, buffer ) ;

  END ;

  WRITE   ( remote_reader, '--------------END-OF-LOG-FILE------------------' );

done_reading_log_file :
  WRITE ( remote_reader, 'CLOSING LOG FILE ' + logfile_description.name ) ;

close_link :
  CLOSE ( remote_reader ) ;

quit_reading_logfile :
  CLOSE ( logfile ) ;
  handle_trc_inf ( TAG := 'LOG/SRV%', 
               MESSAGE := ' Log Server Closed ' + logfile_description.name ) ;
  GOTO infinite_loop ; { forever }

END ;
{ *************************************************************************** }
{ *************************************************************************** }
FUNCTION sys_message ( status_to_decode : INTEGER ) : VARYING_STRING(255) ;

VAR   decoded_stat : VARYING_STRING(255) ;
BEGIN

  ELN$GET_STATUS_TEXT ( status_to_decode,
     [STATUS$TEXT,STATUS$IDENT,STATUS$SEVERITY,STATUS$FACILITY], decoded_stat);
  sys_message := decoded_stat ;

END ;
{ *************************************************************************** }
END.
