1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2006 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
1802.10.2
by Monty Taylor
Update all of the copyright headers to include the correct address. |
14 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
1
by brian
clean slate |
15 |
|
16 |
||
17 |
/**
|
|
18 |
@file
|
|
19 |
||
20 |
Locking functions for mysql.
|
|
21 |
||
22 |
Because of the new concurrent inserts, we must first get external locks
|
|
23 |
before getting internal locks. If we do it in the other order, the status
|
|
24 |
information is not up to date when called from the lock handler.
|
|
25 |
||
26 |
GENERAL DESCRIPTION OF LOCKING
|
|
27 |
||
28 |
When not using LOCK TABLES:
|
|
29 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
30 |
- For each SQL statement lockTables() is called for all involved
|
1
by brian
clean slate |
31 |
tables.
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
32 |
- lockTables() will call
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
33 |
table_handler->external_lock(session,locktype) for each table.
|
1
by brian
clean slate |
34 |
This is followed by a call to thr_multi_lock() for all tables.
|
35 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
36 |
- When statement is done, we call unlockTables().
|
1859.2.4
by Brian Aker
A few cleanups. |
37 |
This will call DrizzleLock::unlock() followed by
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
38 |
table_handler->external_lock(session, F_UNLCK) for each table.
|
1
by brian
clean slate |
39 |
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
40 |
- Note that unlockTables() may be called several times as
|
1
by brian
clean slate |
41 |
MySQL in some cases can free some tables earlier than others.
|
42 |
||
43 |
- The above is true both for normal and temporary tables.
|
|
44 |
||
45 |
- Temporary non transactional tables are never passed to thr_multi_lock()
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
46 |
and we never call external_lock(session, F_UNLOCK) on these.
|
1
by brian
clean slate |
47 |
|
48 |
When using LOCK TABLES:
|
|
49 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
50 |
- LOCK Table will call lockTables() for all tables.
|
51 |
lockTables() will call
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
52 |
table_handler->external_lock(session,locktype) for each table.
|
1
by brian
clean slate |
53 |
This is followed by a call to thr_multi_lock() for all tables.
|
54 |
||
520.1.21
by Brian Aker
THD -> Session rename |
55 |
- For each statement, we will call table_handler->start_stmt(Session)
|
1
by brian
clean slate |
56 |
to inform the table handler that we are using the table.
|
57 |
||
58 |
The tables used can only be tables used in LOCK TABLES or a
|
|
59 |
temporary table.
|
|
60 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
61 |
- When statement is done, we will call ha_commit_stmt(session);
|
1
by brian
clean slate |
62 |
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
63 |
- When calling UNLOCK TABLES we call unlockTables() for all
|
1
by brian
clean slate |
64 |
tables used in LOCK TABLES
|
65 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
66 |
If table_handler->external_lock(session, locktype) fails, we call
|
67 |
table_handler->external_lock(session, F_UNLCK) for each table that was locked,
|
|
1
by brian
clean slate |
68 |
excluding one that caused failure. That means handler must cleanup itself
|
69 |
in case external_lock() fails.
|
|
70 |
||
71 |
@todo
|
|
641.3.8
by Monty Taylor
Removed my_malloc from drizzled. |
72 |
Change to use malloc() ONLY when using LOCK TABLES command or when
|
1
by brian
clean slate |
73 |
we are forced to use mysql_lock_merge.
|
74 |
*/
|
|
1241.9.36
by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h. |
75 |
#include "config.h" |
1241.9.1
by Monty Taylor
Removed global.h. Fixed all the headers. |
76 |
#include <fcntl.h> |
549
by Monty Taylor
Took gettext.h out of header files. |
77 |
#include <drizzled/error.h> |
1241.9.57
by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined. |
78 |
#include <drizzled/my_hash.h> |
1241.9.43
by Monty Taylor
Merged trunk. Also renamed thr_lock. Doh. I hate it when I do both. |
79 |
#include <drizzled/thr_lock.h> |
584.1.15
by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes. |
80 |
#include <drizzled/session.h> |
81 |
#include <drizzled/sql_base.h> |
|
670.2.4
by Monty Taylor
Removed more stuff from the headers. |
82 |
#include <drizzled/lock.h> |
1241.9.31
by Monty Taylor
Moved global pthread variables into their own header. |
83 |
#include "drizzled/pthread_globals.h" |
1241.9.64
by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal. |
84 |
#include "drizzled/internal/my_sys.h" |
1812.3.7
by Brian Aker
Typdef our lock type. |
85 |
#include "drizzled/pthread_globals.h" |
1241.9.62
by Monty Taylor
Removed plugin/myisam/myisam.h from session.h |
86 |
|
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
87 |
#include <set> |
88 |
#include <vector> |
|
89 |
#include <algorithm> |
|
90 |
#include <functional> |
|
91 |
||
1812.3.7
by Brian Aker
Typdef our lock type. |
92 |
#include <boost/thread/shared_mutex.hpp> |
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
93 |
#include <boost/thread/condition_variable.hpp> |
94 |
||
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
95 |
using namespace std; |
96 |
||
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
97 |
namespace drizzled |
98 |
{
|
|
1
by brian
clean slate |
99 |
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
100 |
static boost::mutex LOCK_global_read_lock; |
1812.3.5
by Brian Aker
Move to boost condition_any |
101 |
static boost::condition_variable_any COND_global_read_lock; |
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
102 |
|
1
by brian
clean slate |
103 |
/**
|
104 |
@defgroup Locking Locking
|
|
105 |
@{
|
|
106 |
*/
|
|
107 |
||
108 |
static void print_lock_error(int error, const char *); |
|
109 |
||
110 |
/*
|
|
111 |
Lock tables.
|
|
112 |
||
113 |
SYNOPSIS
|
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
114 |
lockTables()
|
1
by brian
clean slate |
115 |
tables An array of pointers to the tables to lock.
|
116 |
count The number of tables to lock.
|
|
117 |
flags Options:
|
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
118 |
DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK Ignore a global read lock
|
119 |
DRIZZLE_LOCK_IGNORE_FLUSH Ignore a flush tables.
|
|
120 |
DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN Instead of reopening altered
|
|
1
by brian
clean slate |
121 |
or dropped tables by itself,
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
122 |
lockTables() should
|
1
by brian
clean slate |
123 |
notify upper level and rely
|
124 |
on caller doing this.
|
|
125 |
need_reopen Out parameter, TRUE if some tables were altered
|
|
126 |
or deleted and should be reopened by caller.
|
|
127 |
||
128 |
RETURN
|
|
129 |
A lock structure pointer on success.
|
|
130 |
NULL on error or if some tables should be reopen.
|
|
131 |
*/
|
|
132 |
||
133 |
/* Map the return value of thr_lock to an error from errmsg.txt */
|
|
134 |
static int thr_lock_errno_to_mysql[]= |
|
135 |
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK }; |
|
136 |
||
137 |
||
138 |
/**
|
|
139 |
Reset lock type in lock data and free.
|
|
140 |
||
141 |
@param mysql_lock Lock structures to reset.
|
|
142 |
||
143 |
@note After a locking error we want to quit the locking of the table(s).
|
|
144 |
The test case in the bug report for Bug #18544 has the following
|
|
145 |
cases: 1. Locking error in lock_external() due to InnoDB timeout.
|
|
146 |
2. Locking error in get_lock_data() due to missing write permission.
|
|
147 |
3. Locking error in wait_if_global_read_lock() due to lock conflict.
|
|
148 |
||
149 |
@note In all these cases we have already set the lock type into the lock
|
|
150 |
data of the open table(s). If the table(s) are in the open table
|
|
151 |
cache, they could be reused with the non-zero lock type set. This
|
|
152 |
could lead to ignoring a different lock type with the next lock.
|
|
153 |
||
154 |
@note Clear the lock type of all lock data. This ensures that the next
|
|
155 |
lock request will set its lock type properly.
|
|
156 |
*/
|
|
157 |
||
1711.6.1
by Brian Aker
Style on structure cleanup |
158 |
static void reset_lock_data_and_free(DrizzleLock **mysql_lock) |
1
by brian
clean slate |
159 |
{
|
1711.6.1
by Brian Aker
Style on structure cleanup |
160 |
DrizzleLock *sql_lock= *mysql_lock; |
1859.2.4
by Brian Aker
A few cleanups. |
161 |
sql_lock->reset(); |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
162 |
delete sql_lock; |
1
by brian
clean slate |
163 |
*mysql_lock= 0; |
164 |
}
|
|
165 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
166 |
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen) |
1
by brian
clean slate |
167 |
{
|
1711.6.1
by Brian Aker
Style on structure cleanup |
168 |
DrizzleLock *sql_lock; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
169 |
Table *write_lock_used; |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
170 |
vector<plugin::StorageEngine *> involved_engines; |
1
by brian
clean slate |
171 |
int rc; |
172 |
||
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
173 |
*need_reopen= false; |
1
by brian
clean slate |
174 |
|
175 |
for (;;) |
|
176 |
{
|
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
177 |
if (! (sql_lock= get_lock_data(tables, count, true, |
1
by brian
clean slate |
178 |
&write_lock_used))) |
179 |
break; |
|
180 |
||
181 |
if (global_read_lock && write_lock_used && |
|
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
182 |
! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK)) |
1
by brian
clean slate |
183 |
{
|
184 |
/*
|
|
185 |
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
|
|
186 |
Wait until the lock is gone
|
|
187 |
*/
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
188 |
if (wait_if_global_read_lock(1, 1)) |
1
by brian
clean slate |
189 |
{
|
190 |
/* Clear the lock type of all lock data to avoid reusage. */
|
|
191 |
reset_lock_data_and_free(&sql_lock); |
|
192 |
break; |
|
193 |
}
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
194 |
if (version != refresh_version) |
1
by brian
clean slate |
195 |
{
|
196 |
/* Clear the lock type of all lock data to avoid reusage. */
|
|
197 |
reset_lock_data_and_free(&sql_lock); |
|
198 |
goto retry; |
|
199 |
}
|
|
200 |
}
|
|
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
201 |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
202 |
set_proc_info("Notify start statement"); |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
203 |
/*
|
204 |
* Here, we advise all storage engines involved in the
|
|
205 |
* statement that we are starting a new statement
|
|
206 |
*/
|
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
207 |
if (sql_lock->sizeTable()) |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
208 |
{
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
209 |
size_t num_tables= sql_lock->sizeTable(); |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
210 |
plugin::StorageEngine *engine; |
211 |
set<size_t> involved_slots; |
|
212 |
for (size_t x= 1; x <= num_tables; x++, tables++) |
|
213 |
{
|
|
1506
by Brian Aker
encapsulate engine inside of cursor. |
214 |
engine= (*tables)->cursor->getEngine(); |
1273.1.32
by Jay Pipes
Fixes Bug #530870 |
215 |
if (involved_slots.count(engine->getId()) > 0) |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
216 |
continue; /* already added to involved engines */ |
217 |
involved_engines.push_back(engine); |
|
1273.1.32
by Jay Pipes
Fixes Bug #530870 |
218 |
involved_slots.insert(engine->getId()); |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
219 |
}
|
220 |
||
221 |
for_each(involved_engines.begin(), |
|
222 |
involved_engines.end(), |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
223 |
bind2nd(mem_fun(&plugin::StorageEngine::startStatement), this)); |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
224 |
}
|
225 |
||
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
226 |
set_proc_info("External lock"); |
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
227 |
/*
|
228 |
* Here, the call to lock_external() informs the
|
|
229 |
* all engines for all tables used in this statement
|
|
230 |
* of the type of lock that Drizzle intends to take on a
|
|
231 |
* specific table.
|
|
232 |
*/
|
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
233 |
if (sql_lock->sizeTable() && lock_external(sql_lock->getTable(), sql_lock->sizeTable())) |
1
by brian
clean slate |
234 |
{
|
235 |
/* Clear the lock type of all lock data to avoid reusage. */
|
|
236 |
reset_lock_data_and_free(&sql_lock); |
|
237 |
break; |
|
238 |
}
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
239 |
set_proc_info("Table lock"); |
1
by brian
clean slate |
240 |
/* Copy the lock data array. thr_multi_lock() reorders its contens. */
|
1948.2.3
by Brian Aker
Update on lock count. |
241 |
memcpy(sql_lock->getLocks() + sql_lock->sizeLock(), |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
242 |
sql_lock->getLocks(), |
1948.2.3
by Brian Aker
Update on lock count. |
243 |
sql_lock->sizeLock() * sizeof(*sql_lock->getLocks())); |
1
by brian
clean slate |
244 |
/* Lock on the copied half of the lock data array. */
|
1960.1.1
by Brian Aker
Remove dead code in wait, pass session. |
245 |
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this, |
246 |
sql_lock->getLocks() + |
|
1948.2.3
by Brian Aker
Update on lock count. |
247 |
sql_lock->sizeLock(), |
248 |
sql_lock->sizeLock(), |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
249 |
this->lock_id)]; |
1
by brian
clean slate |
250 |
if (rc > 1) /* a timeout or a deadlock */ |
251 |
{
|
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
252 |
if (sql_lock->sizeTable()) |
253 |
unlock_external(sql_lock->getTable(), sql_lock->sizeTable()); |
|
1
by brian
clean slate |
254 |
reset_lock_data_and_free(&sql_lock); |
255 |
my_error(rc, MYF(0)); |
|
256 |
break; |
|
257 |
}
|
|
258 |
else if (rc == 1) /* aborted */ |
|
259 |
{
|
|
1948.2.3
by Brian Aker
Update on lock count. |
260 |
some_tables_deleted= true; // Try again |
261 |
sql_lock->setLock(0); // Locks are already freed |
|
1
by brian
clean slate |
262 |
// Fall through: unlock, reset lock data, free and retry
|
263 |
}
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
264 |
else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH)) |
1
by brian
clean slate |
265 |
{
|
266 |
/*
|
|
267 |
Thread was killed or lock aborted. Let upper level close all
|
|
268 |
used tables and retry or give error.
|
|
269 |
*/
|
|
270 |
break; |
|
271 |
}
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
272 |
else if (not open_tables) |
1
by brian
clean slate |
273 |
{
|
274 |
// Only using temporary tables, no need to unlock
|
|
1948.2.3
by Brian Aker
Update on lock count. |
275 |
some_tables_deleted= false; |
1
by brian
clean slate |
276 |
break; |
277 |
}
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
278 |
set_proc_info(0); |
1
by brian
clean slate |
279 |
|
280 |
/* going to retry, unlock all tables */
|
|
1948.2.3
by Brian Aker
Update on lock count. |
281 |
if (sql_lock->sizeLock()) |
282 |
sql_lock->unlock(sql_lock->sizeLock()); |
|
1
by brian
clean slate |
283 |
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
284 |
if (sql_lock->sizeTable()) |
285 |
unlock_external(sql_lock->getTable(), sql_lock->sizeTable()); |
|
1
by brian
clean slate |
286 |
|
287 |
/*
|
|
288 |
If thr_multi_lock fails it resets lock type for tables, which
|
|
289 |
were locked before (and including) one that caused error. Lock
|
|
290 |
type for other tables preserved.
|
|
291 |
*/
|
|
292 |
reset_lock_data_and_free(&sql_lock); |
|
1273.1.21
by Jay Pipes
* Remove dead ha_innobase::init_table_handle_for_HANDLER() |
293 |
|
294 |
/*
|
|
295 |
* Notify all involved engines that the
|
|
296 |
* SQL statement has ended
|
|
297 |
*/
|
|
298 |
for_each(involved_engines.begin(), |
|
299 |
involved_engines.end(), |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
300 |
bind2nd(mem_fun(&plugin::StorageEngine::endStatement), this)); |
1
by brian
clean slate |
301 |
retry: |
319.1.1
by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_ |
302 |
if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN) |
1
by brian
clean slate |
303 |
{
|
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
304 |
*need_reopen= true; |
1
by brian
clean slate |
305 |
break; |
306 |
}
|
|
1910.2.6
by Brian Aker
Cleanup goto |
307 |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
308 |
if (wait_for_tables(this)) |
1910.2.6
by Brian Aker
Cleanup goto |
309 |
{
|
1
by brian
clean slate |
310 |
break; // Couldn't open tables |
1910.2.6
by Brian Aker
Cleanup goto |
311 |
}
|
1
by brian
clean slate |
312 |
}
|
1910.2.6
by Brian Aker
Cleanup goto |
313 |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
314 |
set_proc_info(0); |
1910.2.8
by Brian Aker
Enapsulate Kill. |
315 |
if (getKilled()) |
1
by brian
clean slate |
316 |
{
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
317 |
send_kill_message(); |
1
by brian
clean slate |
318 |
if (sql_lock) |
319 |
{
|
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
320 |
unlockTables(sql_lock); |
1054.1.8
by Brian Aker
Remove lock_tables list from session. |
321 |
sql_lock= NULL; |
1
by brian
clean slate |
322 |
}
|
323 |
}
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
324 |
set_time_after_lock(); |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
325 |
return (sql_lock); |
1
by brian
clean slate |
326 |
}
|
327 |
||
328 |
||
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
329 |
int Session::lock_external(Table **tables, uint32_t count) |
1
by brian
clean slate |
330 |
{
|
331 |
int lock_type,error; |
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
332 |
for (uint32_t i= 1 ; i <= count ; i++, tables++) |
1
by brian
clean slate |
333 |
{
|
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
334 |
assert((*tables)->reginfo.lock_type >= TL_READ); |
1
by brian
clean slate |
335 |
lock_type=F_WRLCK; /* Lock exclusive */ |
784.1.6
by Stewart Smith
merge |
336 |
if ((*tables)->db_stat & HA_READ_ONLY || |
1
by brian
clean slate |
337 |
((*tables)->reginfo.lock_type >= TL_READ && |
338 |
(*tables)->reginfo.lock_type <= TL_READ_NO_INSERT)) |
|
339 |
lock_type=F_RDLCK; |
|
340 |
||
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
341 |
if ((error=(*tables)->cursor->ha_external_lock(this,lock_type))) |
1
by brian
clean slate |
342 |
{
|
1506
by Brian Aker
encapsulate engine inside of cursor. |
343 |
print_lock_error(error, (*tables)->cursor->getEngine()->getName().c_str()); |
1
by brian
clean slate |
344 |
while (--i) |
345 |
{
|
|
346 |
tables--; |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
347 |
(*tables)->cursor->ha_external_lock(this, F_UNLCK); |
1
by brian
clean slate |
348 |
(*tables)->current_lock=F_UNLCK; |
349 |
}
|
|
1046.1.7
by Brian Aker
Style cleanup. |
350 |
return error; |
1
by brian
clean slate |
351 |
}
|
352 |
else
|
|
353 |
{
|
|
354 |
(*tables)->db_stat &= ~ HA_BLOCK_LOCK; |
|
355 |
(*tables)->current_lock= lock_type; |
|
356 |
}
|
|
357 |
}
|
|
1046.1.7
by Brian Aker
Style cleanup. |
358 |
return 0; |
1
by brian
clean slate |
359 |
}
|
360 |
||
361 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
362 |
void Session::unlockTables(DrizzleLock *sql_lock) |
1
by brian
clean slate |
363 |
{
|
1948.2.3
by Brian Aker
Update on lock count. |
364 |
if (sql_lock->sizeLock()) |
365 |
sql_lock->unlock(sql_lock->sizeLock()); |
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
366 |
if (sql_lock->sizeTable()) |
367 |
unlock_external(sql_lock->getTable(), sql_lock->sizeTable()); |
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
368 |
delete sql_lock; |
1
by brian
clean slate |
369 |
}
|
370 |
||
371 |
/**
|
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
372 |
Unlock some of the tables locked by lockTables.
|
1
by brian
clean slate |
373 |
|
374 |
This will work even if get_lock_data fails (next unlock will free all)
|
|
375 |
*/
|
|
376 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
377 |
void Session::unlockSomeTables(Table **table, uint32_t count) |
1
by brian
clean slate |
378 |
{
|
1711.6.1
by Brian Aker
Style on structure cleanup |
379 |
DrizzleLock *sql_lock; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
380 |
Table *write_lock_used; |
1910.2.4
by Brian Aker
Push some functions behind classes. |
381 |
if ((sql_lock= get_lock_data(table, count, false, |
1
by brian
clean slate |
382 |
&write_lock_used))) |
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
383 |
unlockTables(sql_lock); |
1
by brian
clean slate |
384 |
}
|
385 |
||
386 |
||
387 |
/**
|
|
388 |
unlock all tables locked for read.
|
|
389 |
*/
|
|
390 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
391 |
void Session::unlockReadTables(DrizzleLock *sql_lock) |
1
by brian
clean slate |
392 |
{
|
482
by Brian Aker
Remove uint. |
393 |
uint32_t i,found; |
1
by brian
clean slate |
394 |
|
395 |
/* Move all write locks first */
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
396 |
THR_LOCK_DATA **lock_local= sql_lock->getLocks(); |
1948.2.3
by Brian Aker
Update on lock count. |
397 |
for (i=found=0 ; i < sql_lock->sizeLock(); i++) |
1
by brian
clean slate |
398 |
{
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
399 |
if (sql_lock->getLocks()[i]->type >= TL_WRITE_ALLOW_READ) |
1
by brian
clean slate |
400 |
{
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
401 |
std::swap(*lock_local, sql_lock->getLocks()[i]); |
402 |
lock_local++; |
|
1
by brian
clean slate |
403 |
found++; |
404 |
}
|
|
405 |
}
|
|
406 |
/* unlock the read locked tables */
|
|
407 |
if (i != found) |
|
408 |
{
|
|
1948.2.1
by Brian Aker
Fix for 680028, crash on SELECT FOR UPDATE afer FLUSH TABLES WITH READ LOCKS |
409 |
thr_multi_unlock(lock_local, i - found); |
1948.2.3
by Brian Aker
Update on lock count. |
410 |
sql_lock->setLock(found); |
1
by brian
clean slate |
411 |
}
|
412 |
||
413 |
/* Then do the same for the external locks */
|
|
414 |
/* Move all write locked tables first */
|
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
415 |
Table **table= sql_lock->getTable(); |
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
416 |
for (i=found=0 ; i < sql_lock->sizeTable() ; i++) |
1
by brian
clean slate |
417 |
{
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
418 |
assert(sql_lock->getTable()[i]->lock_position == i); |
419 |
if ((uint32_t) sql_lock->getTable()[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ) |
|
1
by brian
clean slate |
420 |
{
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
421 |
std::swap(*table, sql_lock->getTable()[i]); |
1
by brian
clean slate |
422 |
table++; |
423 |
found++; |
|
424 |
}
|
|
425 |
}
|
|
426 |
/* Unlock all read locked tables */
|
|
427 |
if (i != found) |
|
428 |
{
|
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
429 |
unlock_external(table, i - found); |
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
430 |
sql_lock->resizeTable(found); |
1
by brian
clean slate |
431 |
}
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
432 |
/* Fix the lock positions in Table */
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
433 |
table= sql_lock->getTable(); |
1
by brian
clean slate |
434 |
found= 0; |
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
435 |
for (i= 0; i < sql_lock->sizeTable(); i++) |
1
by brian
clean slate |
436 |
{
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
437 |
Table *tbl= *table; |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
438 |
tbl->lock_position= table - sql_lock->getTable(); |
1
by brian
clean slate |
439 |
tbl->lock_data_start= found; |
440 |
found+= tbl->lock_count; |
|
441 |
table++; |
|
442 |
}
|
|
443 |
}
|
|
444 |
||
445 |
||
446 |
/**
|
|
447 |
Try to find the table in the list of locked tables.
|
|
448 |
In case of success, unlock the table and remove it from this list.
|
|
449 |
||
450 |
@note This function has a legacy side effect: the table is
|
|
451 |
unlocked even if it is not found in the locked list.
|
|
452 |
It's not clear if this side effect is intentional or still
|
|
453 |
desirable. It might lead to unmatched calls to
|
|
454 |
unlock_external(). Moreover, a discrepancy can be left
|
|
455 |
unnoticed by the storage engine, because in
|
|
456 |
unlock_external() we call handler::external_lock(F_UNLCK) only
|
|
457 |
if table->current_lock is not F_UNLCK.
|
|
458 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
459 |
@param session thread context
|
1
by brian
clean slate |
460 |
@param locked list of locked tables
|
461 |
@param table the table to unlock
|
|
462 |
@param always_unlock specify explicitly if the legacy side
|
|
463 |
effect is desired.
|
|
464 |
*/
|
|
465 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
466 |
void Session::removeLock(Table *table) |
1
by brian
clean slate |
467 |
{
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
468 |
unlockSomeTables(&table, /* table count */ 1); |
1
by brian
clean slate |
469 |
}
|
470 |
||
471 |
||
472 |
/** Abort all other threads waiting to get lock in table. */
|
|
473 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
474 |
void Session::abortLock(Table *table) |
1
by brian
clean slate |
475 |
{
|
1711.6.1
by Brian Aker
Style on structure cleanup |
476 |
DrizzleLock *locked; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
477 |
Table *write_lock_used; |
1
by brian
clean slate |
478 |
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
479 |
if ((locked= get_lock_data(&table, 1, false, |
1
by brian
clean slate |
480 |
&write_lock_used))) |
481 |
{
|
|
1948.2.3
by Brian Aker
Update on lock count. |
482 |
for (uint32_t x= 0; x < locked->sizeLock(); x++) |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
483 |
locked->getLocks()[x]->lock->abort_locks(); |
484 |
delete locked; |
|
1
by brian
clean slate |
485 |
}
|
486 |
}
|
|
487 |
||
488 |
||
489 |
/**
|
|
490 |
Abort one thread / table combination.
|
|
491 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
492 |
@param session Thread handler
|
1
by brian
clean slate |
493 |
@param table Table that should be removed from lock queue
|
494 |
||
495 |
@retval
|
|
496 |
0 Table was not locked by another thread
|
|
497 |
@retval
|
|
498 |
1 Table was locked by at least one other thread
|
|
499 |
*/
|
|
500 |
||
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
501 |
bool Session::abortLockForThread(Table *table) |
1
by brian
clean slate |
502 |
{
|
1711.6.1
by Brian Aker
Style on structure cleanup |
503 |
DrizzleLock *locked; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
504 |
Table *write_lock_used; |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
505 |
bool result= false; |
1
by brian
clean slate |
506 |
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
507 |
if ((locked= get_lock_data(&table, 1, false, |
1
by brian
clean slate |
508 |
&write_lock_used))) |
509 |
{
|
|
1948.2.3
by Brian Aker
Update on lock count. |
510 |
for (uint32_t i= 0; i < locked->sizeLock(); i++) |
1
by brian
clean slate |
511 |
{
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
512 |
if (locked->getLocks()[i]->lock->abort_locks_for_thread(table->in_use->thread_id)) |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
513 |
result= true; |
1
by brian
clean slate |
514 |
}
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
515 |
delete locked; |
1
by brian
clean slate |
516 |
}
|
1046.1.7
by Brian Aker
Style cleanup. |
517 |
return result; |
1
by brian
clean slate |
518 |
}
|
519 |
||
520 |
/** Unlock a set of external. */
|
|
521 |
||
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
522 |
int Session::unlock_external(Table **table, uint32_t count) |
1
by brian
clean slate |
523 |
{
|
524 |
int error,error_code; |
|
525 |
||
526 |
error_code=0; |
|
527 |
do
|
|
528 |
{
|
|
529 |
if ((*table)->current_lock != F_UNLCK) |
|
530 |
{
|
|
531 |
(*table)->current_lock = F_UNLCK; |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
532 |
if ((error=(*table)->cursor->ha_external_lock(this, F_UNLCK))) |
1
by brian
clean slate |
533 |
{
|
534 |
error_code=error; |
|
1506
by Brian Aker
encapsulate engine inside of cursor. |
535 |
print_lock_error(error_code, (*table)->cursor->getEngine()->getName().c_str()); |
1
by brian
clean slate |
536 |
}
|
537 |
}
|
|
538 |
table++; |
|
539 |
} while (--count); |
|
1046.1.7
by Brian Aker
Style cleanup. |
540 |
return error_code; |
1
by brian
clean slate |
541 |
}
|
542 |
||
543 |
||
544 |
/**
|
|
545 |
Get lock structures from table structs and initialize locks.
|
|
546 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
547 |
@param session Thread handler
|
1
by brian
clean slate |
548 |
@param table_ptr Pointer to tables that should be locks
|
1046.1.7
by Brian Aker
Style cleanup. |
549 |
@param should_lock One of:
|
550 |
- false : If we should send TL_IGNORE to store lock
|
|
551 |
- true : Store lock info in Table
|
|
1
by brian
clean slate |
552 |
@param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE
|
553 |
*/
|
|
554 |
||
1910.2.4
by Brian Aker
Push some functions behind classes. |
555 |
DrizzleLock *Session::get_lock_data(Table **table_ptr, uint32_t count, |
556 |
bool should_lock, Table **write_lock_used) |
|
1
by brian
clean slate |
557 |
{
|
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
558 |
uint32_t lock_count; |
1
by brian
clean slate |
559 |
THR_LOCK_DATA **locks, **locks_buf, **locks_start; |
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
560 |
Table **to, **table_buf; |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
561 |
|
1
by brian
clean slate |
562 |
*write_lock_used=0; |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
563 |
for (uint32_t i= lock_count= 0 ; i < count ; i++) |
1
by brian
clean slate |
564 |
{
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
565 |
Table *t= table_ptr[i]; |
1
by brian
clean slate |
566 |
|
1235.1.2
by Brian Aker
Added engine flag so that an engine can skip store_lock. |
567 |
if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK))) |
1
by brian
clean slate |
568 |
{
|
569 |
lock_count++; |
|
570 |
}
|
|
571 |
}
|
|
572 |
||
573 |
/*
|
|
574 |
Allocating twice the number of pointers for lock data for use in
|
|
575 |
thr_mulit_lock(). This function reorders the lock data, but cannot
|
|
576 |
update the table values. So the second part of the array is copied
|
|
577 |
from the first part immediately before calling thr_multi_lock().
|
|
578 |
*/
|
|
1948.2.2
by Brian Aker
Merge in change where we remove the need for the additional variable for |
579 |
DrizzleLock *sql_lock= new DrizzleLock(lock_count); |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
580 |
|
581 |
if (not sql_lock) |
|
1046.1.7
by Brian Aker
Style cleanup. |
582 |
return NULL; |
1859.2.2
by Brian Aker
First pass on removing malloc from DrizzleLock |
583 |
|
584 |
locks= locks_buf= sql_lock->getLocks(); |
|
585 |
to= table_buf= sql_lock->getTable(); |
|
1
by brian
clean slate |
586 |
|
1749.3.13
by Brian Aker
cppcheck fix. |
587 |
for (uint32_t i= 0; i < count ; i++) |
1
by brian
clean slate |
588 |
{
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
589 |
Table *table; |
1
by brian
clean slate |
590 |
enum thr_lock_type lock_type; |
591 |
||
1235.1.2
by Brian Aker
Added engine flag so that an engine can skip store_lock. |
592 |
if (table_ptr[i]->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)) |
1
by brian
clean slate |
593 |
continue; |
1235.1.2
by Brian Aker
Added engine flag so that an engine can skip store_lock. |
594 |
|
1220.1.12
by Brian Aker
Small cleanup from something Jay noticed. |
595 |
table= table_ptr[i]; |
1
by brian
clean slate |
596 |
lock_type= table->reginfo.lock_type; |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
597 |
assert (lock_type != TL_WRITE_DEFAULT); |
1
by brian
clean slate |
598 |
if (lock_type >= TL_WRITE_ALLOW_WRITE) |
599 |
{
|
|
600 |
*write_lock_used=table; |
|
784.1.6
by Stewart Smith
merge |
601 |
if (table->db_stat & HA_READ_ONLY) |
1
by brian
clean slate |
602 |
{
|
1669.2.6
by Brian Aker
First pass through encapsulating getAlias() from table. |
603 |
my_error(ER_OPEN_AS_READONLY, MYF(0), table->getAlias()); |
1
by brian
clean slate |
604 |
/* Clear the lock type of the lock data that are stored already. */
|
1948.2.3
by Brian Aker
Update on lock count. |
605 |
sql_lock->setLock(locks - sql_lock->getLocks()); |
1
by brian
clean slate |
606 |
reset_lock_data_and_free(&sql_lock); |
1046.1.7
by Brian Aker
Style cleanup. |
607 |
return NULL; |
1
by brian
clean slate |
608 |
}
|
609 |
}
|
|
610 |
locks_start= locks; |
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
611 |
locks= table->cursor->store_lock(this, locks, should_lock == false ? TL_IGNORE : lock_type); |
1046.1.7
by Brian Aker
Style cleanup. |
612 |
if (should_lock) |
1
by brian
clean slate |
613 |
{
|
895
by Brian Aker
Completion (?) of uint conversion. |
614 |
table->lock_position= (uint32_t) (to - table_buf); |
615 |
table->lock_data_start= (uint32_t) (locks_start - locks_buf); |
|
616 |
table->lock_count= (uint32_t) (locks - locks_start); |
|
1046.1.7
by Brian Aker
Style cleanup. |
617 |
assert(table->lock_count == 1); |
1
by brian
clean slate |
618 |
}
|
619 |
*to++= table; |
|
620 |
}
|
|
621 |
/*
|
|
622 |
We do not use 'tables', because there are cases where store_lock()
|
|
623 |
returns less locks than lock_count() claimed. This can happen when
|
|
624 |
a FLUSH TABLES tries to abort locks from a MERGE table of another
|
|
625 |
thread. When that thread has just opened the table, but not yet
|
|
626 |
attached its children, it cannot return the locks. lock_count()
|
|
627 |
always returns the number of locks that an attached table has.
|
|
628 |
This is done to avoid the reverse situation: If lock_count() would
|
|
629 |
return 0 for a non-attached MERGE table, and that table becomes
|
|
630 |
attached between the calls to lock_count() and store_lock(), then
|
|
631 |
we would have allocated too little memory for the lock data. Now
|
|
632 |
we may allocate too much, but better safe than memory overrun.
|
|
633 |
And in the FLUSH case, the memory is released quickly anyway.
|
|
634 |
*/
|
|
1948.2.3
by Brian Aker
Update on lock count. |
635 |
sql_lock->setLock(locks - locks_buf); |
1046.1.7
by Brian Aker
Style cleanup. |
636 |
|
637 |
return sql_lock; |
|
1
by brian
clean slate |
638 |
}
|
639 |
||
640 |
||
641 |
/**
|
|
642 |
Put a not open table with an old refresh version in the table cache.
|
|
643 |
||
644 |
@param table_list Lock first table in this list
|
|
645 |
@param check_in_use Do we need to check if table already in use by us
|
|
646 |
||
647 |
@note
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
648 |
One must have a lock on table::Cache::singleton().mutex()!
|
1
by brian
clean slate |
649 |
|
650 |
@warning
|
|
651 |
If you are going to update the table, you should use
|
|
1113.1.2
by Brian Aker
Refactor/kill some dead lock code. |
652 |
lock_and_wait_for_table_name(removed) instead of this function as this works
|
1
by brian
clean slate |
653 |
together with 'FLUSH TABLES WITH READ LOCK'
|
654 |
||
655 |
@note
|
|
656 |
This will force any other threads that uses the table to release it
|
|
657 |
as soon as possible.
|
|
658 |
||
659 |
@return
|
|
660 |
< 0 error
|
|
661 |
@return
|
|
662 |
== 0 table locked
|
|
663 |
@return
|
|
664 |
> 0 table locked, but someone is using it
|
|
665 |
*/
|
|
666 |
||
1910.2.4
by Brian Aker
Push some functions behind classes. |
667 |
int Session::lock_table_name(TableList *table_list) |
1
by brian
clean slate |
668 |
{
|
1874.1.2
by Brian Aker
Encapsulate table_name from table_list. |
669 |
TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName()); |
1618
by Brian Aker
This is a rollup set of patches for modifications to TableIdentifier to have |
670 |
const TableIdentifier::Key &key(identifier.getKey()); |
1
by brian
clean slate |
671 |
|
672 |
{
|
|
673 |
/* Only insert the table if we haven't insert it already */
|
|
1877.2.4
by Brian Aker
Shift over to cache definition in table/cache |
674 |
table::CacheRange ppp; |
1669
by Brian Aker
This patch turns the table_cache into boost::unordered_multimap. |
675 |
|
1877.2.5
by Brian Aker
Shift a bit more of the guts of cache to its own space. |
676 |
ppp= table::getCache().equal_range(key); |
1669
by Brian Aker
This patch turns the table_cache into boost::unordered_multimap. |
677 |
|
1877.2.6
by Brian Aker
Fixed header/etc. |
678 |
for (table::CacheMap::const_iterator iter= ppp.first; |
1669
by Brian Aker
This patch turns the table_cache into boost::unordered_multimap. |
679 |
iter != ppp.second; ++iter) |
1
by brian
clean slate |
680 |
{
|
1669
by Brian Aker
This patch turns the table_cache into boost::unordered_multimap. |
681 |
Table *table= (*iter).second; |
1
by brian
clean slate |
682 |
if (table->reginfo.lock_type < TL_WRITE) |
683 |
{
|
|
684 |
continue; |
|
685 |
}
|
|
686 |
||
1910.2.4
by Brian Aker
Push some functions behind classes. |
687 |
if (table->in_use == this) |
1
by brian
clean slate |
688 |
{
|
1578.2.3
by Brian Aker
Take version and encapsulate it in TableShare |
689 |
table->getMutableShare()->resetVersion(); // Ensure no one can use this |
1532.1.14
by Brian Aker
We no longer use alloc for placeholders (due to HASH I didn't use a |
690 |
table->locked_by_name= true; |
1046.1.7
by Brian Aker
Style cleanup. |
691 |
return 0; |
1
by brian
clean slate |
692 |
}
|
693 |
}
|
|
694 |
}
|
|
695 |
||
1877.2.1
by Brian Aker
Refactor table_cache_insert_placeholder. |
696 |
table::Placeholder *table= NULL; |
1910.2.4
by Brian Aker
Push some functions behind classes. |
697 |
if (!(table= table_cache_insert_placeholder(identifier))) |
1532.1.14
by Brian Aker
We no longer use alloc for placeholders (due to HASH I didn't use a |
698 |
{
|
1046.1.7
by Brian Aker
Style cleanup. |
699 |
return -1; |
1532.1.14
by Brian Aker
We no longer use alloc for placeholders (due to HASH I didn't use a |
700 |
}
|
1
by brian
clean slate |
701 |
|
1877.2.1
by Brian Aker
Refactor table_cache_insert_placeholder. |
702 |
table_list->table= reinterpret_cast<Table *>(table); |
1
by brian
clean slate |
703 |
|
704 |
/* Return 1 if table is in use */
|
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
705 |
return(test(table::Cache::singleton().removeTable(this, identifier, RTFC_NO_FLAG))); |
1
by brian
clean slate |
706 |
}
|
707 |
||
708 |
||
1910.2.4
by Brian Aker
Push some functions behind classes. |
709 |
void TableList::unlock_table_name() |
1
by brian
clean slate |
710 |
{
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
711 |
if (table) |
1
by brian
clean slate |
712 |
{
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
713 |
table::remove_table(static_cast<table::Concurrent *>(table)); |
1910.2.5
by Brian Aker
Merge in changes such that lock is now broken out into its own directory. |
714 |
locking::broadcast_refresh(); |
1
by brian
clean slate |
715 |
}
|
716 |
}
|
|
717 |
||
718 |
||
1019.1.1
by Brian Aker
Merge (also removes session from show variables). |
719 |
static bool locked_named_table(TableList *table_list) |
1
by brian
clean slate |
720 |
{
|
721 |
for (; table_list ; table_list=table_list->next_local) |
|
722 |
{
|
|
327.1.5
by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h |
723 |
Table *table= table_list->table; |
1
by brian
clean slate |
724 |
if (table) |
725 |
{
|
|
1608
by Brian Aker
This encapsulates prev/next. |
726 |
Table *save_next= table->getNext(); |
1
by brian
clean slate |
727 |
bool result; |
1608
by Brian Aker
This encapsulates prev/next. |
728 |
table->setNext(NULL); |
1877.2.7
by Brian Aker
Encapsulate more of the table cache. |
729 |
result= table::Cache::singleton().areTablesUsed(table_list->table, 0); |
1608
by Brian Aker
This encapsulates prev/next. |
730 |
table->setNext(save_next); |
1
by brian
clean slate |
731 |
if (result) |
732 |
return 1; |
|
733 |
}
|
|
734 |
}
|
|
735 |
return 0; // All tables are locked |
|
736 |
}
|
|
737 |
||
738 |
||
1910.2.4
by Brian Aker
Push some functions behind classes. |
739 |
bool Session::wait_for_locked_table_names(TableList *table_list) |
1
by brian
clean slate |
740 |
{
|
1046.1.7
by Brian Aker
Style cleanup. |
741 |
bool result= false; |
1
by brian
clean slate |
742 |
|
1798.3.8
by Brian Aker
Additional removal of native_handle |
743 |
#if 0
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
744 |
assert(ownership of table::Cache::singleton().mutex());
|
1798.3.8
by Brian Aker
Additional removal of native_handle |
745 |
#endif
|
1
by brian
clean slate |
746 |
|
1019.1.1
by Brian Aker
Merge (also removes session from show variables). |
747 |
while (locked_named_table(table_list)) |
1
by brian
clean slate |
748 |
{
|
1910.2.8
by Brian Aker
Enapsulate Kill. |
749 |
if (getKilled()) |
1
by brian
clean slate |
750 |
{
|
751 |
result=1; |
|
752 |
break; |
|
753 |
}
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
754 |
wait_for_condition(table::Cache::singleton().mutex(), COND_refresh); |
755 |
table::Cache::singleton().mutex().lock(); /* Wait for a table to unlock and then lock it */ |
|
1
by brian
clean slate |
756 |
}
|
1046.1.7
by Brian Aker
Style cleanup. |
757 |
return result; |
1
by brian
clean slate |
758 |
}
|
759 |
||
760 |
||
761 |
/**
|
|
762 |
Lock all tables in list with a name lock.
|
|
763 |
||
764 |
REQUIREMENTS
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
765 |
- One must have a lock on table::Cache::singleton().mutex() when calling this
|
1
by brian
clean slate |
766 |
|
767 |
@param table_list Names of tables to lock
|
|
768 |
||
769 |
@retval
|
|
770 |
0 ok
|
|
771 |
@retval
|
|
772 |
1 Fatal error (end of memory ?)
|
|
773 |
*/
|
|
774 |
||
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
775 |
bool Session::lock_table_names(TableList *table_list) |
1
by brian
clean slate |
776 |
{
|
1910.2.6
by Brian Aker
Cleanup goto |
777 |
bool got_all_locks= true; |
327.2.4
by Brian Aker
Refactoring table.h |
778 |
TableList *lock_table; |
1
by brian
clean slate |
779 |
|
780 |
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local) |
|
781 |
{
|
|
782 |
int got_lock; |
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
783 |
if ((got_lock= lock_table_name(lock_table)) < 0) |
1910.2.6
by Brian Aker
Cleanup goto |
784 |
{
|
785 |
table_list->unlock_table_names(table_list); |
|
786 |
return true; // Fatal error |
|
787 |
}
|
|
788 |
||
1
by brian
clean slate |
789 |
if (got_lock) |
1910.2.6
by Brian Aker
Cleanup goto |
790 |
got_all_locks= false; // Someone is using table |
1
by brian
clean slate |
791 |
}
|
792 |
||
793 |
/* If some table was in use, wait until we got the lock */
|
|
1910.2.6
by Brian Aker
Cleanup goto |
794 |
if (not got_all_locks && wait_for_locked_table_names(table_list)) |
795 |
{
|
|
796 |
table_list->unlock_table_names(table_list); |
|
797 |
||
798 |
return true; |
|
799 |
}
|
|
800 |
||
1034.1.7
by Brian Aker
Remove dead bits to the end of functions. |
801 |
return false; |
1
by brian
clean slate |
802 |
}
|
803 |
||
804 |
||
805 |
/**
|
|
806 |
Unlock all tables in list with a name lock.
|
|
807 |
||
808 |
@param table_list Names of tables to lock.
|
|
809 |
||
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
810 |
@note
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
811 |
This function needs to be protected by table::Cache::singleton().mutex(). If we're
|
1
by brian
clean slate |
812 |
under LOCK TABLES, this function does not work as advertised. Namely,
|
813 |
it does not exclude other threads from using this table and does not
|
|
814 |
put an exclusive name lock on this table into the table cache.
|
|
815 |
||
816 |
@see lock_table_names
|
|
817 |
@see unlock_table_names
|
|
818 |
||
819 |
@retval TRUE An error occured.
|
|
820 |
@retval FALSE Name lock successfully acquired.
|
|
821 |
*/
|
|
822 |
||
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
823 |
bool Session::lock_table_names_exclusively(TableList *table_list) |
1
by brian
clean slate |
824 |
{
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
825 |
if (lock_table_names(table_list)) |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
826 |
return true; |
1
by brian
clean slate |
827 |
|
828 |
/*
|
|
829 |
Upgrade the table name locks from semi-exclusive to exclusive locks.
|
|
830 |
*/
|
|
327.2.4
by Brian Aker
Refactoring table.h |
831 |
for (TableList *table= table_list; table; table= table->next_global) |
1
by brian
clean slate |
832 |
{
|
833 |
if (table->table) |
|
834 |
table->table->open_placeholder= 1; |
|
835 |
}
|
|
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
836 |
return false; |
1
by brian
clean slate |
837 |
}
|
838 |
||
839 |
||
840 |
/**
|
|
841 |
Unlock all tables in list with a name lock.
|
|
842 |
||
843 |
@param
|
|
844 |
table_list Names of tables to unlock
|
|
845 |
@param
|
|
846 |
last_table Don't unlock any tables after this one.
|
|
847 |
(default 0, which will unlock all tables)
|
|
848 |
||
849 |
@note
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
850 |
One must have a lock on table::Cache::singleton().mutex() when calling this.
|
1
by brian
clean slate |
851 |
|
852 |
@note
|
|
853 |
This function will broadcast refresh signals to inform other threads
|
|
854 |
that the name locks are removed.
|
|
855 |
||
856 |
@retval
|
|
857 |
0 ok
|
|
858 |
@retval
|
|
859 |
1 Fatal error (end of memory ?)
|
|
860 |
*/
|
|
861 |
||
1910.2.4
by Brian Aker
Push some functions behind classes. |
862 |
void TableList::unlock_table_names(TableList *last_table) |
1
by brian
clean slate |
863 |
{
|
1910.2.4
by Brian Aker
Push some functions behind classes. |
864 |
for (TableList *table_iter= this; |
865 |
table_iter != last_table; |
|
866 |
table_iter= table_iter->next_local) |
|
867 |
{
|
|
868 |
table_iter->unlock_table_name(); |
|
869 |
}
|
|
870 |
||
1910.2.5
by Brian Aker
Merge in changes such that lock is now broken out into its own directory. |
871 |
locking::broadcast_refresh(); |
1
by brian
clean slate |
872 |
}
|
873 |
||
874 |
||
875 |
static void print_lock_error(int error, const char *table) |
|
876 |
{
|
|
877 |
int textno; |
|
878 |
||
879 |
switch (error) { |
|
880 |
case HA_ERR_LOCK_WAIT_TIMEOUT: |
|
881 |
textno=ER_LOCK_WAIT_TIMEOUT; |
|
882 |
break; |
|
883 |
case HA_ERR_READ_ONLY_TRANSACTION: |
|
884 |
textno=ER_READ_ONLY_TRANSACTION; |
|
885 |
break; |
|
886 |
case HA_ERR_LOCK_DEADLOCK: |
|
887 |
textno=ER_LOCK_DEADLOCK; |
|
888 |
break; |
|
889 |
case HA_ERR_WRONG_COMMAND: |
|
890 |
textno=ER_ILLEGAL_HA; |
|
891 |
break; |
|
892 |
default: |
|
893 |
textno=ER_CANT_LOCK; |
|
894 |
break; |
|
895 |
}
|
|
896 |
||
897 |
if ( textno == ER_ILLEGAL_HA ) |
|
898 |
my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table); |
|
899 |
else
|
|
900 |
my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error); |
|
901 |
}
|
|
902 |
||
903 |
||
904 |
/****************************************************************************
|
|
905 |
Handling of global read locks
|
|
906 |
||
907 |
Taking the global read lock is TWO steps (2nd step is optional; without
|
|
908 |
it, COMMIT of existing transactions will be allowed):
|
|
909 |
lock_global_read_lock() THEN make_global_read_lock_block_commit().
|
|
910 |
||
911 |
The global locks are handled through the global variables:
|
|
912 |
global_read_lock
|
|
913 |
count of threads which have the global read lock (i.e. have completed at
|
|
914 |
least the first step above)
|
|
915 |
global_read_lock_blocks_commit
|
|
916 |
count of threads which have the global read lock and block
|
|
917 |
commits (i.e. are in or have completed the second step above)
|
|
918 |
waiting_for_read_lock
|
|
919 |
count of threads which want to take a global read lock but cannot
|
|
920 |
protect_against_global_read_lock
|
|
921 |
count of threads which have set protection against global read lock.
|
|
922 |
||
923 |
access to them is protected with a mutex LOCK_global_read_lock
|
|
924 |
||
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
925 |
(XXX: one should never take table::Cache::singleton().mutex() if LOCK_global_read_lock is
|
1
by brian
clean slate |
926 |
taken, otherwise a deadlock may occur. Other mutexes could be a
|
927 |
problem too - grep the code for global_read_lock if you want to use
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
928 |
any other mutex here) Also one must not hold table::Cache::singleton().mutex() when calling
|
1
by brian
clean slate |
929 |
wait_if_global_read_lock(). When the thread with the global read lock
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
930 |
tries to close its tables, it needs to take table::Cache::singleton().mutex() in
|
1
by brian
clean slate |
931 |
close_thread_table().
|
932 |
||
933 |
How blocking of threads by global read lock is achieved: that's
|
|
934 |
advisory. Any piece of code which should be blocked by global read lock must
|
|
935 |
be designed like this:
|
|
936 |
- call to wait_if_global_read_lock(). When this returns 0, no global read
|
|
937 |
lock is owned; if argument abort_on_refresh was 0, none can be obtained.
|
|
938 |
- job
|
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
939 |
- if abort_on_refresh was 0, call to session->startWaitingGlobalReadLock() to
|
1
by brian
clean slate |
940 |
allow other threads to get the global read lock. I.e. removal of the
|
941 |
protection.
|
|
942 |
(Note: it's a bit like an implementation of rwlock).
|
|
943 |
||
944 |
[ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
|
|
945 |
no better descriptive way ]
|
|
946 |
||
947 |
Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
|
|
948 |
to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
|
|
949 |
log.
|
|
950 |
||
951 |
Why getting the global read lock is two steps and not one. Because FLUSH
|
|
952 |
TABLES WITH READ LOCK needs to insert one other step between the two:
|
|
953 |
flushing tables. So the order is
|
|
954 |
1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
|
|
955 |
all new updates)
|
|
956 |
2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
|
|
957 |
currently opened and being updated to close (so it's possible that there is
|
|
958 |
a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
|
|
959 |
READ LOCK is, too).
|
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
960 |
3) session::makeGlobalReadLockBlockCommit().
|
1
by brian
clean slate |
961 |
If we have merged 1) and 3) into 1), we would have had this deadlock:
|
962 |
imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
|
|
963 |
table t.
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
964 |
session1: SELECT * FROM t FOR UPDATE;
|
965 |
session2: UPDATE t SET a=1; # blocked by row-level locks of session1
|
|
966 |
session3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
|
|
967 |
table instance of session2
|
|
968 |
session1: COMMIT; # blocked by session3.
|
|
969 |
session1 blocks session2 which blocks session3 which blocks session1: deadlock.
|
|
1
by brian
clean slate |
970 |
|
971 |
Note that we need to support that one thread does
|
|
972 |
FLUSH TABLES WITH READ LOCK; and then COMMIT;
|
|
973 |
(that's what innobackup does, for some good reason).
|
|
974 |
So in this exceptional case the COMMIT should not be blocked by the FLUSH
|
|
975 |
TABLES WITH READ LOCK.
|
|
976 |
||
977 |
****************************************************************************/
|
|
978 |
||
482
by Brian Aker
Remove uint. |
979 |
volatile uint32_t global_read_lock=0; |
980 |
volatile uint32_t global_read_lock_blocks_commit=0; |
|
981 |
static volatile uint32_t protect_against_global_read_lock=0; |
|
982 |
static volatile uint32_t waiting_for_read_lock=0; |
|
1
by brian
clean slate |
983 |
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
984 |
bool Session::lockGlobalReadLock() |
1
by brian
clean slate |
985 |
{
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
986 |
if (isGlobalReadLock() == Session::NONE) |
1
by brian
clean slate |
987 |
{
|
988 |
const char *old_message; |
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
989 |
LOCK_global_read_lock.lock(); |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
990 |
old_message= enter_cond(COND_global_read_lock, LOCK_global_read_lock, |
991 |
"Waiting to get readlock"); |
|
1
by brian
clean slate |
992 |
|
993 |
waiting_for_read_lock++; |
|
1812.3.7
by Brian Aker
Typdef our lock type. |
994 |
boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t()); |
1910.2.8
by Brian Aker
Enapsulate Kill. |
995 |
while (protect_against_global_read_lock && not getKilled()) |
1798.3.8
by Brian Aker
Additional removal of native_handle |
996 |
COND_global_read_lock.wait(scopedLock); |
1
by brian
clean slate |
997 |
waiting_for_read_lock--; |
1798.3.8
by Brian Aker
Additional removal of native_handle |
998 |
scopedLock.release(); |
1910.2.8
by Brian Aker
Enapsulate Kill. |
999 |
if (getKilled()) |
1
by brian
clean slate |
1000 |
{
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1001 |
exit_cond(old_message); |
1046.1.7
by Brian Aker
Style cleanup. |
1002 |
return true; |
1
by brian
clean slate |
1003 |
}
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1004 |
setGlobalReadLock(Session::GOT_GLOBAL_READ_LOCK); |
1
by brian
clean slate |
1005 |
global_read_lock++; |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1006 |
exit_cond(old_message); // this unlocks LOCK_global_read_lock |
1
by brian
clean slate |
1007 |
}
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1008 |
|
1
by brian
clean slate |
1009 |
/*
|
1010 |
We DON'T set global_read_lock_blocks_commit now, it will be set after
|
|
1011 |
tables are flushed (as the present function serves for FLUSH TABLES WITH
|
|
1012 |
READ LOCK only). Doing things in this order is necessary to avoid
|
|
1013 |
deadlocks (we must allow COMMIT until all tables are closed; we should not
|
|
1014 |
forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
|
|
1015 |
UPDATE and one does FLUSH TABLES WITH READ LOCK).
|
|
1016 |
*/
|
|
1046.1.7
by Brian Aker
Style cleanup. |
1017 |
return false; |
1
by brian
clean slate |
1018 |
}
|
1019 |
||
1020 |
||
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1021 |
void Session::unlockGlobalReadLock(void) |
1
by brian
clean slate |
1022 |
{
|
482
by Brian Aker
Remove uint. |
1023 |
uint32_t tmp; |
1
by brian
clean slate |
1024 |
|
1948.2.12
by Brian Aker
Fix for bug 682037. |
1025 |
if (not isGlobalReadLock()) // If we have no personal stake in the global lock, just return |
1026 |
return; |
|
1027 |
||
1786.2.1
by Brian Aker
Current boost work (more conversion). |
1028 |
{
|
1812.3.7
by Brian Aker
Typdef our lock type. |
1029 |
boost_unique_lock_t scopedLock(LOCK_global_read_lock); |
1786.2.1
by Brian Aker
Current boost work (more conversion). |
1030 |
tmp= --global_read_lock; |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1031 |
if (isGlobalReadLock() == Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT) |
1786.2.1
by Brian Aker
Current boost work (more conversion). |
1032 |
--global_read_lock_blocks_commit; |
1033 |
}
|
|
1
by brian
clean slate |
1034 |
/* Send the signal outside the mutex to avoid a context switch */
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1035 |
if (not tmp) |
1
by brian
clean slate |
1036 |
{
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1037 |
COND_global_read_lock.notify_all(); |
1
by brian
clean slate |
1038 |
}
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1039 |
setGlobalReadLock(Session::NONE); |
1
by brian
clean slate |
1040 |
}
|
1041 |
||
1377.6.3
by pawel
changed function-like defines into functions in some files |
1042 |
static inline bool must_wait(bool is_not_commit) |
1043 |
{
|
|
1044 |
return (global_read_lock && |
|
1045 |
(is_not_commit || |
|
1046 |
global_read_lock_blocks_commit)); |
|
1047 |
}
|
|
1
by brian
clean slate |
1048 |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1049 |
bool Session::wait_if_global_read_lock(bool abort_on_refresh, bool is_not_commit) |
1
by brian
clean slate |
1050 |
{
|
1051 |
const char *old_message= NULL; |
|
1052 |
bool result= 0, need_exit_cond; |
|
1053 |
||
1054 |
/*
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
1055 |
Assert that we do not own table::Cache::singleton().mutex(). If we would own it, other
|
1
by brian
clean slate |
1056 |
threads could not close their tables. This would make a pretty
|
1057 |
deadlock.
|
|
1058 |
*/
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
1059 |
safe_mutex_assert_not_owner(table::Cache::singleton().mutex().native_handle()); |
1
by brian
clean slate |
1060 |
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1061 |
LOCK_global_read_lock.lock(); |
1377.6.3
by pawel
changed function-like defines into functions in some files |
1062 |
if ((need_exit_cond= must_wait(is_not_commit))) |
1
by brian
clean slate |
1063 |
{
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1064 |
if (isGlobalReadLock()) // This thread had the read locks |
1
by brian
clean slate |
1065 |
{
|
1066 |
if (is_not_commit) |
|
1067 |
my_message(ER_CANT_UPDATE_WITH_READLOCK, |
|
1068 |
ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0)); |
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1069 |
LOCK_global_read_lock.unlock(); |
1
by brian
clean slate |
1070 |
/*
|
1071 |
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
|
|
1072 |
This allowance is needed to not break existing versions of innobackup
|
|
1073 |
which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
|
|
1074 |
*/
|
|
1046.1.7
by Brian Aker
Style cleanup. |
1075 |
return is_not_commit; |
1
by brian
clean slate |
1076 |
}
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1077 |
old_message= enter_cond(COND_global_read_lock, LOCK_global_read_lock, |
1078 |
"Waiting for release of readlock"); |
|
1079 |
||
1910.2.8
by Brian Aker
Enapsulate Kill. |
1080 |
while (must_wait(is_not_commit) && not getKilled() && |
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1081 |
(!abort_on_refresh || version == refresh_version)) |
1
by brian
clean slate |
1082 |
{
|
1812.3.7
by Brian Aker
Typdef our lock type. |
1083 |
boost_unique_lock_t scoped(LOCK_global_read_lock, boost::adopt_lock_t()); |
1798.3.9
by Brian Aker
Adds in release/scope locks to remove native_handle |
1084 |
COND_global_read_lock.wait(scoped); |
1085 |
scoped.release(); |
|
1
by brian
clean slate |
1086 |
}
|
1910.2.8
by Brian Aker
Enapsulate Kill. |
1087 |
if (getKilled()) |
1
by brian
clean slate |
1088 |
result=1; |
1089 |
}
|
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1090 |
if (not abort_on_refresh && not result) |
1
by brian
clean slate |
1091 |
protect_against_global_read_lock++; |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1092 |
|
1
by brian
clean slate |
1093 |
/*
|
1094 |
The following is only true in case of a global read locks (which is rare)
|
|
1095 |
and if old_message is set
|
|
1096 |
*/
|
|
1097 |
if (unlikely(need_exit_cond)) |
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1098 |
{
|
1099 |
exit_cond(old_message); // this unlocks LOCK_global_read_lock |
|
1100 |
}
|
|
1
by brian
clean slate |
1101 |
else
|
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1102 |
{
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1103 |
LOCK_global_read_lock.unlock(); |
1910.2.3
by Brian Aker
Second pass on move code to global lock encapsulation. |
1104 |
}
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1105 |
|
1046.1.7
by Brian Aker
Style cleanup. |
1106 |
return result; |
1
by brian
clean slate |
1107 |
}
|
1108 |
||
1109 |
||
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1110 |
void Session::startWaitingGlobalReadLock() |
1
by brian
clean slate |
1111 |
{
|
1112 |
bool tmp; |
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1113 |
if (unlikely(isGlobalReadLock())) |
51.1.27
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1114 |
return; |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1115 |
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1116 |
LOCK_global_read_lock.lock(); |
1
by brian
clean slate |
1117 |
tmp= (!--protect_against_global_read_lock && |
1118 |
(waiting_for_read_lock || global_read_lock_blocks_commit)); |
|
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1119 |
LOCK_global_read_lock.unlock(); |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1120 |
|
1
by brian
clean slate |
1121 |
if (tmp) |
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1122 |
COND_global_read_lock.notify_all(); |
1
by brian
clean slate |
1123 |
}
|
1124 |
||
1125 |
||
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1126 |
bool Session::makeGlobalReadLockBlockCommit() |
1
by brian
clean slate |
1127 |
{
|
1128 |
bool error; |
|
1129 |
const char *old_message; |
|
1130 |
/*
|
|
1131 |
If we didn't succeed lock_global_read_lock(), or if we already suceeded
|
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1132 |
Session::makeGlobalReadLockBlockCommit(), do nothing.
|
1
by brian
clean slate |
1133 |
*/
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1134 |
if (isGlobalReadLock() != Session::GOT_GLOBAL_READ_LOCK) |
1046.1.7
by Brian Aker
Style cleanup. |
1135 |
return false; |
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1136 |
LOCK_global_read_lock.lock(); |
1
by brian
clean slate |
1137 |
/* increment this BEFORE waiting on cond (otherwise race cond) */
|
1138 |
global_read_lock_blocks_commit++; |
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1139 |
old_message= enter_cond(COND_global_read_lock, LOCK_global_read_lock, |
1140 |
"Waiting for all running commits to finish"); |
|
1910.2.8
by Brian Aker
Enapsulate Kill. |
1141 |
while (protect_against_global_read_lock && not getKilled()) |
1798.3.9
by Brian Aker
Adds in release/scope locks to remove native_handle |
1142 |
{
|
1812.3.7
by Brian Aker
Typdef our lock type. |
1143 |
boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t()); |
1798.3.9
by Brian Aker
Adds in release/scope locks to remove native_handle |
1144 |
COND_global_read_lock.wait(scopedLock); |
1145 |
scopedLock.release(); |
|
1146 |
}
|
|
1910.2.8
by Brian Aker
Enapsulate Kill. |
1147 |
if ((error= test(getKilled()))) |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1148 |
{
|
1
by brian
clean slate |
1149 |
global_read_lock_blocks_commit--; // undo what we did |
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1150 |
}
|
1
by brian
clean slate |
1151 |
else
|
1910.2.2
by Brian Aker
First pass through the global lock refactor merge. |
1152 |
{
|
1153 |
setGlobalReadLock(Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT); |
|
1154 |
}
|
|
1155 |
||
1156 |
exit_cond(old_message); // this unlocks LOCK_global_read_lock |
|
1157 |
||
1046.1.7
by Brian Aker
Style cleanup. |
1158 |
return error; |
1
by brian
clean slate |
1159 |
}
|
1160 |
||
1161 |
||
1162 |
/**
|
|
1163 |
Broadcast COND_refresh and COND_global_read_lock.
|
|
1164 |
||
1165 |
Due to a bug in a threading library it could happen that a signal
|
|
1166 |
did not reach its target. A condition for this was that the same
|
|
1167 |
condition variable was used with different mutexes in
|
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
1168 |
pthread_cond_wait(). Some time ago we changed table::Cache::singleton().mutex() to
|
1
by brian
clean slate |
1169 |
LOCK_global_read_lock in global read lock handling. So COND_refresh
|
1938.4.10
by Brian Aker
Convert LOCK_open to lock in mutex |
1170 |
was used with table::Cache::singleton().mutex() and LOCK_global_read_lock.
|
1
by brian
clean slate |
1171 |
|
1172 |
We did now also change from COND_refresh to COND_global_read_lock
|
|
1173 |
in global read lock handling. But now it is necessary to signal
|
|
1174 |
both conditions at the same time.
|
|
1175 |
||
1176 |
@note
|
|
1177 |
When signalling COND_global_read_lock within the global read lock
|
|
1178 |
handling, it is not necessary to also signal COND_refresh.
|
|
1179 |
*/
|
|
1180 |
||
1910.2.5
by Brian Aker
Merge in changes such that lock is now broken out into its own directory. |
1181 |
namespace locking { |
1182 |
||
1
by brian
clean slate |
1183 |
void broadcast_refresh(void) |
1184 |
{
|
|
1703.1.2
by Brian Aker
Upgrade to using the boost call. |
1185 |
COND_refresh.notify_all(); |
1689.2.2
by Brian Aker
Convert LOCK_global_read_lock. |
1186 |
COND_global_read_lock.notify_all(); |
1
by brian
clean slate |
1187 |
}
|
1188 |
||
1910.2.5
by Brian Aker
Merge in changes such that lock is now broken out into its own directory. |
1189 |
}
|
1190 |
||
1
by brian
clean slate |
1191 |
|
1192 |
/**
|
|
1193 |
@} (end of group Locking)
|
|
1194 |
*/
|
|
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
1195 |
|
1196 |
} /* namespace drizzled */ |