<> <> <> <> <<>> <> DIRECTORY BasicTime USING [Now], Commander USING [CommandProc, Register], CommandTool USING [ParseToList], Convert USING [RopeFromBool, RopeFromTime], Coordinator USING [Outcome, State], CoordinatorMap USING [Handle, LockedEnumerate], FS USING [ExpandName], IO USING [rope, Put, STREAM, time], List USING [Assoc], Menus USING [AppendMenuEntry, CreateEntry, Menu, MenuProc], ProcessProps USING [GetPropList], Rope USING [Cat, Equal, Index, ROPE, Substr], RopeList USING [CompareProc, IgnoreCase, Sort], SkiPatrolHooks USING [InactiveWorker, TestForAbort, TransIDToRope], SkiPatrolViewers USING [AddProps, AddSaveAndStore], TransactionMap USING [Handle, LockedEnumerate], ViewerClasses USING [Viewer], ViewerIO USING [CreateViewerStreams], ViewerOps USING [CreateViewer, SetMenu, SetNewVersion], Worker USING [Handle, State]; SkiPatrol: CEDAR PROGRAM IMPORTS BasicTime, Commander, CommandTool, Convert, CoordinatorMap, FS, IO, List, Menus, ProcessProps, Rope, RopeList, SkiPatrolHooks, SkiPatrolViewers, TransactionMap, ViewerIO, ViewerOps = BEGIN NO: BOOLEAN = FALSE; YES: BOOLEAN = TRUE; ROPE: TYPE = Rope.ROPE; <> workerStream: IO.STREAM; coordinatorStream: IO.STREAM; coordinatorStateToRope: ARRAY Coordinator.State OF ROPE = [ "active ", "collecting ", "completing ", "complete "]; workerStateToRope: ARRAY Worker.State OF ROPE = [ "unknown ", "active ", "preparing ", "ready ", "completing ", "fpmComplete ", "fpmCompleteBeingForcedOut ", "complete "]; outcomeToRope: ARRAY Coordinator.Outcome OF ROPE = ["abort", "commit", "unknown"]; <> coordinatorViewer: ViewerClasses.Viewer _ NIL; workerViewer: ViewerClasses.Viewer _ NIL; <> ShowCoordinators: Commander.CommandProc ~ { <> parmsList: LIST OF ROPE _ CommandTool.ParseToList[cmd].list; useOldViewer: BOOLEAN _ YES; aMenu: Menus.Menu; -- used to set the menu for the viewer. IF parmsList # NIL AND Rope.Equal[parmsList.first, "-n"] THEN useOldViewer _ NO; IF coordinatorViewer = NIL OR coordinatorViewer.destroyed THEN useOldViewer _ NO; IF NOT useOldViewer THEN { <> coordinatorViewer _ ViewerOps.CreateViewer[flavor: $Typescript, info: [iconic: NO, name: "Alpine Coordinators"]]; coordinatorViewer.file _ FS.ExpandName[name: "CoordinatorList", wDir: MyWDir[] ].fullFName; aMenu _ coordinatorViewer.menu; Menus.AppendMenuEntry[ menu: aMenu, entry: Menus.CreateEntry[ name: "Again", proc: ShowCoordinatorsAgain ] ]; SkiPatrolViewers.AddSaveAndStore[aMenu]; ViewerOps.SetMenu[viewer: coordinatorViewer, menu: aMenu]; SkiPatrolViewers.AddProps[viewer: coordinatorViewer, baseTitle: coordinatorViewer.name, WDir: MyWDir[]]; coordinatorStream _ ViewerIO.CreateViewerStreams[name: "", viewer: coordinatorViewer].out; }; ShowCoordinatorsCore[]; }; ShowCoordinatorsCore: PROC [] ~ { <> resultList: LIST OF ROPE _ NIL; -- one rope per coordinator; put in a list to be sorted ShowCoordinator: PROC [h:CoordinatorMap.Handle] RETURNS [stop: BOOLEAN] = { <> <> oneLine: ROPE; oneLine _ SkiPatrolHooks.TransIDToRope[transID: h.transID, includeRName: NO]; oneLine _ oneLine.Cat[" (", h.userRName, ")"]; oneLine _ oneLine.Cat["\t", coordinatorStateToRope[h.state]]; oneLine _ oneLine.Cat["\t", outcomeToRope[h.outcome]]; oneLine _ oneLine.Cat["\t", Convert.RopeFromBool[h.finishInProgress], "\n"]; resultList _ CONS[oneLine, resultList]; RETURN [stop: NO] }; ViewerOps.SetNewVersion[coordinatorViewer]; coordinatorStream.Put[IO.rope["\n\n----- "], IO.time[], IO.rope[" ------\n"]]; coordinatorStream.Put[IO.rope["TransID\t\t\t\t\t\tState\t\tOutcome\tFinishing\n"]]; TRUSTED {CoordinatorMap.LockedEnumerate[proc: ShowCoordinator]}; resultList _ RopeList.Sort[list: resultList, compareProc: RNameCompare]; FOR resultList _ resultList, resultList.rest WHILE resultList # NIL DO coordinatorStream.Put[IO.rope[resultList.first]]; ENDLOOP; coordinatorStream.Put[IO.rope["\n\n"]]; }; ShowCoordinatorsAgain: Menus.MenuProc ~ { <> ShowCoordinatorsCore[]; }; ShowWorkers: Commander.CommandProc = { <> parmsList: LIST OF ROPE _ CommandTool.ParseToList[cmd].list; useOldViewer: BOOLEAN _ YES; aMenu: Menus.Menu; -- used to set the menu for the viewer. IF parmsList # NIL AND Rope.Equal[parmsList.first, "-n"] THEN useOldViewer _ NO; IF workerViewer = NIL OR workerViewer.destroyed THEN useOldViewer _ NO; IF NOT useOldViewer THEN { <> workerViewer _ ViewerOps.CreateViewer[flavor: $Typescript, info: [iconic: NO, name: "Alpine Workers"]]; workerViewer.file _ FS.ExpandName[name: "WorkerList", wDir: MyWDir[] ].fullFName; aMenu _ workerViewer.menu; Menus.AppendMenuEntry[ menu: aMenu, entry: Menus.CreateEntry[ name: "Again", proc: ShowWorkersAgain ] ]; SkiPatrolViewers.AddSaveAndStore[aMenu]; ViewerOps.SetMenu[viewer: workerViewer, menu: aMenu]; SkiPatrolViewers.AddProps[viewer: workerViewer, baseTitle: workerViewer.name, WDir: MyWDir[]]; workerStream _ ViewerIO.CreateViewerStreams[name: "", viewer: workerViewer].out; }; ShowWorkersCore[]; }; ShowWorkersCore: PROC [] ~ { <> resultList: LIST OF ROPE _ NIL; -- one rope per worker; put in a list to be sorted ShowWorker: PROC [h:TransactionMap.Handle] RETURNS [stop: BOOLEAN] = { <> trueHandle: Worker.Handle; oneLine: ROPE; TRUSTED {trueHandle _ LOOPHOLE[h]}; oneLine _ SkiPatrolHooks.TransIDToRope[transID: trueHandle.transID, includeRName: YES]; oneLine _ oneLine.Cat["\t", workerStateToRope[trueHandle.state]]; oneLine _ oneLine.Cat["\t", outcomeToRope[trueHandle.outcome]]; oneLine _ oneLine.Cat["\t", Convert.RopeFromTime[from: trueHandle.timeOfLastStartWork, end: $seconds, useAMPM: NO, includeZone: NO]]; IF SkiPatrolHooks.InactiveWorker[trueHandle] THEN oneLine _ oneLine.Cat[" (Inactive)"]; IF SkiPatrolHooks.TestForAbort[trueHandle] = abort THEN oneLine _ oneLine.Cat[" (Abortable)"]; oneLine _ oneLine.Cat["\n"]; resultList _ CONS[oneLine, resultList]; RETURN [stop: NO] }; ViewerOps.SetNewVersion[workerViewer]; workerStream.Put[IO.rope["\n\n----- "], IO.time[], IO.rope[" ------\n"]]; workerStream.Put[IO.rope["TransID\t\t\t\t\t\tState\t\t\t\tOutcome\tLast Work\n"]]; TRUSTED {TransactionMap.LockedEnumerate[proc: ShowWorker]}; resultList _ RopeList.Sort[list: resultList, compareProc: RNameCompare]; FOR resultList _ resultList, resultList.rest WHILE resultList # NIL DO workerStream.Put[IO.rope[resultList.first]]; ENDLOOP; workerStream.Put[IO.rope["\n\n"]]; }; ShowWorkersAgain: Menus.MenuProc ~ { <> ShowWorkersCore[]; }; <> MyWDir: PROC [] RETURNS [Rope.ROPE] ~ { <> RETURN [NARROW [ List.Assoc[key: $WorkingDirectory, aList: ProcessProps.GetPropList[]]]] }; RNameCompare: RopeList.CompareProc ~ { <> r1Start: INT _ r1.Index[s2: "("] + 1; r1End: INT _ r1.Index[s2: ")"]; r2Start: INT _ r2.Index[s2: "("] + 1; r2End: INT _ r2.Index[s2: ")"]; RETURN [RopeList.IgnoreCase[ r1.Substr[start: r1Start, len: r1End-r1Start], r2.Substr[start: r2Start, len: r2End-r2Start] ]] }; <> <> Commander.Register[key: "ShowCoordinators", proc: ShowCoordinators, doc: "Display the current Alpine transaction coordinators"]; Commander.Register[key: "ShowWorkers", proc: ShowWorkers, doc: "Display the current local Alpine transaction workers"]; END. CHANGE LOG. <> <> <> <> <> <> <> <> <> <> <> <> <> <>