X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/b4e6d72fde248153207b0b311af4f46ee30e5e52..aa5f27fb91a567b489032a2788debfee38380461:/nominatim/nominatim.py?ds=inline diff --git a/nominatim/nominatim.py b/nominatim/nominatim.py index bbda4d7e..0db0777d 100755 --- a/nominatim/nominatim.py +++ b/nominatim/nominatim.py @@ -35,9 +35,14 @@ import select log = logging.getLogger() def make_connection(options, asynchronous=False): - return psycopg2.connect(dbname=options.dbname, user=options.user, - password=options.password, host=options.host, - port=options.port, async_=asynchronous) + params = {'dbname' : options.dbname, + 'user' : options.user, + 'password' : options.password, + 'host' : options.host, + 'port' : options.port, + 'async' : asynchronous} + + return psycopg2.connect(**params) class RankRunner(object): @@ -100,23 +105,43 @@ class InterpolationRunner(object): class DBConnection(object): - """ A signle non-blocking database connection. + """ A single non-blocking database connection. """ def __init__(self, options): + self.current_query = None + self.current_params = None + + self.conn = None + self.connect() + + def connect(self): + if self.conn is not None: + self.cursor.close() + self.conn.close() + self.conn = make_connection(options, asynchronous=True) self.wait() self.cursor = self.conn.cursor() - self.current_query = None - self.current_params = None - def wait(self): """ Block until any pending operation is done. """ - wait_select(self.conn) - self.current_query = None + while True: + try: + wait_select(self.conn) + self.current_query = None + return + except psycopg2.extensions.TransactionRollbackError as e: + if e.pgcode == '40P01': + log.info("Deadlock detected (params = {}), retry." + .format(self.current_params)) + self.cursor.execute(self.current_query, self.current_params) + else: + raise + except psycopg2.errors.DeadlockDetected: + self.cursor.execute(self.current_query, self.current_params) def perform(self, sql, args=None): """ Send SQL query to the server. Returns immediately without @@ -146,10 +171,12 @@ class DBConnection(object): return True except psycopg2.extensions.TransactionRollbackError as e: if e.pgcode == '40P01': - log.debug("Deadlock detected, retry.") + log.info("Deadlock detected (params = {}), retry.".format(self.current_params)) self.cursor.execute(self.current_query, self.current_params) else: raise + except psycopg2.errors.DeadlockDetected: + self.cursor.execute(self.current_query, self.current_params) return False @@ -175,7 +202,8 @@ class Indexer(object): if self.maxrank == 30: self.index(InterpolationRunner()) - self.index(RankRunner(30)) + + self.index(RankRunner(self.maxrank)) def index(self, obj): """ Index a single rank or table. `obj` describes the SQL to use @@ -256,15 +284,27 @@ class Indexer(object): sending a query. """ ready = self.threads + command_stat = 0 while True: for thread in ready: if thread.is_done(): + command_stat += 1 yield thread - ready, _, _ = select.select(self.threads, [], []) + # refresh the connections occasionaly to avoid potential + # memory leaks in Postgresql. + if command_stat > 100000: + for t in self.threads: + while not t.is_done(): + wait_select(t.conn) + t.connect() + command_stat = 0 + ready = self.threads + else: + ready, _, _ = select.select(self.threads, [], []) - assert(False, "Unreachable code") + assert False, "Unreachable code" def nominatim_arg_parser():