--Transport Mechanism Filestore - Mailbox restart -- -- [Indigo]<Grapevine>MS>MailboxRestart.mesa -- Andrew Birrell 10-Sep-82 16:37:56 -- DIRECTORY BitMapDefs USING[ Create, Set ], BodyDefs USING[ oldestTime, RName, Timestamp ], BTreeDefs USING[ CreateAndInitializeBTree, NullProc ], MailboxAlloc, ObjectDirDefs USING[ noObject, ObjectNumber, RestartObject ], RestartDefs, --EXPORT only-- VMDefs USING[ OpenFile, Page, ReadPage, Release, MarkStartWait, PageIndex, PageNumber, GetFileLength ]; MailboxRestart: MONITOR[ initHeap: BOOLEAN ] IMPORTS BitMapDefs, BTreeDefs, MailboxAlloc, ObjectDirDefs, VMDefs EXPORTS RestartDefs --MailboxRestart-- SHARES MailboxAlloc = BEGIN OPEN MailboxAlloc; initMBX: BOOLEAN ← FALSE; maxMBXPages: CARDINAL ← 4000; DuplicatePage: ERROR = CODE; Init: ENTRY PROCEDURE = BEGIN pos: VMDefs.PageNumber; handle ← VMDefs.OpenFile[options:oldOrNew, name: "MBX.Mailboxes"L, cacheFraction: 0]; lockMap ← BitMapDefs.Create[maxMBXPages]; pageMap ← BitMapDefs.Create[maxMBXPages]; conflictMap ← BitMapDefs.Create[maxMBXPages]; tree ← BTreeDefs.CreateAndInitializeBTree [ fileH: LOOPHOLE[VMDefs.OpenFile[options:oldOrNew, name: "MBX.BTree", cacheFraction: 10] ], initializeFile: TRUE, useDefaultOrderingRoutines: TRUE, isFirstGreaterOrEqual: BTreeDefs.NullProc, areTheyEqual: BTreeDefs.NullProc ]; nextVirginPage ← VMDefs.GetFileLength[handle].page; FOR pos IN [0 .. nextVirginPage ) DO BEGIN page: VMDefs.Page = VMDefs.ReadPage[[handle,pos],lookAhead]; base: VMDefs.PageIndex = FIRST[VMDefs.PageIndex]; header: POINTER TO MBXHeader = LOOPHOLE[page,POINTER]+base; IF initMBX OR initHeap THEN BEGIN header.first←header.free; VMDefs.MarkStartWait[ page ]; END; IF header.first # header.free THEN BEGIN buffer: DESCRIPTOR FOR ARRAY OF ObjectDirDefs.ObjectNumber; index: CARDINAL; rName: BodyDefs.RName = LOOPHOLE[page,POINTER] +base+SIZE[MBXHeader]; otherValue: TreeRec = FindInTree[rName]; otherN: CARDINAL; oldest: BodyDefs.Timestamp; -- estimate of oldest in mailbox -- timeWantedInThisPage: BOOLEAN; WITH otherV: otherValue SELECT FROM empty => { oldest ← BodyDefs.oldestTime; timeWantedInThisPage ← TRUE }; found => BEGIN otherP: VMDefs.Page = VMDefs.ReadPage[[handle,otherV.where],0]; otherH: POINTER TO MBXHeader = LOOPHOLE[otherP,POINTER] + base; otherN ← otherH.number; IF header.number = otherN THEN ERROR DuplicatePage[]; oldest ← otherV.oldest; timeWantedInThisPage ← (otherN > header.number OR oldest = BodyDefs.oldestTime); VMDefs.Release[otherP]; END; ENDCASE => ERROR; BitMapDefs.Set[pageMap, pos]; buffer ← DESCRIPTOR[page+header.first, (header.free-header.first)/SIZE[ObjectDirDefs.ObjectNumber] ]; FOR index IN [0..LENGTH[buffer]) DO IF buffer[index].type = TOC THEN ObjectDirDefs.RestartObject[buffer[index]]; IF buffer[index] # ObjectDirDefs.noObject THEN BEGIN body: ObjectDirDefs.ObjectNumber = GetBodyObj[buffer[index]]; ObjectDirDefs.RestartObject[body]; IF timeWantedInThisPage AND body.type # archived THEN BEGIN oldest ← ReadPostmark[body]; timeWantedInThisPage ← FALSE; END; END; mailboxContents ← mailboxContents + 1; ENDLOOP; WITH otherV: otherValue SELECT FROM empty => BEGIN ChangeInTree[who:rName, where:pos, lock:pos, oldest:oldest]; mailboxes ← mailboxes+1; END; found => ChangeInTree[who:rName, where: IF header.number > otherN THEN pos ELSE otherV.where, lock: IF header.number = 0 THEN pos ELSE otherV.lock, oldest:oldest]; ENDCASE => ERROR; END; VMDefs.Release[page]; END ENDLOOP; END; ArchiverProcess: PROCESS; START MailboxAlloc; Init[]; ArchiverProcess ← FORK MailboxAlloc.Archiver[]; END.