python: Support PDM in ashd-wsgi.
authorFredrik Tolf <fredrik@dolda2000.com>
Fri, 16 Dec 2011 05:47:03 +0000 (06:47 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Fri, 16 Dec 2011 05:47:03 +0000 (06:47 +0100)
python/ashd-wsgi
python/ashd/perf.py [new file with mode: 0644]
python/doc/ashd-wsgi.doc
python3/ashd-wsgi3
python3/ashd/perf.py [new file with mode: 0644]
python3/doc/ashd-wsgi3.doc

index 894211d..af2c332 100755 (executable)
@@ -1,14 +1,18 @@
 #!/usr/bin/python
 
 import sys, os, getopt, threading, time
-import ashd.proto, ashd.util
+import ashd.proto, ashd.util, ashd.perf
+try:
+    import pdm.srv
+except:
+    pdm = None
 
 def usage(out):
-    out.write("usage: ashd-wsgi [-hA] [-p MODPATH] [-l REQLIMIT] HANDLER-MODULE [ARGS...]\n")
+    out.write("usage: ashd-wsgi [-hA] [-m PDM-SPEC] [-p MODPATH] [-l REQLIMIT] HANDLER-MODULE [ARGS...]\n")
 
 reqlimit = 0
 modwsgi_compat = False
-opts, args = getopt.getopt(sys.argv[1:], "+hAp:l:")
+opts, args = getopt.getopt(sys.argv[1:], "+hAp:l:m:")
 for o, a in opts:
     if o == "-h":
         usage(sys.stdout)
@@ -19,6 +23,9 @@ for o, a in opts:
         modwsgi_compat = True
     elif o == "-l":
         reqlimit = int(a)
+    elif o == "-m":
+        if pdm is not None:
+            pdm.srv.listen(a)
 if len(args) < 1:
     usage(sys.stderr)
     sys.exit(1)
@@ -167,18 +174,27 @@ def dowsgi(req):
         resp[:] = status, headers
         return write
 
-    respiter = handler(env, startreq)
+    reqevent = ashd.perf.request(env)
+    exc = (None, None, None)
     try:
+        respiter = handler(env, startreq)
         try:
-            for data in respiter:
-                write(data)
-            if resp:
-                flushreq()
-        except closed:
-            pass
+            try:
+                for data in respiter:
+                    write(data)
+                if resp:
+                    flushreq()
+            except closed:
+                pass
+        finally:
+            if hasattr(respiter, "close"):
+                respiter.close()
+        if resp:
+            reqevent.response(resp)
+    except:
+        exc = sys.exc_info()
     finally:
-        if hasattr(respiter, "close"):
-            respiter.close()
+        reqevent.__exit__(*exc)
 
 flightlock = threading.Condition()
 inflight = 0
diff --git a/python/ashd/perf.py b/python/ashd/perf.py
new file mode 100644 (file)
index 0000000..d3d3cb7
--- /dev/null
@@ -0,0 +1,57 @@
+try:
+    import pdm.perf
+except:
+    pdm = None
+
+reqstat = {}
+
+if pdm:
+    statistics = pdm.perf.staticdir()
+    statistics["req"] = pdm.perf.valueattr(reqstat)
+    requests = pdm.perf.eventobj()
+
+    class reqstart(pdm.perf.startevent):
+        def __init__(self, env):
+            super(reqstart, self).__init__()
+            self.method = env.get("REQUEST_METHOD")
+            self.uri = env.get("REQUEST_URI")
+            self.host = env.get("HTTP_HOST")
+
+    class reqfinish(pdm.perf.finishevent):
+        def __init__(self, start, aborted, status):
+            super(reqfinish, self).__init__(start, aborted)
+            self.status = status
+
+class request(object):
+    def __init__(self, env):
+        self.resp = None
+        if pdm:
+            self.startev = reqstart(env)
+            requests.notify(self.startev)
+
+    def response(self, resp):
+        self.resp = resp
+
+    def finish(self, aborted):
+        key = None
+        status = None
+        try:
+            if len(self.resp) > 0:
+                status = self.resp[0]
+                p = status.find(" ")
+                if p < 0:
+                    key = status
+                else:
+                    key = status[:p]
+        except:
+            pass
+        reqstat[key] = reqstat.setdefault(key, 0) + 1
+        if pdm:
+            requests.notify(reqfinish(self.startev, aborted, status))
+
+    def __enter__(self):
+        return self
+    
+    def __exit__(self, *excinfo):
+        self.finish(bool(excinfo[0]))
+        return False
index 9b950b8..2102557 100644 (file)
@@ -7,7 +7,7 @@ ashd-wsgi - WSGI adapter for ashd(7)
 
 SYNOPSIS
 --------
-*ashd-wsgi* [*-hA*] [*-p* 'MODPATH'] [*-l* 'LIMIT'] 'HANDLER-MODULE' ['ARGS'...]
+*ashd-wsgi* [*-hA*] [*-m* 'PDM-SPEC'] [*-p* 'MODPATH'] [*-l* 'LIMIT'] 'HANDLER-MODULE' ['ARGS'...]
 
 DESCRIPTION
 -----------
@@ -62,6 +62,12 @@ OPTIONS
        complete; if none does, *ashd-wsgi* will assume that the
        process is foobar and *abort*(3).
 
+*-m* 'PDM-SPEC'::
+
+       If the PDM library is installed on the system, create a
+       listening socket for connection PDM clients according to
+       'PDM-SPEC'.
+
 PROTOCOL
 --------
 
index da60cfa..0e562ec 100755 (executable)
@@ -1,14 +1,18 @@
 #!/usr/bin/python3
 
 import sys, os, getopt, threading, time, locale, collections
-import ashd.proto, ashd.util
+import ashd.proto, ashd.util, ashd.perf
+try:
+    import pdm.srv
+except:
+    pdm = None
 
 def usage(out):
-    out.write("usage: ashd-wsgi3 [-hA] [-p MODPATH] [-l REQLIMIT] HANDLER-MODULE [ARGS...]\n")
+    out.write("usage: ashd-wsgi3 [-hA] [-m PDM-SPEC] [-p MODPATH] [-l REQLIMIT] HANDLER-MODULE [ARGS...]\n")
 
 reqlimit = 0
 modwsgi_compat = False
-opts, args = getopt.getopt(sys.argv[1:], "+hAp:l:")
+opts, args = getopt.getopt(sys.argv[1:], "+hAp:l:m:")
 for o, a in opts:
     if o == "-h":
         usage(sys.stdout)
@@ -19,6 +23,9 @@ for o, a in opts:
         modwsgi_compat = True
     elif o == "-l":
         reqlimit = int(a)
+    elif o == "-m":
+        if pdm is not None:
+            pdm.srv.listen(a)
 if len(args) < 1:
     usage(sys.stderr)
     sys.exit(1)
@@ -178,18 +185,21 @@ def dowsgi(req):
         resp[:] = status, headers
         return write
 
-    respiter = handler(env, startreq)
-    try:
+    with ashd.perf.request(env) as reqevent:
+        respiter = handler(env, startreq)
         try:
-            for data in respiter:
-                write(data)
-            if resp:
-                flushreq()
-        except closed:
-            pass
-    finally:
-        if hasattr(respiter, "close"):
-            respiter.close()
+            try:
+                for data in respiter:
+                    write(data)
+                if resp:
+                    flushreq()
+            except closed:
+                pass
+        finally:
+            if hasattr(respiter, "close"):
+                respiter.close()
+        if resp:
+            reqevent.response(resp)
 
 flightlock = threading.Condition()
 inflight = 0
diff --git a/python3/ashd/perf.py b/python3/ashd/perf.py
new file mode 100644 (file)
index 0000000..0d1e7aa
--- /dev/null
@@ -0,0 +1,62 @@
+import collections
+try:
+    import pdm.perf
+except:
+    pdm = None
+
+reqstat = {}
+
+if pdm:
+    statistics = pdm.perf.staticdir()
+    statistics["req"] = pdm.perf.valueattr(reqstat)
+    requests = pdm.perf.eventobj()
+
+    class reqstart(pdm.perf.startevent):
+        def __init__(self, env):
+            super(reqstart, self).__init__()
+            self.method = env.get("REQUEST_METHOD")
+            self.uri = env.get("REQUEST_URI")
+            self.host = env.get("HTTP_HOST")
+
+    class reqfinish(pdm.perf.finishevent):
+        def __init__(self, start, aborted, status):
+            super(reqfinish, self).__init__(start, aborted)
+            self.status = status
+
+class request(object):
+    def __init__(self, env):
+        self.resp = None
+        if pdm:
+            self.startev = reqstart(env)
+            requests.notify(self.startev)
+
+    def response(self, resp):
+        self.resp = resp
+
+    def finish(self, aborted):
+        key = None
+        status = None
+        try:
+            if len(self.resp) > 0:
+                status = self.resp[0]
+                if isinstance(status, collections.ByteString):
+                    status = status.decode("latin-1")
+                else:
+                    status = str(status)
+                p = status.find(" ")
+                if p < 0:
+                    key = status
+                else:
+                    key = status[:p]
+        except:
+            pass
+        reqstat[key] = reqstat.setdefault(key, 0) + 1
+        if pdm:
+            requests.notify(reqfinish(self.startev, aborted, status))
+
+    def __enter__(self):
+        return self
+    
+    def __exit__(self, *excinfo):
+        self.finish(bool(excinfo[0]))
+        return False
index 0af0882..0be02b1 100644 (file)
@@ -7,7 +7,7 @@ ashd-wsgi3 - WSGI adapter for ashd(7)
 
 SYNOPSIS
 --------
-*ashd-wsgi3* [*-hA*] [*-p* 'MODPATH'] [*-l* 'LIMIT'] 'HANDLER-MODULE' ['ARGS'...]
+*ashd-wsgi3* [*-hA*] [*-m* 'PDM-SPEC'] [*-p* 'MODPATH'] [*-l* 'LIMIT'] 'HANDLER-MODULE' ['ARGS'...]
 
 DESCRIPTION
 -----------
@@ -62,6 +62,12 @@ OPTIONS
        complete; if none does, *ashd-wsgi3* will assume that the
        process is foobar and *abort*(3).
 
+*-m* 'PDM-SPEC'::
+
+       If the PDM library is installed on the system, create a
+       listening socket for connection PDM clients according to
+       'PDM-SPEC'.
+
 PROTOCOL
 --------