From bc4783efacb6806c26c1513a97590effbbbd2bd7 Mon Sep 17 00:00:00 2001 From: lagos Date: Thu, 27 Sep 2012 01:26:04 -0700 Subject: [PATCH 1/3] Make procpool compatible with windows and OS X. --- contrib/procpools/ampoule/main.py | 3 ++- contrib/procpools/python_procpool_plugin.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/procpools/ampoule/main.py b/contrib/procpools/ampoule/main.py index 9aec2817a4..993264ca3d 100644 --- a/contrib/procpools/ampoule/main.py +++ b/contrib/procpools/ampoule/main.py @@ -278,7 +278,8 @@ def spawnProcess(processProtocol, bootstrap, args=(), env={}, pythonpath = [] for pkg in packages: - p = os.path.split(imp.find_module(pkg)[1])[0] + path, name = os.path.split(pkg) + p = os.path.split(imp.find_module(name, [path] if path else None)[1])[0] if p.startswith(os.path.join(sys.prefix, 'lib')): continue pythonpath.append(p) diff --git a/contrib/procpools/python_procpool_plugin.py b/contrib/procpools/python_procpool_plugin.py index 337b47b5f0..d13447e661 100644 --- a/contrib/procpools/python_procpool_plugin.py +++ b/contrib/procpools/python_procpool_plugin.py @@ -24,6 +24,7 @@ file locking clashes. Test what works with your mileage. """ import os +import sys from django.conf import settings @@ -85,21 +86,20 @@ def start_plugin_services(server): apackages = ("twisted", os.path.join(os.pardir, "contrib", "procpools", "ampoule"), os.path.join(os.pardir, "ev"), - os.path.join(os.pardir)) + "settings") aenv = {"DJANGO_SETTINGS_MODULE":"settings", "DATABASE_NAME":settings.DATABASES.get("default", {}).get("NAME") or settings.DATABASE_NAME} if PROCPOOL_DEBUG: _BOOTSTRAP = _BOOTSTRAP % "log.startLogging(sys.stderr)" else: _BOOTSTRAP = _BOOTSTRAP % "" - procpool_starter = ampoule_main.ProcessStarter(packages=apackages, env=aenv, path=PROCPOOL_DIRECTORY, uid=PROCPOOL_UID, gid=PROCPOOL_GID, bootstrap=_BOOTSTRAP, - childReactor=os.name == 'nt' and "select" or "epoll") + childReactor=sys.platform == 'linux2' and "epoll" or "default") procpool = ampoule_pool.ProcessPool(name=SERVICE_NAME, min=PROCPOOL_MIN_NPROC, max=PROCPOOL_MAX_NPROC, From 5e8f077eb57902f78038ebae0f7a4c7d11e0971e Mon Sep 17 00:00:00 2001 From: lagos Date: Thu, 27 Sep 2012 16:50:11 -0700 Subject: [PATCH 2/3] Fixes clobbering of 'path' argument. --- contrib/procpools/ampoule/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/procpools/ampoule/main.py b/contrib/procpools/ampoule/main.py index 993264ca3d..1f46deb3f1 100644 --- a/contrib/procpools/ampoule/main.py +++ b/contrib/procpools/ampoule/main.py @@ -278,8 +278,8 @@ def spawnProcess(processProtocol, bootstrap, args=(), env={}, pythonpath = [] for pkg in packages: - path, name = os.path.split(pkg) - p = os.path.split(imp.find_module(name, [path] if path else None)[1])[0] + pkg_path, name = os.path.split(pkg) + p = os.path.split(imp.find_module(name, [pkg_path] if pkg_path else None)[1])[0] if p.startswith(os.path.join(sys.prefix, 'lib')): continue pythonpath.append(p) From 965be0a84fe77a8c5d971ff6b3299ceeb3de8f29 Mon Sep 17 00:00:00 2001 From: lagos Date: Thu, 27 Sep 2012 23:16:09 -0700 Subject: [PATCH 3/3] Fixes for Chrome clients of webclient. webclient.py now maintains a mapping of suid->single request as opposed to a mapp of suid->list of requests. Since the evennia_webclient.js client only has one valid request outstanding at all times, this should be safe. --- src/server/webclient.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/server/webclient.py b/src/server/webclient.py index 015492aef7..00ed4c63f5 100644 --- a/src/server/webclient.py +++ b/src/server/webclient.py @@ -72,8 +72,8 @@ class WebClient(resource.Resource): def _responseFailed(self, failure, suid, request): "callback if a request is lost/timed out" try: - self.requests.get(suid, []).remove(request) - except ValueError: + del self.requests[suid] + except KeyError: pass def lineSend(self, suid, string, data=None): @@ -81,13 +81,12 @@ class WebClient(resource.Resource): This adds the data to the buffer and/or sends it to the client as soon as possible. """ - requests = self.requests.get(suid, None) - if requests: - request = requests.pop(0) + request = self.requests.get(suid) + if request: # we have a request waiting. Return immediately. request.write(jsonify({'msg':string, 'data':data})) request.finish() - self.requests[suid] = requests + del self.requests[suid] else: # no waiting request. Store data in buffer dataentries = self.databuffer.get(suid, []) @@ -99,9 +98,8 @@ class WebClient(resource.Resource): Disconnect session with given suid. """ if self.requests.has_key(suid): - for request in self.requests.get(suid, []): - request.finish() - del self.requests[suid] + self.requests[suid].finish() + del self.requests[suid] if self.databuffer.has_key(suid): del self.databuffer[suid] @@ -119,7 +117,6 @@ class WebClient(resource.Resource): if suid == '0': # creating a unique id hash string suid = md5(str(time.time())).hexdigest() - self.requests[suid] = [] self.databuffer[suid] = [] sess = WebClientSession() @@ -160,10 +157,10 @@ class WebClient(resource.Resource): dataentries = self.databuffer.get(suid, []) if dataentries: return dataentries.pop(0) - reqlist = self.requests.get(suid, []) request.notifyFinish().addErrback(self._responseFailed, suid, request) - reqlist.append(request) - self.requests[suid] = reqlist + if self.requests.has_key(suid): + self.requests[suid].finish() # Clear any stale request. + self.requests[suid] = request return server.NOT_DONE_YET def mode_close(self, request):