-- Copyright (C) 1985  by Xerox Corporation. All rights reserved. 
-- LogRejection.mesa, HGM, 18-Sep-85  3:37:15

-- This gets called from the Listener process. We can't just print the message because
-- the log might overflow onto a new page. Then we end up deep in the VM machinery,
-- and it might need a Pup Buffer. Buffer lockups have happened.

-- NB: String must not be Local.

DIRECTORY
  Heap USING [systemZone],
  LogDefs USING [WriteLine, WriteLogEntry],
  String USING [AppendDecimal, AppendString],
  PupDefs USING [AppendHostName],
  PupTypes USING [PupAddress];

LogRejection: MONITOR
  IMPORTS Heap, LogDefs, PupDefs, String
  EXPORTS LogDefs =
  BEGIN
  
  Rejection: TYPE = LONG POINTER TO RejectionRecord;
  RejectionRecord: TYPE = RECORD [
    next: Rejection,
    what: LONG STRING,
    who: PupTypes.PupAddress,
    count: CARDINAL ];
  
  ready: Rejection ← NIL;
  waiting: CONDITION;
  printer: PROCESS ← FORK Printer[];
  
  ShowRejection: PUBLIC ENTRY PROCEDURE [what: LONG STRING, who: PupTypes.PupAddress] =
    BEGIN
    new: Rejection;
    FOR finger: Rejection ← ready, finger.next UNTIL finger = NIL DO
      IF what = finger.what AND who = finger.who THEN {
        finger.count ← finger.count + 1; RETURN; };
      ENDLOOP;
    new ← Heap.systemZone.NEW[RejectionRecord];
    new↑ ← [
      next: NIL,
      what: what,
      who: who,
      count: 1 ];
    AppendReady[new];
    END;
    
  AppendReady: INTERNAL PROCEDURE [rejection: Rejection] =
    BEGIN
    rejection.next ← NIL;
    IF ready = NIL THEN ready ← rejection
    ELSE
      FOR finger: Rejection ← ready, ready.next DO
        IF finger.next = NIL THEN finger.next ← rejection; EXIT;
	ENDLOOP;
    NOTIFY waiting;
    END;
    
  GetReady: ENTRY PROCEDURE RETURNS [rejection: Rejection] =
    BEGIN
    UNTIL ready # NIL DO WAIT waiting; ENDLOOP;
    rejection ← ready;
    ready ← ready.next;
    END;
    
  Printer: PROCEDURE =
    BEGIN
    DO
      rejection: Rejection ← GetReady[];
      log: LONG STRING ← Heap.systemZone.NEW[StringBody[500]];
      String.AppendString[log, "Rejecting "L];
      String.AppendString[log, rejection.what];
      String.AppendString[log, " connection from "L];
      PupDefs.AppendHostName[log, rejection.who];
      IF rejection.count # 1 THEN {
        String.AppendString[log, " count = "L];
        String.AppendDecimal[log, rejection.count]; };
      LogDefs.WriteLogEntry[log];
      LogDefs.WriteLine[log];
      Heap.systemZone.FREE[@rejection];
      Heap.systemZone.FREE[@log];
      ENDLOOP;
    END;
    
  END.