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