DIRECTORY Basics, CedarProcess, FSBackdoor, IO, MakeDo, MakeDoPrivate, Process, RedBlackTree, Rope; MakeDoUpNodes: CEDAR MONITOR LOCKS n.up USING n: Node IMPORTS CedarProcess, FSBackdoor, IO, MakeDo, MakeDoPrivate, RedBlackTree EXPORTS MakeDo, MakeDoPrivate = BEGIN OPEN MakeDo, MakeDoPrivate; NodeRep: PUBLIC TYPE = MakeDoPrivate.NodeRep; CommandRep: PUBLIC TYPE = MakeDoPrivate.CommandRep; GetCreated: PUBLIC ENTRY PROC [n: Node] RETURNS [t: Time] = { ENABLE UNWIND => {}; t _ InnerGetCreated[n]; }; InnerGetCreated: INTERNAL PROC [n: Node] RETURNS [t: Time] = { IF NOT n.timeValid THEN { IF n.forceNotExist THEN ERROR; n.created _ n.class.GetTime[n]; n.timeValid _ TRUE; IF debugging THEN { IF n.created # notExistTime THEN Log[0, "Created[%g]=%g", IO.rope[n.name], IO.time[n.created]] ELSE Log[0, "Created[%g]=never", IO.rope[n.name]]; }; }; t _ n.created; }; SuspectNodeChange: PUBLIC PROC [n: Node, stack: Table] = {ReallySuspectNodeChange[n, leaveNotExist, stack]}; ReallySuspectNodeChange: PUBLIC PROC [n: Node, op: NTOp, stack: Table] = { InnerReset: INTERNAL PROC [n: Node] = { ENABLE UNWIND => {}; SELECT op FROM unforceNotExist => n.forceNotExist _ n.timeValid _ FALSE; forceNotExist => { n.timeValid _ n.forceNotExist _ TRUE; n.created _ notExistTime; IF debugging THEN Log[0, "Created[%g] forced never", IO.rope[n.name]]; }; leaveNotExist => IF NOT n.forceNotExist THEN n.timeValid _ FALSE ELSE IF NOT n.timeValid THEN ERROR; ENDCASE => ERROR; }; Inner: ENTRY PROC [n: Node] = { ENABLE UNWIND => {}; For: INTERNAL PROC [which: CmdDep] = { created: Time _ InnerGetCreated[n]; FOR e: Edge _ n.to[which].first, e.nNext WHILE e # NIL DO IF e.n # n THEN ERROR; IF created # e.traverseCreated THEN { CmdMayNeedRemaking[e.c, which, stack]; }; ENDLOOP; which _ which; }; InnerReset[n]; For[cmd]; For[data]; }; IF debugging THEN Log[0, "%g may have changed", IO.rope[n.name]]; IF stack.Lookup[n] # NIL THEN RETURN; stack.Insert[n, n]; Inner[n !UNWIND => [] _ stack.Delete[n]]; [] _ stack.Delete[n]; }; NodeMayNeedRemaking: PUBLIC PROC [n: Node, stack: Table] = { Inner: ENTRY PROC [n: Node] = { ENABLE UNWIND => {}; For: INTERNAL PROC [which: CmdDep] = { which _ which; FOR e: Edge _ n.to[which].first, e.nNext WHILE e # NIL DO IF e.n # n THEN ERROR; CmdMayNeedRemaking[e.c, which, stack]; ENDLOOP; which _ which; }; IF n.suspect THEN RETURN; n.suspect _ TRUE; IF debugging THEN Log[0, "%g may need remaking", IO.rope[n.name]]; For[cmd]; For[data]; }; IF stack.Lookup[n] # NIL THEN RETURN; stack.Insert[n, n]; Inner[n !UNWIND => [] _ stack.Delete[n]]; [] _ stack.Delete[n]; }; EnumerateConsumers: PUBLIC ENTRY PROC [n: Node, which: CmdDep, to: PROC [Command, CmdDep]] = { x: BOOL _ FALSE; x _ x; FOR e: Edge _ n.to[which].first, e.nNext WHILE e # NIL DO to[e.c, which]; ENDLOOP; x _ x; }; EnumerateConsumerEdges: PUBLIC ENTRY PROC [n: Node, which: CmdDep, to: PROC [Edge, CmdDep]] = { x: BOOL _ FALSE; x _ x; FOR e: Edge _ n.to[which].first, e.nNext WHILE e # NIL DO to[e, which]; ENDLOOP; x _ x; }; UnlinkToFrom: PUBLIC PROC [e: Edge--on n.to=c.from--, which: CmdDep] = { Inner: ENTRY PROC [n: Node] = { ENABLE UNWIND => ERROR; IF e.n # n THEN ERROR; IF e.nNext # NIL THEN e.nNext.nPrev _ e.nPrev ELSE SELECT which FROM cmd => n.to[cmd].last _ e.nPrev; data => n.to[data].last _ e.nPrev; ENDCASE => ERROR; IF e.nPrev # NIL THEN e.nPrev.nNext _ e.nNext ELSE SELECT which FROM cmd => n.to[cmd].first _ e.nNext; data => n.to[data].first _ e.nNext; ENDCASE => ERROR; e.nNext _ e.nPrev _ NIL; }; Inner[e.n]; }; ShouldRemakeNode: PUBLIC ENTRY PROC [n: Node, callerPromisesToDoIt: BOOL] RETURNS [suspect: BOOL] = { ENABLE UNWIND => {}; IF (suspect _ n.suspect) AND callerPromisesToDoIt THEN n.suspect _ FALSE; }; fsWatchEnabled: BOOL _ TRUE; WatchFS: PROC [REF ANY] RETURNS [REF ANY _ NIL] = { ce: REF READONLY FSBackdoor.CreateEvent _ NIL; stack: Table _ NewRefTable[]; WHILE fsWatchEnabled DO ce _ FSBackdoor.NextCreateEvent[ce]; {ENABLE ABORTED => CONTINUE; n: Node _ GetNode[ce.fName, fileClass, FALSE]; IF n # NIL THEN { IF stack.Size[] # 0 THEN { out: IO.STREAM = GetCommanderHandle[].out; out.PutRope["Filesystem watcher recovering.\n"]; stack.DestroyTable[]; }; SuspectNodeChange[n, stack]; }; }; ENDLOOP; ce _ ce; }; watcher: CedarProcess.Process; Start: PROC = { watcher _ CedarProcess.Fork[action: WatchFS, options: [inheritProperties: TRUE]]; }; Start[]; END. MakeDoUpNodes.Mesa Last Edited by: Spreitzer, September 3, 1985 2:52:58 pm PDT INVARIANT Data described in MakeDoPrivate are consistent. Κγ– "cedar" style˜code™J™;—K˜KšΟk œ#œ5˜cK˜šΠbx œœ˜Kšœœ˜Kšœœ%˜IKšœ˜Kšœ˜™ Jšœ/™/——K˜Kšœœ˜!K˜Kšœ œœ˜-Kšœ œœ˜3K˜š Οn œœœœ œ˜=Kšœœ˜Kšœ˜Kšœ˜—K˜šŸœœœ œ˜>šœœ œ˜Kšœœœ˜K˜Kšœœ˜šœ œ˜šœ˜Kšœœœ˜BKšœœ˜2—K˜—Kšœ˜—Kšœ˜K˜—K˜šŸœœœ˜8Kšœ3˜3—K˜šŸœœœ&˜JšŸ œœœ˜'Kšœœ˜šœ˜Kšœ3œ˜9šœ˜Kšœ œ˜%Kšœ˜Kšœ œ$œ˜FKšœ˜—šœœœ˜'Kšœ˜Kš œœœ œœ˜#—Kšœœ˜—K˜—šŸœœœ˜Kšœœ˜šŸœœœ˜&K˜#šœ&œœ˜9Kšœ œœ˜šœœ˜%Kšœ&˜&K˜—Kšœ˜—Kšœ˜K˜—K˜K˜ K˜ K˜—Kšœ œœ˜AKšœœœœ˜%K˜Kšœ œ˜)K˜K˜—K˜šŸœœœ˜<šŸœœœ˜Kšœœ˜šŸœœœ˜&Kšœ˜šœ&œœ˜9Kšœ œœ˜K˜&Kšœ˜—Kšœ˜K˜—Jšœ œœ˜Jšœ œ˜Kšœ œ œ˜BJ˜ J˜ K˜—Kšœœœœ˜%K˜Kšœ œ˜)K˜K˜—K˜š Ÿœœœœœ˜^Kšœœœ˜Kšœ˜šœ&œœ˜9K˜Kšœ˜—Kšœ˜K˜—K˜š Ÿœœœœœ˜_Kšœœœ˜Kšœ˜šœ&œœ˜9K˜ Kšœ˜—Kšœ˜K˜—K˜šŸ œœœ Οcœ˜HšŸœœœ˜Kšœœœ˜Kšœ œœ˜Kšœ œœœœœEœœ˜šKšœ œœœœœGœœ˜œKšœœ˜K˜—K˜ K˜—K˜šŸœœœœ!œœ œ˜eKšœœ˜Kšœœœ œ˜IK˜—K˜Kšœœœ˜K˜šŸœœœœœœœœ˜3Kšœœœœ˜.Kšœ˜šœ˜K˜$Kšœœœœ˜Kšœ'œ˜.šœœœ˜šœœ˜Kšœœœ˜*K˜0K˜K˜—Kšœ˜Kšœ˜—K˜Kšœ˜—K˜K˜—K˜Kšœ˜K˜šŸœœ˜KšœJœ˜QK˜—K˜K˜K˜Kšœ˜—…—(›