don't use one libmc client in two threads

This commit is contained in:
Laura Klünder 2017-12-23 20:42:36 +01:00
parent 90807f6f27
commit e447250247

View file

@ -1,5 +1,6 @@
import base64 import base64
import logging import logging
import multiprocessing
import os import os
import pickle import pickle
import re import re
@ -60,11 +61,11 @@ class TileServer:
self.cache_package_etag = None self.cache_package_etag = None
self.cache_package_filename = None self.cache_package_filename = None
self.cache = pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"tcp_nodelay": True, "ketama": True}) self.cache = self.get_cache_client()
wait = 1 wait = 1
while True: while True:
success = self.load_cache_package() success = self.load_cache_package(cache=self.cache)
if success: if success:
logger.info('Cache package successfully loaded.') logger.info('Cache package successfully loaded.')
break break
@ -74,15 +75,20 @@ class TileServer:
threading.Thread(target=self.update_cache_package_thread, daemon=True).start() threading.Thread(target=self.update_cache_package_thread, daemon=True).start()
@staticmethod
def get_cache_client():
return pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"tcp_nodelay": True, "ketama": True})
def update_cache_package_thread(self): def update_cache_package_thread(self):
cache = self.get_cache_client() # different thread → different client!
while True: while True:
time.sleep(self.reload_interval) time.sleep(self.reload_interval)
self.load_cache_package() self.load_cache_package(cache=cache)
def get_date_header(self): def get_date_header(self):
return 'Date', formatdate(timeval=time.time(), localtime=False, usegmt=True) return 'Date', formatdate(timeval=time.time(), localtime=False, usegmt=True)
def load_cache_package(self): def load_cache_package(self, cache):
logger.debug('Downloading cache package from upstream...') logger.debug('Downloading cache package from upstream...')
try: try:
headers = self.auth_headers.copy() headers = self.auth_headers.copy()
@ -97,7 +103,7 @@ class TileServer:
if r.status_code == 304: if r.status_code == 304:
if self.cache_package is not None: if self.cache_package is not None:
logger.debug('Not modified.') logger.debug('Not modified.')
self.cache['cache_package_filename'] = self.cache_package_filename cache['cache_package_filename'] = self.cache_package_filename
return True return True
logger.error('Unexpected not modified.') logger.error('Unexpected not modified.')
return False return False
@ -121,7 +127,7 @@ class TileServer:
) )
with open(self.cache_package_filename, 'wb') as f: with open(self.cache_package_filename, 'wb') as f:
pickle.dump(self.cache_package, f) pickle.dump(self.cache_package, f)
self.cache.set('cache_package_filename', self.cache_package_filename) cache.set('cache_package_filename', self.cache_package_filename)
except Exception as e: except Exception as e:
self.cache_package_etag = None self.cache_package_etag = None
logger.error('Saving pickled package failed: %s' % e) logger.error('Saving pickled package failed: %s' % e)
@ -154,6 +160,8 @@ class TileServer:
self.cache_package = pickle.load(f) self.cache_package = pickle.load(f)
return self.cache_package return self.cache_package
cache_lock = multiprocessing.Lock()
def __call__(self, env, start_response): def __call__(self, env, start_response):
path_info = env['PATH_INFO'] path_info = env['PATH_INFO']
match = self.path_regex.match(path_info) match = self.path_regex.match(path_info)
@ -217,7 +225,7 @@ class TileServer:
headers=self.auth_headers) headers=self.auth_headers)
if r.status_code == 200 and r.headers['Content-Type'] == 'image/png': if r.status_code == 200 and r.headers['Content-Type'] == 'image/png':
self.cache[cache_key] = r.content self.cache.set(cache_key, r.content)
return self.deliver_tile(start_response, tile_etag, r.content) return self.deliver_tile(start_response, tile_etag, r.content)
start_response('%d %s' % (r.status_code, r.reason), [ start_response('%d %s' % (r.status_code, r.reason), [