1
/* Copyright (C) 2000-2006 MySQL AB
2
Copyright (C) 2011 Brian Aker
3
Copyright (C) 2000-2006 MySQL AB
3
5
This program is free software; you can redistribute it and/or modify
4
6
it under the terms of the GNU General Public License as published by
20
Locking functions for mysql.
22
@note this is out of date, just for historical reference
24
Locking functions for drizzled.
22
26
Because of the new concurrent inserts, we must first get external locks
23
27
before getting internal locks. If we do it in the other order, the status
30
34
- For each SQL statement lockTables() is called for all involved
32
36
- lockTables() will call
33
table_handler->external_lock(session,locktype) for each table.
37
cursor->external_lock(session,locktype) for each table.
34
38
This is followed by a call to thr_multi_lock() for all tables.
36
40
- When statement is done, we call unlockTables().
72
76
Change to use malloc() ONLY when using LOCK TABLES command or when
73
77
we are forced to use mysql_lock_merge.
77
83
#include <drizzled/error.h>
78
#include <drizzled/my_hash.h>
79
84
#include <drizzled/thr_lock.h>
80
85
#include <drizzled/session.h>
86
#include <drizzled/session/times.h>
81
87
#include <drizzled/sql_base.h>
82
88
#include <drizzled/lock.h>
83
#include "drizzled/pthread_globals.h"
84
#include "drizzled/internal/my_sys.h"
85
#include "drizzled/pthread_globals.h"
89
#include <drizzled/pthread_globals.h>
90
#include <drizzled/internal/my_sys.h>
91
#include <drizzled/pthread_globals.h>
92
#include <drizzled/plugin/storage_engine.h>
93
#include <drizzled/util/test.h>
94
#include <drizzled/open_tables_state.h>
95
#include <drizzled/table/cache.h>
133
141
/* 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 };
142
static drizzled::error_t thr_lock_errno_to_mysql[]=
143
{ EE_OK, EE_ERROR_FIRST, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
155
163
lock request will set its lock type properly.
158
static void reset_lock_data_and_free(DrizzleLock **mysql_lock)
166
static void reset_lock_data_and_free(DrizzleLock*& lock)
160
DrizzleLock *sql_lock= *mysql_lock;
166
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
173
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags)
168
175
DrizzleLock *sql_lock;
169
176
Table *write_lock_used;
170
177
vector<plugin::StorageEngine *> involved_engines;
177
if (! (sql_lock= get_lock_data(tables, count, true,
181
if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
181
if (global_read_lock && write_lock_used &&
182
! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK))
184
if (global_read_lock && write_lock_used and (not (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK)))
185
187
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
188
190
if (wait_if_global_read_lock(1, 1))
190
192
/* Clear the lock type of all lock data to avoid reusage. */
191
reset_lock_data_and_free(&sql_lock);
193
reset_lock_data_and_free(sql_lock);
194
if (version != refresh_version)
197
if (open_tables.version != g_refresh_version)
196
199
/* Clear the lock type of all lock data to avoid reusage. */
197
reset_lock_data_and_free(&sql_lock);
200
reset_lock_data_and_free(sql_lock);
209
212
size_t num_tables= sql_lock->sizeTable();
210
213
plugin::StorageEngine *engine;
211
set<size_t> involved_slots;
214
std::set<size_t> involved_slots;
212
216
for (size_t x= 1; x <= num_tables; x++, tables++)
214
218
engine= (*tables)->cursor->getEngine();
215
220
if (involved_slots.count(engine->getId()) > 0)
216
221
continue; /* already added to involved engines */
217
223
involved_engines.push_back(engine);
218
224
involved_slots.insert(engine->getId());
233
239
if (sql_lock->sizeTable() && lock_external(sql_lock->getTable(), sql_lock->sizeTable()))
235
241
/* Clear the lock type of all lock data to avoid reusage. */
236
reset_lock_data_and_free(&sql_lock);
242
reset_lock_data_and_free(sql_lock);
239
245
set_proc_info("Table lock");
241
247
memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
242
248
sql_lock->getLocks(),
243
249
sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
244
251
/* Lock on the copied half of the lock data array. */
252
drizzled::error_t rc;
245
253
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this,
246
254
sql_lock->getLocks() +
247
255
sql_lock->sizeLock(),
248
256
sql_lock->sizeLock(),
250
if (rc > 1) /* a timeout or a deadlock */
258
if (rc) /* a timeout or a deadlock */
252
260
if (sql_lock->sizeTable())
253
261
unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
254
reset_lock_data_and_free(&sql_lock);
262
reset_lock_data_and_free(sql_lock);
255
263
my_error(rc, MYF(0));
258
else if (rc == 1) /* aborted */
260
some_tables_deleted= true; // Try again
261
sql_lock->setLock(0); // Locks are already freed
262
// Fall through: unlock, reset lock data, free and retry
264
else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
267
Thread was killed or lock aborted. Let upper level close all
268
used tables and retry or give error.
272
else if (not open_tables)
274
// Only using temporary tables, no need to unlock
275
some_tables_deleted= false;
280
/* going to retry, unlock all tables */
281
if (sql_lock->sizeLock())
282
sql_lock->unlock(sql_lock->sizeLock());
284
if (sql_lock->sizeTable())
285
unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
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.
292
reset_lock_data_and_free(&sql_lock);
295
* Notify all involved engines that the
296
* SQL statement has ended
298
for_each(involved_engines.begin(),
299
involved_engines.end(),
300
bind2nd(mem_fun(&plugin::StorageEngine::endStatement), this));
302
if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
308
if (wait_for_tables(this))
310
break; // Couldn't open tables
314
267
set_proc_info(0);
334
289
assert((*tables)->reginfo.lock_type >= TL_READ);
335
290
lock_type=F_WRLCK; /* Lock exclusive */
336
291
if ((*tables)->db_stat & HA_READ_ONLY ||
337
((*tables)->reginfo.lock_type >= TL_READ &&
338
(*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
292
((*tables)->reginfo.lock_type >= TL_READ &&
293
(*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
339
294
lock_type=F_RDLCK;
341
296
if ((error=(*tables)->cursor->ha_external_lock(this,lock_type)))
501
456
bool Session::abortLockForThread(Table *table)
504
Table *write_lock_used;
505
458
bool result= false;
507
if ((locked= get_lock_data(&table, 1, false,
459
Table* write_lock_used;
460
if (DrizzleLock* locked= get_lock_data(&table, 1, false, &write_lock_used))
510
462
for (uint32_t i= 0; i < locked->sizeLock(); i++)
603
555
my_error(ER_OPEN_AS_READONLY, MYF(0), table->getAlias());
604
556
/* Clear the lock type of the lock data that are stored already. */
605
557
sql_lock->setLock(locks - sql_lock->getLocks());
606
reset_lock_data_and_free(&sql_lock);
558
reset_lock_data_and_free(sql_lock);
610
562
locks_start= locks;
611
locks= table->cursor->store_lock(this, locks, should_lock == false ? TL_IGNORE : lock_type);
563
locks= table->cursor->store_lock(this, locks, should_lock ? lock_type : TL_IGNORE);
614
566
table->lock_position= (uint32_t) (to - table_buf);
667
619
int Session::lock_table_name(TableList *table_list)
669
TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
670
const TableIdentifier::Key &key(identifier.getKey());
621
identifier::Table identifier(table_list->getSchemaName(), table_list->getTableName());
673
623
/* Only insert the table if we haven't insert it already */
674
table::CacheRange ppp;
676
ppp= table::getCache().equal_range(key);
678
for (table::CacheMap::const_iterator iter= ppp.first;
679
iter != ppp.second; ++iter)
624
table::CacheRange ppp= table::getCache().equal_range(identifier.getKey());
625
for (table::CacheMap::const_iterator iter= ppp.first; iter != ppp.second; ++iter)
681
Table *table= (*iter).second;
627
Table *table= iter->second;
682
628
if (table->reginfo.lock_type < TL_WRITE)
687
630
if (table->in_use == this)
689
632
table->getMutableShare()->resetVersion(); // Ensure no one can use this
696
table::Placeholder *table= NULL;
697
if (!(table= table_cache_insert_placeholder(identifier)))
702
table_list->table= reinterpret_cast<Table *>(table);
639
table::Placeholder *table= &table_cache_insert_placeholder(identifier);
640
table_list->table= reinterpret_cast<Table*>(table);
704
642
/* Return 1 if table is in use */
705
return(test(table::Cache::singleton().removeTable(this, identifier, RTFC_NO_FLAG)));
643
return (test(table::Cache::removeTable(*this, identifier, RTFC_NO_FLAG)));
719
657
static bool locked_named_table(TableList *table_list)
721
for (; table_list ; table_list=table_list->next_local)
659
for (; table_list; table_list=table_list->next_local)
723
661
Table *table= table_list->table;
726
664
Table *save_next= table->getNext();
728
665
table->setNext(NULL);
729
result= table::Cache::singleton().areTablesUsed(table_list->table, 0);
666
bool result= table::Cache::areTablesUsed(table_list->table, 0);
730
667
table->setNext(save_next);
741
678
bool result= false;
744
assert(ownership of table::Cache::singleton().mutex());
681
assert(ownership of table::Cache::mutex());
747
684
while (locked_named_table(table_list))
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 */
691
wait_for_condition(table::Cache::mutex(), COND_refresh);
692
table::Cache::mutex().lock(); /* Wait for a table to unlock and then lock it */
775
712
bool Session::lock_table_names(TableList *table_list)
777
714
bool got_all_locks= true;
778
TableList *lock_table;
780
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
715
for (TableList* lock_table= table_list; lock_table; lock_table= lock_table->next_local)
783
if ((got_lock= lock_table_name(lock_table)) < 0)
717
int got_lock= lock_table_name(lock_table);
785
720
table_list->unlock_table_names(table_list);
786
721
return true; // Fatal error
790
724
got_all_locks= false; // Someone is using table
808
740
@param table_list Names of tables to lock.
811
This function needs to be protected by table::Cache::singleton().mutex(). If we're
743
This function needs to be protected by table::Cache::mutex(). If we're
812
744
under LOCK TABLES, this function does not work as advertised. Namely,
813
745
it does not exclude other threads from using this table and does not
814
746
put an exclusive name lock on this table into the table cache.
862
794
void TableList::unlock_table_names(TableList *last_table)
864
for (TableList *table_iter= this;
865
table_iter != last_table;
866
table_iter= table_iter->next_local)
796
for (TableList *table_iter= this; table_iter != last_table; table_iter= table_iter->next_local)
868
798
table_iter->unlock_table_name();
871
800
locking::broadcast_refresh();
875
804
static void print_lock_error(int error, const char *table)
806
drizzled::error_t textno;
880
809
case HA_ERR_LOCK_WAIT_TIMEOUT:
881
810
textno=ER_LOCK_WAIT_TIMEOUT;
923
852
access to them is protected with a mutex LOCK_global_read_lock
925
(XXX: one should never take table::Cache::singleton().mutex() if LOCK_global_read_lock is
854
(XXX: one should never take table::Cache::mutex() if LOCK_global_read_lock is
926
855
taken, otherwise a deadlock may occur. Other mutexes could be a
927
856
problem too - grep the code for global_read_lock if you want to use
928
any other mutex here) Also one must not hold table::Cache::singleton().mutex() when calling
857
any other mutex here) Also one must not hold table::Cache::mutex() when calling
929
858
wait_if_global_read_lock(). When the thread with the global read lock
930
tries to close its tables, it needs to take table::Cache::singleton().mutex() in
859
tries to close its tables, it needs to take table::Cache::mutex() in
931
860
close_thread_table().
933
862
How blocking of threads by global read lock is achieved: that's
991
920
"Waiting to get readlock");
993
922
waiting_for_read_lock++;
994
boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
923
boost::mutex::scoped_lock scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
995
924
while (protect_against_global_read_lock && not getKilled())
996
925
COND_global_read_lock.wait(scopedLock);
997
926
waiting_for_read_lock--;
1052
981
bool result= 0, need_exit_cond;
1055
Assert that we do not own table::Cache::singleton().mutex(). If we would own it, other
984
Assert that we do not own table::Cache::mutex(). If we would own it, other
1056
985
threads could not close their tables. This would make a pretty
1059
safe_mutex_assert_not_owner(table::Cache::singleton().mutex().native_handle());
988
safe_mutex_assert_not_owner(table::Cache::mutex().native_handle());
1061
990
LOCK_global_read_lock.lock();
1062
991
if ((need_exit_cond= must_wait(is_not_commit)))
1078
1007
"Waiting for release of readlock");
1080
1009
while (must_wait(is_not_commit) && not getKilled() &&
1081
(!abort_on_refresh || version == refresh_version))
1010
(!abort_on_refresh || open_tables.version == g_refresh_version))
1083
boost_unique_lock_t scoped(LOCK_global_read_lock, boost::adopt_lock_t());
1012
boost::mutex::scoped_lock scoped(LOCK_global_read_lock, boost::adopt_lock_t());
1084
1013
COND_global_read_lock.wait(scoped);
1085
1014
scoped.release();
1087
1016
if (getKilled())
1090
1020
if (not abort_on_refresh && not result)
1091
1021
protect_against_global_read_lock++;
1110
1040
void Session::startWaitingGlobalReadLock()
1113
1042
if (unlikely(isGlobalReadLock()))
1116
1045
LOCK_global_read_lock.lock();
1117
tmp= (!--protect_against_global_read_lock &&
1118
(waiting_for_read_lock || global_read_lock_blocks_commit));
1046
bool tmp= (!--protect_against_global_read_lock && (waiting_for_read_lock || global_read_lock_blocks_commit));
1119
1047
LOCK_global_read_lock.unlock();
1140
1068
"Waiting for all running commits to finish");
1141
1069
while (protect_against_global_read_lock && not getKilled())
1143
boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
1071
boost::mutex::scoped_lock scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
1144
1072
COND_global_read_lock.wait(scopedLock);
1145
1073
scopedLock.release();
1165
1093
Due to a bug in a threading library it could happen that a signal
1166
1094
did not reach its target. A condition for this was that the same
1167
1095
condition variable was used with different mutexes in
1168
pthread_cond_wait(). Some time ago we changed table::Cache::singleton().mutex() to
1096
pthread_cond_wait(). Some time ago we changed table::Cache::mutex() to
1169
1097
LOCK_global_read_lock in global read lock handling. So COND_refresh
1170
was used with table::Cache::singleton().mutex() and LOCK_global_read_lock.
1098
was used with table::Cache::mutex() and LOCK_global_read_lock.
1172
1100
We did now also change from COND_refresh to COND_global_read_lock
1173
1101
in global read lock handling. But now it is necessary to signal
1178
1106
handling, it is not necessary to also signal COND_refresh.
1183
void broadcast_refresh(void)
1109
void locking::broadcast_refresh()
1185
1111
COND_refresh.notify_all();
1186
1112
COND_global_read_lock.notify_all();
1193
@} (end of group Locking)
1196
1115
} /* namespace drizzled */