From 3e11d7ede84e52974e41542ed60899ff340088d7 Mon Sep 17 00:00:00 2001
From: Fredrik Tolf <fredrik@dolda2000.com>
Date: Thu, 21 Apr 2011 04:46:21 +0200
Subject: [PATCH] python: Added a request limiter to ashd-wsgi.

---
 python/ashd-wsgi         | 34 ++++++++++++++++++++++++++++++----
 python/doc/ashd-wsgi.doc | 10 +++++++++-
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/python/ashd-wsgi b/python/ashd-wsgi
index 79aad4f..e43dbc0 100755
--- a/python/ashd-wsgi
+++ b/python/ashd-wsgi
@@ -1,13 +1,14 @@
 #!/usr/bin/python
 
-import sys, os, getopt, threading
+import sys, os, getopt, threading, time
 import ashd.proto, ashd.util
 
 def usage(out):
-    out.write("usage: ashd-wsgi [-hA] [-p MODPATH] HANDLER-MODULE [ARGS...]\n")
+    out.write("usage: ashd-wsgi [-hA] [-p MODPATH] [-l REQLIMIT] HANDLER-MODULE [ARGS...]\n")
 
+reqlimit = 0
 modwsgi_compat = False
-opts, args = getopt.getopt(sys.argv[1:], "+hAp:")
+opts, args = getopt.getopt(sys.argv[1:], "+hAp:l:")
 for o, a in opts:
     if o == "-h":
         usage(sys.stdout)
@@ -16,6 +17,8 @@ for o, a in opts:
         sys.path.insert(0, a)
     elif o == "-A":
         modwsgi_compat = True
+    elif o == "-l":
+        reqlimit = int(a)
 if len(args) < 1:
     usage(sys.stderr)
     sys.exit(1)
@@ -170,14 +173,37 @@ def dowsgi(req):
         if hasattr(respiter, "close"):
             respiter.close()
 
+flightlock = threading.Condition()
+inflight = 0
+
 class reqthread(threading.Thread):
     def __init__(self, req):
         super(reqthread, self).__init__(name = "Request handler")
         self.req = req.dup()
     
     def run(self):
+        global inflight
         try:
-            dowsgi(self.req)
+            flightlock.acquire()
+            try:
+                if reqlimit != 0:
+                    start = time.time()
+                    while inflight >= reqlimit:
+                        flightlock.wait(10)
+                        if time.time() - start > 10:
+                            os.abort()
+                inflight += 1
+            finally:
+                flightlock.release()
+            try:
+                dowsgi(self.req)
+            finally:
+                flightlock.acquire()
+                try:
+                    inflight -= 1
+                    flightlock.notify()
+                finally:
+                    flightlock.release()
         finally:
             self.req.close()
     
diff --git a/python/doc/ashd-wsgi.doc b/python/doc/ashd-wsgi.doc
index 25531ff..b73f90d 100644
--- a/python/doc/ashd-wsgi.doc
+++ b/python/doc/ashd-wsgi.doc
@@ -7,7 +7,7 @@ ashd-wsgi - WSGI adapter for ashd(7)
 
 SYNOPSIS
 --------
-*ashd-wsgi* [*-hA*] [*-p* 'MODPATH'] 'HANDLER-MODULE' ['ARGS'...]
+*ashd-wsgi* [*-hA*] [*-p* 'MODPATH'] [*-l* 'LIMIT'] 'HANDLER-MODULE' ['ARGS'...]
 
 DESCRIPTION
 -----------
@@ -54,6 +54,14 @@ OPTIONS
 	on Python's module path by default, so if you want to use a
 	module in that directory, you will need to specify "`-p .`".
 
+*-l* 'LIMIT'::
+
+	Allow at most 'LIMIT' requests to run concurrently. If a new
+	request is made when 'LIMIT' requests are executing, the new
+	request will wait up to ten seconds for one of them to
+	complete; if none does, the *ashd-wsgi* will assume that the
+	process is foobar and *abort*(3).
+
 PROTOCOL
 --------
 
-- 
2.11.0