Skip to content
This repository
  • 2 commits
  • 1 file changed
  • 0 comments
  • 1 contributor
Jul 23, 2012
Oliver Tonnhofer olt fixed reloading of multiapps in threaded servers
make sure MultiMapProxy.proj_app returns an app when the app was stale
and another thread reloaded it first
c904ebe
Oliver Tonnhofer olt Merge branch '1.4.x' 34b61ca

Showing 1 changed file with 31 additions and 30 deletions. Show diff stats Hide diff stats

  1. +31 30 mapproxy/multiapp.py
61 mapproxy/multiapp.py
... ... @@ -1,13 +1,13 @@
1 1 # -:- encoding: utf-8 -:-
2 2 # This file is part of the MapProxy project.
3 3 # Copyright (C) 2010 Omniscale <http://omniscale.de>
4   -#
  4 +#
5 5 # Licensed under the Apache License, Version 2.0 (the "License");
6 6 # you may not use this file except in compliance with the License.
7 7 # You may obtain a copy of the License at
8   -#
  8 +#
9 9 # http://www.apache.org/licenses/LICENSE-2.0
10   -#
  10 +#
11 11 # Unless required by applicable law or agreed to in writing, software
12 12 # distributed under the License is distributed on an "AS IS" BASIS,
13 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -39,7 +39,7 @@ def asbool(value):
39 39 def app_factory(global_options, config_dir, allow_listing=False, **local_options):
40 40 """
41 41 Create a new MultiMapProxy app.
42   -
  42 +
43 43 :param config_dir: directory with all mapproxy configurations
44 44 :param allow_listing: allow to list all available apps
45 45 """
@@ -48,7 +48,7 @@ def app_factory(global_options, config_dir, allow_listing=False, **local_options
48 48 def make_wsgi_app(config_dir, allow_listing=True):
49 49 """
50 50 Create a MultiMapProxy with the given config directory.
51   -
  51 +
52 52 :param config_dir: the directory with all project configurations.
53 53 :param allow_listing: True if MapProxy should list all instances
54 54 at the root URL
@@ -59,38 +59,38 @@ def make_wsgi_app(config_dir, allow_listing=True):
59 59
60 60
61 61 class MultiMapProxy(object):
62   -
  62 +
63 63 def __init__(self, loader, list_apps=False, app_cache_size=100):
64 64 self.loader = loader
65 65 self.list_apps = list_apps
66 66 self._app_init_lock = Lock()
67 67 self.apps = LRU(app_cache_size)
68   -
  68 +
69 69 def __call__(self, environ, start_response):
70 70 req = Request(environ)
71 71 return self.handle(req)(environ, start_response)
72   -
  72 +
73 73 def handle(self, req):
74 74 app_name = req.pop_path()
75 75 if not app_name:
76 76 return self.index_list()
77   -
  77 +
78 78 if not app_name or (
79 79 app_name not in self.apps and not self.loader.app_available(app_name)
80 80 ):
81 81 return Response('not found', status=404)
82   -
  82 +
83 83 # safe instance/app name for authorization
84 84 req.environ['mapproxy.instance_name'] = app_name
85 85 return self.proj_app(app_name)
86   -
  86 +
87 87 def index_list(self):
88 88 """
89 89 Return greeting response with a list of available apps (if enabled with list_apps).
90 90 """
91 91 import mapproxy.version
92 92 html = "<html><body><h1>Welcome to MapProxy %s</h1>" % mapproxy.version.version
93   -
  93 +
94 94 if self.list_apps:
95 95 html += "<h2>available instances:</h2><ul>"
96 96 html += '\n'.join('<li><a href="%(name)s/">%(name)s</a></li>' % {'name': app}
@@ -104,21 +104,22 @@ def proj_app(self, proj_name):
104 104 Return the (cached) project app.
105 105 """
106 106 proj_app, timestamp = self.apps.get(proj_name, (None, None))
107   -
  107 +
108 108 if proj_app:
109 109 if self.loader.needs_reload(proj_name, timestamp):
110 110 # discard cached app
111 111 proj_app = None
112   - del self.apps[proj_name]
113   -
  112 +
114 113 if not proj_app:
115 114 with self._app_init_lock:
116   - if proj_name not in self.apps:
  115 + if self.loader.needs_reload(proj_name, timestamp):
117 116 proj_app, m_time = self.create_app(proj_name)
118 117 self.apps[proj_name] = proj_app, m_time
119   -
  118 + else:
  119 + proj_app = self.apps[proj_name]
  120 +
120 121 return proj_app
121   -
  122 +
122 123 def create_app(self, proj_name):
123 124 """
124 125 Returns a new configured MapProxy app and the timestamp of the configuration.
@@ -137,29 +138,29 @@ def needs_reload(self, app_name, timestamp):
137 138 since `timestamp`.
138 139 """
139 140 raise NotImplementedError()
140   -
  141 +
141 142 def app_available(self, app_name):
142 143 """
143 144 Returns ``True`` if `app_name` is available.
144 145 """
145 146 raise NotImplementedError()
146   -
  147 +
147 148 def available_apps(self):
148 149 """
149 150 Returns a list with all available lists.
150 151 """
151 152 raise NotImplementedError()
152   -
  153 +
153 154 def app_conf(self, app_name):
154 155 """
155 156 Returns a configuration dict for the given `app_name`,
156 157 None if the app is not found.
157   -
  158 +
158 159 The configuration dict contains at least 'mapproxy_conf'
159 160 with the filename of the configuration.
160 161 """
161 162 raise NotImplementedError()
162   -
  163 +
163 164
164 165 class DirectoryConfLoader(ConfLoader):
165 166 """
@@ -168,14 +169,14 @@ class DirectoryConfLoader(ConfLoader):
168 169 def __init__(self, base_dir, suffix='.yaml'):
169 170 self.base_dir = base_dir
170 171 self.suffix = suffix
171   -
  172 +
172 173 def needs_reload(self, app_name, timestamp):
173 174 conf_file = self.filename_from_app_name(app_name)
174 175 m_time = os.path.getmtime(conf_file)
175 176 if m_time > timestamp:
176 177 return True
177 178 return False
178   -
  179 +
179 180 def _is_conf_file(self, fname):
180 181 if not os.path.isfile(fname):
181 182 return False
@@ -183,7 +184,7 @@ def _is_conf_file(self, fname):
183 184 return fname.lower().endswith(self.suffix)
184 185 else:
185 186 return True
186   -
  187 +
187 188 def app_name_from_filename(self, fname):
188 189 """
189 190 >>> DirectoryConfLoader('/tmp/').app_name_from_filename('/tmp/foobar.yaml')
@@ -192,14 +193,14 @@ def app_name_from_filename(self, fname):
192 193 _path, fname = os.path.split(fname)
193 194 app_name, _ext = os.path.splitext(fname)
194 195 return app_name
195   -
  196 +
196 197 def filename_from_app_name(self, app_name):
197 198 """
198 199 >>> DirectoryConfLoader('/tmp/').filename_from_app_name('foobar')
199 200 '/tmp/foobar.yaml'
200 201 """
201 202 return os.path.join(self.base_dir, app_name + self.suffix or '')
202   -
  203 +
203 204 def available_apps(self):
204 205 apps = []
205 206 for f in os.listdir(self.base_dir):
@@ -207,11 +208,11 @@ def available_apps(self):
207 208 app_name = self.app_name_from_filename(f)
208 209 apps.append(app_name)
209 210 return apps
210   -
  211 +
211 212 def app_available(self, app_name):
212 213 conf_file = self.filename_from_app_name(app_name)
213 214 return self._is_conf_file(conf_file)
214   -
  215 +
215 216 def app_conf(self, app_name):
216 217 conf_file = self.filename_from_app_name(app_name)
217 218 if not self._is_conf_file(conf_file):

No commit comments for this range

Something went wrong with that request. Please try again.