-- Transport Mechanism Mail Server - SL Restart --
-- [Juniper]<Grapevine>MS>SLRestart.mesa
-- Randy Gobbel 19-May-81 12:48:15 --
-- Andrew Birrell September 13, 1982 3:43 pm --
DIRECTORY
LogDefs USING[ DisplayNumber, WriteLogEntry ],
ObjectDirDefs USING[ RestartObject ],
Process USING[ InitializeCondition, DisableTimeout ],
RestartDefs --EXPORT only--,
SLDefs USING[ SLQueue, ItemIndex, ItemAddress, Item ],
SLQueueImpl: FROM "SLQueue",
VMDefs USING[ Page, PageNumber, GetFileLength, OpenFile,
FileHandle, UsePage, Release ];
SLRestart: PROGRAM[ initHeap:BOOLEAN ]
IMPORTS LogDefs, ObjectDirDefs, SLQueueImpl, Process, VMDefs
EXPORTS RestartDefs -- PROGRAM --
SHARES SLQueueImpl =
BEGIN
RestartQueues: PROCEDURE =
BEGIN
OPEN SLQueueImpl;
SLTitle: ARRAY SLDefs.SLQueue OF STRING =
[ express: "SLQueue.Express"L,
input: "SLQueue.Input"L,
forward: "SLQueue.Forward"L,
pending: "SLQueue.Pending"L,
foreign: "SLQueue.Foreign"L,
mailbox: "SLQueue.Mailbox"L ];
SLName: ARRAY SLDefs.SLQueue OF STRING =
[ express: "Express queue"L,
input: "Input queue"L,
forward: "Forward queue"L,
pending: "Pending queue"L,
foreign: "IFS/MAXC queue"L,
mailbox: "Mailbox queue"L ];
FOR index: SLDefs.SLQueue IN SLDefs.SLQueue
DO BEGIN
handle: VMDefs.FileHandle =
VMDefs.OpenFile[options:oldOrNew,
name: SLTitle[index], cacheFraction: 2];
firstPos: SLDefs.ItemAddress = [ page: [ file: handle, page: 0 ],
item: FIRST[SLDefs.ItemIndex] ];
newFile: BOOLEAN;
data[index].size ← VMDefs.GetFileLength[ handle ].page;
newFile ← data[index].size = 0;
IF newFile
THEN BEGIN
data[index].size ← 1 --cause extension to 1 pages--;
LogDefs.WriteLogEntry["New SL-queue file created"L];
END;
IF initHeap OR newFile
THEN BEGIN -- initialise with empty queue --
p: VMDefs.PageNumber;
FOR p IN [ FIRST[VMDefs.PageNumber] .. data[index].size )
DO IF page # NIL THEN VMDefs.Release[LOOPHOLE[page,VMDefs.Page]];
page ← LOOPHOLE[VMDefs.UsePage[dataPos←[handle,p]],SLQPage];
BEGIN
index: SLDefs.ItemIndex;
FOR index IN SLDefs.ItemIndex
DO page[index].state ← free ENDLOOP;
END;
ReleaseData[dirty];
ENDLOOP;
END;
Process.InitializeCondition[ @(data[index].itemWritten), 1];
Process.DisableTimeout[ @(data[index].itemWritten) ];
-- Adjust object reference counts --
BEGIN
pos: SLDefs.ItemAddress ← firstPos;
count[index] ← 0; -- count of SL's in this queue --
DO BEGIN
ptr: POINTER TO SLDefs.Item = GetItem[pos];
state: DataState ← clean;
IF ptr.state = reading THEN { ptr.state ← full; state ← dirty };
IF ptr.state = full
THEN BEGIN
ObjectDirDefs.RestartObject[ptr.body];
ObjectDirDefs.RestartObject[ptr.SL];
count[index] ← count[index] + 1;
END;
ReleaseData[state];
NextItem[index, @pos];
IF pos = firstPos THEN EXIT;
END;
ENDLOOP;
END;
-- find reader position: skip optional full, then all free items --
data[index].rPos ← firstPos;
DO ptr: POINTER TO SLDefs.Item = GetItem[data[index].rPos];
IF ptr.state = free THEN { ReleaseData[clean]; EXIT };
ReleaseData[clean];
NextItem[index, @(data[index].rPos)];
IF data[index].rPos = firstPos THEN EXIT --all items full--;
ENDLOOP;
BEGIN
started: SLDefs.ItemAddress = data[index].rPos;
DO ptr: POINTER TO SLDefs.Item = GetItem[data[index].rPos];
IF ptr.state # free THEN { ReleaseData[clean]; EXIT };
ReleaseData[clean];
NextItem[index, @(data[index].rPos)];
IF data[index].rPos = started THEN EXIT --all items free--;
ENDLOOP;
END;
-- find writer position: after all full items --
data[index].wPos ← data[index].rPos;
DO ptr: POINTER TO SLDefs.Item ← GetItem[data[index].wPos];
IF ptr.state = free THEN { ReleaseData[clean]; EXIT };
ReleaseData[clean];
NextItem[index, @(data[index].wPos)];
IF data[index].wPos = data[index].rPos THEN EXIT;
ENDLOOP;
LogDefs.DisplayNumber[ SLName[index], [short[@(count[index])]] ];
END
ENDLOOP;
LogDefs.DisplayNumber[ "Messages received"L, [short[@received]] ];
-- LogDefs.DisplayNumber[ "Messages re-processed"L, [short[@reDone]] ];
END;
START SLQueueImpl; RestartQueues[];
END.