[CalendarServer-changes] [12816] CalendarServer/trunk/calendarserver/tools/jobitems.py

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 5 08:40:56 PST 2014


Revision: 12816
          http://trac.calendarserver.org//changeset/12816
Author:   cdaboo at apple.com
Date:     2014-03-05 08:40:56 -0800 (Wed, 05 Mar 2014)
Log Message:
-----------
Allow keyboard to control dashboard (e.g. q to quit). Add a help panel to show available keyboard options.

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tools/jobitems.py

Modified: CalendarServer/trunk/calendarserver/tools/jobitems.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/jobitems.py	2014-03-05 15:45:13 UTC (rev 12815)
+++ CalendarServer/trunk/calendarserver/tools/jobitems.py	2014-03-05 16:40:56 UTC (rev 12816)
@@ -17,15 +17,18 @@
 ##
 from __future__ import print_function
 
+from calendarserver.tools.cmdline import utilityMain, WorkerService
+
 from getopt import getopt, GetoptError
+
+from twext.enterprise.jobqueue import JobItem
+
+from twisted.internet.defer import inlineCallbacks, succeed
+
+import curses
 import os
 import sys
-import curses
 
-from twisted.internet.defer import inlineCallbacks, succeed
-from calendarserver.tools.cmdline import utilityMain, WorkerService
-from twext.enterprise.jobqueue import JobItem
-
 useCurses = True
 
 def usage(e=None):
@@ -86,28 +89,35 @@
         else:
             raise NotImplementedError(opt)
 
-    utilityMain(configFileName, JobItemMonitorService, verbose=debug)
+    if useCurses:
+        def _wrapped(stdscrn):
+            JobItemMonitorService.screen = stdscrn
+            curses.curs_set(0)
+            curses.use_default_colors()
+            utilityMain(configFileName, JobItemMonitorService, verbose=debug)
+        curses.wrapper(_wrapped)
+    else:
+        utilityMain(configFileName, JobItemMonitorService, verbose=debug)
 
 
 
 class JobItemMonitorService(WorkerService, object):
 
+    screen = None
+
     def __init__(self, store):
         super(JobItemMonitorService, self).__init__(store)
         from twisted.internet import reactor
         self.reactor = reactor
+        self.paused = False
+        self.seconds = 0.1
 
 
+    @inlineCallbacks
     def doWork(self):
-        if useCurses:
-            self.screen = curses.initscr()
-            curses.curs_set(0)
-        else:
-            self.screen = None
-        self.windows = []
-        self.updateScreenGeometry()
+        self.window = None
+        yield self.displayJobs()
         self.reactor.callLater(0, self.updateDisplay)
-        return succeed(None)
 
 
     def postStartService(self):
@@ -117,30 +127,56 @@
         pass
 
 
-    def updateScreenGeometry(self):
-        for win in self.windows:
-            del win
-        window = WorkWindow(JobItem.numberOfWorkTypes() + 5, BOX_WIDTH, 0, 0, self.store, "Jobs")
-        self.windows.append(window)
+    @inlineCallbacks
+    def displayHelp(self):
+        if self.window is not None:
+            self.window.clear()
+        self.window = HelpWindow(10, BOX_WIDTH, 0, 0, self.store, "Help")
+        yield self.window.update()
 
 
     @inlineCallbacks
+    def displayJobs(self):
+        if self.window is not None:
+            self.window.clear()
+        self.window = WorkWindow(JobItem.numberOfWorkTypes() + 5, BOX_WIDTH, 0, 0, self.store, "Jobs")
+        yield self.window.update()
+
+
+    @inlineCallbacks
     def updateDisplay(self):
-        for window in self.windows:
-            try:
-                yield window.update()
-            except Exception as e:
-                print(str(e))
+        try:
+            if not self.paused and self.window.requiresUpdate():
+                yield self.window.update()
+        except Exception as e:
+            print(str(e))
         if not useCurses:
             print("-------------")
 
-        self.reactor.callLater(0.1, self.updateDisplay)
+        # Check keystrokes
+        try:
+            c = self.window.window.getkey()
+        except:
+            c = -1
+        if c == "q":
+            self.reactor.stop()
+        elif c == " ":
+            self.paused = not self.paused
+        elif c == "t":
+            self.seconds = 1.0 if self.seconds == 0.1 else 1.0
+        elif c == "h":
+            yield self.displayHelp()
+        elif c == "j":
+            yield self.displayJobs()
 
+        self.reactor.callLater(self.seconds, self.updateDisplay)
 
 
-class WorkWindow(object):
+
+class BaseWindow(object):
     def __init__(self, nlines, ncols, begin_y, begin_x, store, title):
         self.window = curses.newwin(nlines, ncols, begin_y, begin_x) if useCurses else None
+        self.window.nodelay(1)
         self.ncols = ncols
         self.store = store
         self.title = title
@@ -148,6 +184,62 @@
         self.lastResult = {}
 
 
+    def requiresUpdate(self):
+        return True
+
+
+    def clear(self):
+
+        if useCurses:
+            self.window.erase()
+            self.window.refresh()
+
+
+    def update(self):
+        return succeed(True)
+
+
+
+class HelpWindow(BaseWindow):
+
+    def requiresUpdate(self):
+        return False
+
+
+    def update(self):
+
+        if useCurses:
+            self.window.erase()
+            self.window.border()
+            self.window.addstr(0, 2, "Help for Dashboard")
+
+        x = 1
+        y = 1
+
+        for title in (
+            "j - display server jobs",
+            "h - display dashboard help",
+            "",
+            "  - (space) pause dashboard polling",
+            "t - toggle update between 0.1 and 1.0 seconds",
+            "",
+            "q - exit the dashboard",
+        ):
+            if useCurses:
+                self.window.addstr(y, x, title)
+            else:
+                print(title)
+            y += 1
+
+        if useCurses:
+            self.window.refresh()
+
+        return succeed(True)
+
+
+
+class WorkWindow(BaseWindow):
+
     @inlineCallbacks
     def update(self):
         txn = self.store.newTransaction()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140305/bb4927c0/attachment-0001.html>


More information about the calendarserver-changes mailing list