Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: third_party/buildbot_8_4p1/buildbot/db/pool.py

Issue 2103043002: Cherry-pick buildbot 7d31a0593e2e207289511c10f68a8bc4ba13b759: (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@buildbot-revert-hack
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This file is part of Buildbot. Buildbot is free software: you can 1 # This file is part of Buildbot. Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public 2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2. 3 # License as published by the Free Software Foundation, version 2.
4 # 4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT 5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
8 # details. 8 # details.
9 # 9 #
10 # You should have received a copy of the GNU General Public License along with 10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51 11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 # 13 #
14 # Copyright Buildbot Team Members 14 # Copyright Buildbot Team Members
15 15
16 import os 16 import os
17 import sqlalchemy as sa 17 import sqlalchemy as sa
18 import twisted 18 import twisted
19 from twisted.internet import reactor, threads, defer 19 from twisted.internet import reactor, threads, defer
20 from twisted.python import threadpool, failure, versions, log 20 from twisted.python import threadpool, failure, versions, log
21 21
22 22
23 class DBThreadPool(threadpool.ThreadPool): 23 class DBThreadPool(threadpool.ThreadPool):
24 """
25 A pool of threads ready and waiting to execute queries.
26
27 If the engine has an C{optimal_thread_pool_size} attribute, then the
28 maxthreads of the thread pool will be set to that value. This is most
29 useful for SQLite in-memory connections, where exactly one connection
30 (and thus thread) should be used.
31 """
32 24
33 running = False 25 running = False
34 26
35 # Some versions of SQLite incorrectly cache metadata about which tables are 27 # Some versions of SQLite incorrectly cache metadata about which tables are
36 # and are not present on a per-connection basis. This cache can be flushed 28 # and are not present on a per-connection basis. This cache can be flushed
37 # by querying the sqlite_master table. We currently assume all versions of 29 # by querying the sqlite_master table. We currently assume all versions of
38 # SQLite have this bug, although it has only been observed in 3.4.2. A 30 # SQLite have this bug, although it has only been observed in 3.4.2. A
39 # dynamic check for this bug would be more appropriate. This is documented 31 # dynamic check for this bug would be more appropriate. This is documented
40 # in bug #1810. 32 # in bug #1810.
41 __broken_sqlite = False 33 __broken_sqlite = False
42 34
43 def __init__(self, engine): 35 def __init__(self, engine):
44 pool_size = 5 36 pool_size = 5
37
38 # If the engine has an C{optimal_thread_pool_size} attribute, then the
39 # maxthreads of the thread pool will be set to that value. This is
40 # most useful for SQLite in-memory connections, where exactly one
41 # connection (and thus thread) should be used.
45 if hasattr(engine, 'optimal_thread_pool_size'): 42 if hasattr(engine, 'optimal_thread_pool_size'):
46 pool_size = engine.optimal_thread_pool_size 43 pool_size = engine.optimal_thread_pool_size
44
47 threadpool.ThreadPool.__init__(self, 45 threadpool.ThreadPool.__init__(self,
48 minthreads=1, 46 minthreads=1,
49 maxthreads=pool_size, 47 maxthreads=pool_size,
50 name='DBThreadPool') 48 name='DBThreadPool')
51 self.engine = engine 49 self.engine = engine
52 if engine.dialect.name == 'sqlite': 50 if engine.dialect.name == 'sqlite':
53 log.msg("applying SQLite workaround from Buildbot bug #1810") 51 log.msg("applying SQLite workaround from Buildbot bug #1810")
54 self.__broken_sqlite = self.detect_bug1810() 52 self.__broken_sqlite = self.detect_bug1810()
55 self._start_evt = reactor.callWhenRunning(self._start) 53 self._start_evt = reactor.callWhenRunning(self._start)
56 54
(...skipping 14 matching lines...) Expand all
71 def shutdown(self): 69 def shutdown(self):
72 """Manually stop the pool. This is only necessary from tests, as the 70 """Manually stop the pool. This is only necessary from tests, as the
73 pool will stop itself when the reactor stops under normal 71 pool will stop itself when the reactor stops under normal
74 circumstances.""" 72 circumstances."""
75 if not self._stop_evt: 73 if not self._stop_evt:
76 return # pool is already stopped 74 return # pool is already stopped
77 reactor.removeSystemEventTrigger(self._stop_evt) 75 reactor.removeSystemEventTrigger(self._stop_evt)
78 self._stop() 76 self._stop()
79 77
80 def do(self, callable, *args, **kwargs): 78 def do(self, callable, *args, **kwargs):
81 """
82 Call C{callable} in a thread, with a Connection as first argument.
83 Returns a deferred that will indicate the results of the callable.
84
85 Note: do not return any SQLAlchemy objects via this deferred!
86 """
87 def thd(): 79 def thd():
88 conn = self.engine.contextual_connect() 80 conn = self.engine.contextual_connect()
89 if self.__broken_sqlite: # see bug #1810 81 if self.__broken_sqlite: # see bug #1810
90 conn.execute("select * from sqlite_master") 82 conn.execute("select * from sqlite_master")
91 try: 83 try:
92 rv = callable(conn, *args, **kwargs) 84 rv = callable(conn, *args, **kwargs)
93 assert not isinstance(rv, sa.engine.ResultProxy), \ 85 assert not isinstance(rv, sa.engine.ResultProxy), \
94 "do not return ResultProxy objects!" 86 "do not return ResultProxy objects!"
95 finally: 87 finally:
96 conn.close() 88 conn.close()
97 return rv 89 return rv
98 return threads.deferToThreadPool(reactor, self, thd) 90 return threads.deferToThreadPool(reactor, self, thd)
99 91
100 def do_with_engine(self, callable, *args, **kwargs): 92 def do_with_engine(self, callable, *args, **kwargs):
101 """
102 Like L{do}, but with an SQLAlchemy Engine as the first argument. This
103 is only used for schema manipulation, and is not used at master
104 runtime.
105 """
106 def thd(): 93 def thd():
107 if self.__broken_sqlite: # see bug #1810 94 if self.__broken_sqlite: # see bug #1810
108 self.engine.execute("select * from sqlite_master") 95 self.engine.execute("select * from sqlite_master")
109 rv = callable(self.engine, *args, **kwargs) 96 rv = callable(self.engine, *args, **kwargs)
110 assert not isinstance(rv, sa.engine.ResultProxy), \ 97 assert not isinstance(rv, sa.engine.ResultProxy), \
111 "do not return ResultProxy objects!" 98 "do not return ResultProxy objects!"
112 return rv 99 return rv
113 return threads.deferToThreadPool(reactor, self, thd) 100 return threads.deferToThreadPool(reactor, self, thd)
114 101
115 # older implementations for twisted < 0.8.2, which does not have 102 # older implementations for twisted < 0.8.2, which does not have
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 172
186 try: 173 try:
187 test() 174 test()
188 except sqlite.OperationalError: 175 except sqlite.OperationalError:
189 # this is the expected error indicating it's broken 176 # this is the expected error indicating it's broken
190 return True 177 return True
191 178
192 # but this version should not fail.. 179 # but this version should not fail..
193 test(select_from_sqlite_master=True) 180 test(select_from_sqlite_master=True)
194 return False # not broken - no workaround required 181 return False # not broken - no workaround required
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698