<> <> DIRECTORY Basics, BasicTime, CedarProcess, Convert, FS, FSBackdoor, IO, MakeDo, PrincOpsUtils, Process, RedBlackTree, Rope, UserProfile, ViewerClasses, ViewerIO; MakeDoFiles: CEDAR MONITOR IMPORTS BasicTime, CedarProcess, Convert, FS, FSBackdoor, IO, MakeDo, Rope, UserProfile EXPORTS MakeDo = BEGIN OPEN MakeDo; fileClass: PUBLIC NodeClass _ DeclareNodeClass[ name: "file", CanonizeName: CannonizeFileName, GetTime: GetFileTime ]; CannonizeFileName: PROC [random: ROPE] RETURNS [canonical: ROPE] = { full: ROPE; cp: FS.ComponentPositions; [full, cp] _ FS.ExpandName[random]; canonical _ full.Substr[len: cp.ext.start + cp.ext.length]; }; GetFileTime: PUBLIC PROC [n: Node] RETURNS [created: Time] --GetTimeProc-- = BEGIN name: ROPE = n.PublicPartsOfNode[].name; <> [created: created] _ FS.FileInfo[name !FS.Error => {created _ notExistTime; CONTINUE}]; END; localOpNames: ARRAY FSBackdoor.CreateOp OF ATOM = [ writeClose: $writeClose, renameTo: $renameTo, copyTo: $copyTo ]; remoteOpNames: ARRAY FSBackdoor.RemoteOp OF ATOM = [ startRetrieving: $startRetrieving, endRetrieving: $endRetrieving, startStoring: $startStoring, endStoring: $endStoring, startDeleting: $startDeleting, endDeleting: $endDeleting, startRenaming: $startRenaming, endRenaming: $endRenaming, startFlushing: $startFlushing, endFlushing: $endFlushing ]; EventList: TYPE = LIST OF Event; Event: TYPE = RECORD [ start, finish: BasicTime.GMT _ BasicTime.nullGMT, local: BOOL, op: ATOM, fName: ROPE]; fsWatchEnabled: BOOL _ TRUE; logFSWatch: BOOL _ FALSE; logHead, logTail: EventList _ NIL; WatchFSLocal: PROC [REF ANY] RETURNS [REF ANY _ NIL] = { ce: REF READONLY FSBackdoor.CreateEvent _ NIL; WHILE fsWatchEnabled DO me: EventList _ NIL; ce _ FSBackdoor.NextCreateEvent[ce]; IF logFSWatch THEN me _ Log[[ start: BasicTime.Now[], local: TRUE, op: localOpNames[ce.op], fName: ce.fName]]; {ENABLE ABORTED => CONTINUE; n: Node _ GetNode[ce.fName, fileClass, FALSE]; IF n # NIL THEN { SuspectNodeChange[n]; }; }; IF me#NIL THEN me.first.finish _ BasicTime.Now[]; ENDLOOP; ce _ ce; }; WatchFSRemote: PROC [REF ANY] RETURNS [REF ANY _ NIL] = { re: REF READONLY FSBackdoor.RemoteEvent _ NIL; WHILE fsWatchEnabled DO me: EventList _ NIL; re _ FSBackdoor.NextRemoteEvent[re]; IF logFSWatch THEN me _ Log[[ start: BasicTime.Now[], local: FALSE, op: remoteOpNames[re.op], fName: re.fName]]; {ENABLE ABORTED => CONTINUE; n: Node _ GetNode[re.fName, fileClass, FALSE]; IF n # NIL THEN { SuspectNodeChange[n]; }; }; IF me#NIL THEN me.first.finish _ BasicTime.Now[]; ENDLOOP; re _ re; }; localWatcher, remoteWatcher: CedarProcess.Process; Log: ENTRY PROC [e: Event] RETURNS [el: EventList] = { ENABLE UNWIND => NULL; el _ LIST[e]; IF logTail = NIL THEN logHead _ el ELSE logTail.rest _ el; logTail _ el; }; PrintLog: PROC [to: IO.STREAM] = { FOR log: EventList _ logHead, log.rest WHILE log # NIL DO to.PutF[ "%g-%g: %g[%g]\n", [rope[Convert.RopeFromTime[from: log.first.start, start: days, end: seconds, useAMPM: FALSE, includeZone: FALSE]]], [rope[Convert.RopeFromTime[from: log.first.finish, start: hours, end: seconds, useAMPM: FALSE, includeZone: FALSE]]], [atom[log.first.op]], [rope[log.first.fName]]]; ENDLOOP; }; NoteProfile: PROC [reason: UserProfile.ProfileChangeReason] --UserProfile.ProfileChangedProc-- = { logFSWatch _ UserProfile.Boolean["MakeDo.LogFSWatch", FALSE]; }; Start: PROC = { UserProfile.CallWhenProfileChanges[NoteProfile]; localWatcher _ CedarProcess.Fork[action: WatchFSLocal, options: [inheritProperties: TRUE]]; remoteWatcher _ CedarProcess.Fork[action: WatchFSRemote, options: [inheritProperties: TRUE]]; }; Start[]; END.