-- TempFileManager.mesa
-- created by Schroeder, November 18, 1980  9:19 PM

DIRECTORY
  crD: FROM "CoreDefs",
  exD: FROM "ExceptionDefs",
  intCommon: FROM "IntCommon",
  ovD: FROM "OverviewDefs",
  Storage,
  String,
  tfD: FROM "TempFileDefs";


TempFileManager: MONITOR
  IMPORTS crD, exD, intC:intCommon, Storage, String
  EXPORTS tfD
  = BEGIN

TempFile: TYPE = RECORD[c: CARDINAL, h: crD.UFileHandle,
  n: POINTER TO TempFile];

alloc: POINTER TO TempFile ← NIL; --checked out temp files
free: POINTER TO TempFile ← NIL; --freed temp files
tmpFileCntr: CARDINAL ← 100;


AllocateTempFile: PUBLIC ENTRY PROCEDURE
    RETURNS [crD.UFileHandle] =
BEGIN
t: POINTER TO TempFile;
fnm: STRING ← [10];
erc: ovD.ErrorCode;
IF free = NIL
  THEN BEGIN -- generate a new temp file node
    t ← Storage.Node[SIZE[TempFile]];
    IF (tmpFileCntr ← tmpFileCntr - 1) = 0 THEN exD.SysBug[];
    t.c ← tmpFileCntr;
    END
  ELSE BEGIN -- take one from free list
    t ← free;
    free ← t.n; 
    END;
t.n ← alloc;
alloc ← t;
String.AppendString[fnm, "DMS-"L];
String.AppendDecimal[fnm, t.c];
String.AppendString[fnm, ".TMP"L];
[erc, t.h] ← crD.OpenFile[intC.user, fnm, update];
IF erc # ovD.ok THEN exD.SysBug[];
RETURN[t.h];
END; -- of AllocateTempFile --


FreeTempFile: PUBLIC ENTRY PROCEDURE [h: crD.UFileHandle] =
BEGIN
current: POINTER TO TempFile;
previous: POINTER TO TempFile ← NIL;
FOR current ← alloc, current.n UNTIL current = NIL DO
  IF current.h = h THEN EXIT;
  previous ← current;
  REPEAT FINISHED => exD.SysBug[];
  ENDLOOP;
IF previous = NIL
  THEN alloc ← current.n
  ELSE previous.n ← current.n;
current.n ← free;
free ← current;
IF crD.UFileLength[current.h].lastPage > 3
  AND crD.UFileTruncate[4, 0, current.h] # ovD.ok
    THEN exD.SysBug[];
IF crD.CloseFile[current.h] # ovD.ok THEN exD.SysBug[];
current.h ← NIL;
END; -- of FreeTempFile --


END.