##// END OF EJS Templates
hgweb: use separate repo instances per thread...
Gregory Szorc -
r26220:a43328ba default
parent child Browse files
Show More
@@ -6,6 +6,7
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 import contextlib
9 10 import os
10 11 from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
11 12 from mercurial.templatefilters import websub
@@ -208,7 +209,8 class hgweb(object):
208 209 # break some wsgi implementation.
209 210 r.ui.setconfig('progress', 'disable', 'true', 'hgweb')
210 211 r.baseui.setconfig('progress', 'disable', 'true', 'hgweb')
211 self._repo = hg.cachedlocalrepo(self._webifyrepo(r))
212 self._repos = [hg.cachedlocalrepo(self._webifyrepo(r))]
213 self._lastrepo = self._repos[0]
212 214 hook.redirect(True)
213 215 self.reponame = name
214 216
@@ -217,13 +219,34 class hgweb(object):
217 219 self.websubtable = webutil.getwebsubs(repo)
218 220 return repo
219 221
220 def _getrepo(self):
221 r, created = self._repo.fetch()
222 @contextlib.contextmanager
223 def _obtainrepo(self):
224 """Obtain a repo unique to the caller.
225
226 Internally we maintain a stack of cachedlocalrepo instances
227 to be handed out. If one is available, we pop it and return it,
228 ensuring it is up to date in the process. If one is not available,
229 we clone the most recently used repo instance and return it.
230
231 It is currently possible for the stack to grow without bounds
232 if the server allows infinite threads. However, servers should
233 have a thread limit, thus establishing our limit.
234 """
235 if self._repos:
236 cached = self._repos.pop()
237 r, created = cached.fetch()
222 238 if created:
223 239 r = self._webifyrepo(r)
240 else:
241 cached = self._lastrepo.copy()
242 r, created = cached.fetch()
224 243
225 self.mtime = self._repo.mtime
226 return r
244 self._lastrepo = cached
245 self.mtime = cached.mtime
246 try:
247 yield r
248 finally:
249 self._repos.append(cached)
227 250
228 251 def run(self):
229 252 """Start a server from CGI environment.
@@ -251,7 +274,10 class hgweb(object):
251 274 This is typically only called by Mercurial. External consumers
252 275 should be using instances of this class as the WSGI application.
253 276 """
254 repo = self._getrepo()
277 with self._obtainrepo() as repo:
278 return self._runwsgi(req, repo)
279
280 def _runwsgi(self, req, repo):
255 281 rctx = requestcontext(self, repo)
256 282
257 283 # This state is global across all threads.
@@ -64,7 +64,8 by the WSGI standard and strictly implem
64 64 > print '---- OS.ENVIRON wsgi variables'
65 65 > print sorted([x for x in os.environ if x.startswith('wsgi')])
66 66 > print '---- request.ENVIRON wsgi variables'
67 > print sorted([x for x in i._getrepo().ui.environ if x.startswith('wsgi')])
67 > with i._obtainrepo() as repo:
68 > print sorted([x for x in repo.ui.environ if x.startswith('wsgi')])
68 69 > EOF
69 70 $ python request.py
70 71 ---- STATUS
General Comments 0
You need to be logged in to leave comments. Login now