-- 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.