43
43
- The above is true both for normal and temporary tables.
45
45
- Temporary non transactional tables are never passed to thr_multi_lock()
46
and we never call external_lock(thd, F_UNLOCK) on these.
46
and we never call external_lock(session, F_UNLOCK) on these.
48
48
When using LOCK TABLES:
50
- LOCK TABLE will call mysql_lock_tables() for all tables.
50
- LOCK Table will call mysql_lock_tables() for all tables.
51
51
mysql_lock_tables() will call
52
table_handler->external_lock(thd,locktype) for each table.
52
table_handler->external_lock(session,locktype) for each table.
53
53
This is followed by a call to thr_multi_lock() for all tables.
55
- For each statement, we will call table_handler->start_stmt(THD)
55
- For each statement, we will call table_handler->start_stmt(Session)
56
56
to inform the table handler that we are using the table.
58
58
The tables used can only be tables used in LOCK TABLES or a
61
- When statement is done, we will call ha_commit_stmt(thd);
61
- When statement is done, we will call ha_commit_stmt(session);
63
63
- When calling UNLOCK TABLES we call mysql_unlock_tables() for all
64
64
tables used in LOCK TABLES
66
If table_handler->external_lock(thd, locktype) fails, we call
67
table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
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,
68
68
excluding one that caused failure. That means handler must cleanup itself
69
69
in case external_lock() fails.
72
Change to use my_malloc() ONLY when using LOCK TABLES command or when
72
Change to use malloc() ONLY when using LOCK TABLES command or when
73
73
we are forced to use mysql_lock_merge.
75
#include <drizzled/server_includes.h>
76
#include <drizzled/drizzled_error_messages.h>
77
#include <drizzled/error.h>
78
#include <drizzled/my_hash.h>
79
#include <drizzled/thr_lock.h>
80
#include <drizzled/session.h>
81
#include <drizzled/sql_base.h>
82
#include <drizzled/lock.h>
83
#include "drizzled/pthread_globals.h"
84
#include "drizzled/internal/my_sys.h"
79
90
@defgroup Locking Locking
199
if (!(flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
205
Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
206
We do not wait for READ_ONLY=0, and fail.
208
reset_lock_data_and_free(&sql_lock);
209
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
213
thd_proc_info(thd, "System lock");
214
if (sql_lock->table_count && lock_external(thd, sql_lock->table,
206
session->set_proc_info("System lock");
207
if (sql_lock->table_count && lock_external(session, sql_lock->table,
215
208
sql_lock->table_count))
217
210
/* Clear the lock type of all lock data to avoid reusage. */
218
211
reset_lock_data_and_free(&sql_lock);
221
thd_proc_info(thd, "Table lock");
214
session->set_proc_info("Table lock");
222
215
/* Copy the lock data array. thr_multi_lock() reorders its contens. */
223
216
memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
224
217
sql_lock->lock_count * sizeof(*sql_lock->locks));
428
421
unlock_external() we call handler::external_lock(F_UNLCK) only
429
422
if table->current_lock is not F_UNLCK.
431
@param thd thread context
424
@param session thread context
432
425
@param locked list of locked tables
433
426
@param table the table to unlock
434
427
@param always_unlock specify explicitly if the legacy side
435
428
effect is desired.
438
void mysql_lock_remove(THD *thd, DRIZZLE_LOCK *locked,TABLE *table,
441
if (always_unlock == true)
442
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
446
for (i=0; i < locked->table_count; i++)
448
if (locked->table[i] == table)
450
uint j, removed_locks, old_tables;
454
assert(table->lock_position == i);
456
/* Unlock if not yet unlocked */
457
if (always_unlock == false)
458
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
460
/* Decrement table_count in advance, making below expressions easier */
461
old_tables= --locked->table_count;
463
/* The table has 'removed_locks' lock data elements in locked->locks */
464
removed_locks= table->lock_count;
466
/* Move down all table pointers above 'i'. */
467
memcpy((locked->table+i), (locked->table+i+1),
468
(old_tables - i) * sizeof(TABLE*));
470
lock_data_end= table->lock_data_start + table->lock_count;
471
/* Move down all lock data pointers above 'table->lock_data_end-1' */
472
memcpy((locked->locks + table->lock_data_start),
473
(locked->locks + lock_data_end),
474
(locked->lock_count - lock_data_end) *
475
sizeof(THR_LOCK_DATA*));
478
Fix moved table elements.
479
lock_position is the index in the 'locked->table' array,
480
it must be fixed by one.
481
table->lock_data_start is pointer to the lock data for this table
482
in the 'locked->locks' array, they must be fixed by 'removed_locks',
483
the lock data count of the removed table.
485
for (j= i ; j < old_tables; j++)
487
tbl= locked->table[j];
488
tbl->lock_position--;
489
assert(tbl->lock_position == j);
490
tbl->lock_data_start-= removed_locks;
493
/* Finally adjust lock_count. */
494
locked->lock_count-= removed_locks;
501
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
503
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
504
thr_lock_type new_lock_type)
506
DRIZZLE_LOCK *locked;
507
TABLE *write_lock_used;
508
if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
511
for (uint i=0; i < locked->lock_count; i++)
512
thr_downgrade_write_lock(locked->locks[i], new_lock_type);
513
my_free((uchar*) locked,MYF(0));
431
void mysql_lock_remove(Session *session, Table *table)
433
mysql_unlock_some_tables(session, &table, /* table count */ 1);
518
437
/** Abort all other threads waiting to get lock in table. */
520
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
439
void mysql_lock_abort(Session *session, Table *table)
522
441
DRIZZLE_LOCK *locked;
523
TABLE *write_lock_used;
442
Table *write_lock_used;
525
if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
444
if ((locked= get_lock_data(session, &table, 1, false,
526
445
&write_lock_used)))
528
for (uint i=0; i < locked->lock_count; i++)
529
thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
530
my_free((uchar*) locked,MYF(0));
447
for (uint32_t x= 0; x < locked->lock_count; x++)
448
thr_abort_locks(locked->locks[x]->lock);
449
free((unsigned char*) locked);
537
455
Abort one thread / table combination.
539
@param thd Thread handler
457
@param session Thread handler
540
458
@param table Table that should be removed from lock queue
545
463
1 Table was locked by at least one other thread
548
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
466
bool mysql_lock_abort_for_thread(Session *session, Table *table)
550
468
DRIZZLE_LOCK *locked;
551
TABLE *write_lock_used;
469
Table *write_lock_used;
552
470
bool result= false;
554
if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
472
if ((locked= get_lock_data(session, &table, 1, false,
555
473
&write_lock_used)))
557
for (uint i=0; i < locked->lock_count; i++)
475
for (uint32_t i=0; i < locked->lock_count; i++)
559
477
if (thr_abort_locks_for_thread(locked->locks[i]->lock,
560
478
table->in_use->thread_id))
563
my_free((uchar*) locked,MYF(0));
569
DRIZZLE_LOCK *mysql_lock_merge(DRIZZLE_LOCK *a,DRIZZLE_LOCK *b)
571
DRIZZLE_LOCK *sql_lock;
572
TABLE **table, **end_table;
574
if (!(sql_lock= (DRIZZLE_LOCK*)
575
my_malloc(sizeof(*sql_lock)+
576
sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
577
sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
578
return(0); // Fatal error
579
sql_lock->lock_count=a->lock_count+b->lock_count;
580
sql_lock->table_count=a->table_count+b->table_count;
581
sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
582
sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count);
583
memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
584
memcpy(sql_lock->locks+a->lock_count,b->locks,
585
b->lock_count*sizeof(*b->locks));
586
memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
587
memcpy(sql_lock->table+a->table_count,b->table,
588
b->table_count*sizeof(*b->table));
591
Now adjust lock_position and lock_data_start for all objects that was
592
moved in 'b' (as there is now all objects in 'a' before these).
594
for (table= sql_lock->table + a->table_count,
595
end_table= table + b->table_count;
599
(*table)->lock_position+= a->table_count;
600
(*table)->lock_data_start+= a->lock_count;
603
/* Delete old, not needed locks */
604
my_free((uchar*) a,MYF(0));
605
my_free((uchar*) b,MYF(0));
611
Find duplicate lock in tables.
613
Temporary tables are ignored here like they are ignored in
614
get_lock_data(). If we allow two opens on temporary tables later,
615
both functions should be checked.
617
@param thd The current thread.
618
@param needle The table to check for duplicate lock.
619
@param haystack The list of tables to search for the dup lock.
622
This is mainly meant for MERGE tables in INSERT ... SELECT
623
situations. The 'real', underlying tables can be found only after
624
the MERGE tables are opened. This function assumes that the tables are
628
NULL No duplicate lock found.
630
!NULL First table from 'haystack' that matches a lock on 'needle'.
633
TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
634
TABLE_LIST *haystack)
636
DRIZZLE_LOCK *mylock;
640
THR_LOCK_DATA **lock_locks;
641
THR_LOCK_DATA **table_lock_data;
642
THR_LOCK_DATA **end_data;
643
THR_LOCK_DATA **lock_data2;
644
THR_LOCK_DATA **end_data2;
647
Table may not be defined for derived or view tables.
648
Table may not be part of a lock for delayed operations.
650
if (! (table= needle->table) || ! table->lock_count)
653
/* A temporary table does not have locks. */
654
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
657
/* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
658
if (! (mylock= thd->lock ? thd->lock : thd->locked_tables))
661
/* If we have less than two tables, we cannot have duplicates. */
662
if (mylock->table_count < 2)
665
lock_locks= mylock->locks;
666
lock_tables= mylock->table;
668
/* Prepare table related variables that don't change in loop. */
669
assert((table->lock_position < mylock->table_count) &&
670
(table == lock_tables[table->lock_position]));
671
table_lock_data= lock_locks + table->lock_data_start;
672
end_data= table_lock_data + table->lock_count;
674
for (; haystack; haystack= haystack->next_global)
676
if (haystack->placeholder())
678
table2= haystack->table;
679
if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
682
/* All tables in list must be in lock. */
683
assert((table2->lock_position < mylock->table_count) &&
684
(table2 == lock_tables[table2->lock_position]));
686
for (lock_data2= lock_locks + table2->lock_data_start,
687
end_data2= lock_data2 + table2->lock_count;
688
lock_data2 < end_data2;
691
THR_LOCK_DATA **lock_data;
692
THR_LOCK *lock2= (*lock_data2)->lock;
694
for (lock_data= table_lock_data;
695
lock_data < end_data;
698
if ((*lock_data)->lock == lock2)
481
free((unsigned char*) locked);
711
487
/** Unlock a set of external. */
713
static int unlock_external(THD *thd, TABLE **table,uint count)
489
static int unlock_external(Session *session, Table **table,uint32_t count)
715
491
int error,error_code;
720
496
if ((*table)->current_lock != F_UNLCK)
722
498
(*table)->current_lock = F_UNLCK;
723
if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK)))
499
if ((error=(*table)->cursor->ha_external_lock(session, F_UNLCK)))
725
501
error_code=error;
726
print_lock_error(error_code, (*table)->file->table_type());
502
print_lock_error(error_code, (*table)->cursor->engine->getName().c_str());
730
506
} while (--count);
736
512
Get lock structures from table structs and initialize locks.
738
@param thd Thread handler
514
@param session Thread handler
739
515
@param table_ptr Pointer to tables that should be locks
741
- GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock
742
- GET_LOCK_STORE_LOCKS : Store lock info in TABLE
516
@param should_lock One of:
517
- false : If we should send TL_IGNORE to store lock
518
- true : Store lock info in Table
743
519
@param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE
746
static DRIZZLE_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
747
uint flags, TABLE **write_lock_used)
522
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
523
bool should_lock, Table **write_lock_used)
749
uint i,tables,lock_count;
525
uint32_t i,tables,lock_count;
750
526
DRIZZLE_LOCK *sql_lock;
751
527
THR_LOCK_DATA **locks, **locks_buf, **locks_start;
752
TABLE **to, **table_buf;
754
assert((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
528
Table **to, **table_buf;
756
530
*write_lock_used=0;
757
for (i=tables=lock_count=0 ; i < count ; i++)
531
for (i= tables= lock_count= 0 ; i < count ; i++)
759
TABLE *t= table_ptr[i];
533
Table *t= table_ptr[i];
761
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
535
if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)))
763
tables+= t->file->lock_count();
829
604
And in the FLUSH case, the memory is released quickly anyway.
831
606
sql_lock->lock_count= locks - locks_buf;
836
/*****************************************************************************
837
Lock table based on the name.
838
This is used when we need total access to a closed, not open table
839
*****************************************************************************/
842
Lock and wait for the named lock.
844
@param thd Thread handler
845
@param table_list Lock first table in this list
849
Works together with global read lock.
857
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
862
if (wait_if_global_read_lock(thd, 0, 1))
864
VOID(pthread_mutex_lock(&LOCK_open));
865
if ((lock_retcode = lock_table_name(thd, table_list, true)) < 0)
867
if (lock_retcode && wait_for_locked_table_names(thd, table_list))
869
unlock_table_name(thd, table_list);
875
pthread_mutex_unlock(&LOCK_open);
876
start_waiting_global_read_lock(thd);
882
613
Put a not open table with an old refresh version in the table cache.
884
@param thd Thread handler
615
@param session Thread handler
885
616
@param table_list Lock first table in this list
886
617
@param check_in_use Do we need to check if table already in use by us
905
636
> 0 table locked, but someone is using it
908
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
639
int lock_table_name(Session *session, TableList *table_list, bool check_in_use)
911
642
char key[MAX_DBKEY_LENGTH];
912
643
char *db= table_list->db;
914
645
bool found_locked_table= false;
915
646
HASH_SEARCH_STATE state;
917
key_length= create_table_def_key(thd, key, table_list, 0);
648
key_length= table_list->create_table_def_key(key);
919
650
if (check_in_use)
921
652
/* Only insert the table if we haven't insert it already */
922
for (table=(TABLE*) hash_first(&open_cache, (uchar*)key,
653
for (table=(Table*) hash_first(&open_cache, (unsigned char*)key,
923
654
key_length, &state);
925
table = (TABLE*) hash_next(&open_cache,(uchar*) key,
656
table = (Table*) hash_next(&open_cache,(unsigned char*) key,
926
657
key_length, &state))
928
659
if (table->reginfo.lock_type < TL_WRITE)
930
if (table->in_use == thd)
661
if (table->in_use == session)
931
662
found_locked_table= true;
935
if (table->in_use == thd)
666
if (table->in_use == session)
937
668
table->s->version= 0; // Ensure no one can use this
938
669
table->locked_by_name= 1;
944
if (thd->locked_tables && thd->locked_tables->table_count &&
945
! find_temporary_table(thd, table_list->db, table_list->table_name))
947
if (found_locked_table)
948
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias);
950
my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_list->alias);
955
if (!(table= table_cache_insert_placeholder(thd, key, key_length)))
675
if (!(table= session->table_cache_insert_placeholder(key, key_length)))
958
678
table_list->table=table;
960
680
/* Return 1 if table is in use */
961
return(test(remove_table_from_cache(thd, db, table_list->table_name,
681
return(test(remove_table_from_cache(session, db, table_list->table_name,
962
682
check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
966
void unlock_table_name(THD *thd __attribute__((unused)),
967
TABLE_LIST *table_list)
686
void unlock_table_name(TableList *table_list)
969
688
if (table_list->table)
971
hash_delete(&open_cache, (uchar*) table_list->table);
690
hash_delete(&open_cache, (unsigned char*) table_list->table);
972
691
broadcast_refresh();
977
static bool locked_named_table(THD *thd __attribute__((unused)),
978
TABLE_LIST *table_list)
696
static bool locked_named_table(TableList *table_list)
980
698
for (; table_list ; table_list=table_list->next_local)
982
TABLE *table= table_list->table;
700
Table *table= table_list->table;
985
TABLE *save_next= table->next;
703
Table *save_next= table->next;
988
706
result= table_is_used(table_list->table, 0);
1022
740
- One must have a lock on LOCK_open when calling this
1024
@param thd Thread handle
1025
742
@param table_list Names of tables to lock
1028
If you are just locking one table, you should use
1029
lock_and_wait_for_table_name().
1034
747
1 Fatal error (end of memory ?)
1037
bool lock_table_names(THD *thd, TABLE_LIST *table_list)
750
bool lock_table_names(Session *session, TableList *table_list)
1039
752
bool got_all_locks=1;
1040
TABLE_LIST *lock_table;
753
TableList *lock_table;
1042
755
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
1045
if ((got_lock=lock_table_name(thd,lock_table, true)) < 0)
758
if ((got_lock= lock_table_name(session,lock_table, true)) < 0)
1046
759
goto end; // Fatal error
1048
761
got_all_locks=0; // Someone is using table
1051
764
/* If some table was in use, wait until we got the lock */
1052
if (!got_all_locks && wait_for_locked_table_names(thd, table_list))
765
if (!got_all_locks && wait_for_locked_table_names(session, table_list))
1057
unlock_table_names(thd, table_list, lock_table);
770
unlock_table_names(table_list, lock_table);
1063
777
Unlock all tables in list with a name lock.
1065
@param thd Thread handle.
779
@param session Thread handle.
1066
780
@param table_list Names of tables to lock.
1069
This function needs to be protected by LOCK_open. If we're
783
This function needs to be protected by LOCK_open. If we're
1070
784
under LOCK TABLES, this function does not work as advertised. Namely,
1071
785
it does not exclude other threads from using this table and does not
1072
786
put an exclusive name lock on this table into the table cache.
1099
Test is 'table' is protected by an exclusive name lock.
1101
@param[in] thd The current thread handler
1102
@param[in] table_list Table container containing the single table to be
1105
@note Needs to be protected by LOCK_open mutex.
1107
@return Error status code
1108
@retval TRUE Table is protected
1109
@retval FALSE Table is not protected
1113
is_table_name_exclusively_locked_by_this_thread(THD *thd,
1114
TABLE_LIST *table_list)
1116
char key[MAX_DBKEY_LENGTH];
1119
key_length= create_table_def_key(thd, key, table_list, 0);
1121
return is_table_name_exclusively_locked_by_this_thread(thd, (uchar *)key,
1127
Test is 'table key' is protected by an exclusive name lock.
1129
@param[in] thd The current thread handler.
1131
@param[in] key_length
1133
@note Needs to be protected by LOCK_open mutex
1135
@retval TRUE Table is protected
1136
@retval FALSE Table is not protected
1140
is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
1143
HASH_SEARCH_STATE state;
1146
for (table= (TABLE*) hash_first(&open_cache, key,
1147
key_length, &state);
1149
table= (TABLE*) hash_next(&open_cache, key,
1150
key_length, &state))
1152
if (table->in_use == thd &&
1153
table->open_placeholder == 1 &&
1154
table->s->version == 0)
1162
813
Unlock all tables in list with a name lock.
1167
816
table_list Names of tables to unlock
1169
818
last_table Don't unlock any tables after this one.
1301
946
****************************************************************************/
1303
volatile uint global_read_lock=0;
1304
volatile uint global_read_lock_blocks_commit=0;
1305
static volatile uint protect_against_global_read_lock=0;
1306
static volatile uint waiting_for_read_lock=0;
948
volatile uint32_t global_read_lock=0;
949
volatile uint32_t global_read_lock_blocks_commit=0;
950
static volatile uint32_t protect_against_global_read_lock=0;
951
static volatile uint32_t waiting_for_read_lock=0;
1308
953
#define GOT_GLOBAL_READ_LOCK 1
1309
954
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
1311
bool lock_global_read_lock(THD *thd)
956
bool lock_global_read_lock(Session *session)
1313
if (!thd->global_read_lock)
958
if (!session->global_read_lock)
1315
960
const char *old_message;
1316
961
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1317
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
962
old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1318
963
"Waiting to get readlock");
1320
965
waiting_for_read_lock++;
1321
while (protect_against_global_read_lock && !thd->killed)
966
while (protect_against_global_read_lock && !session->killed)
1322
967
pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1323
968
waiting_for_read_lock--;
1326
thd->exit_cond(old_message);
971
session->exit_cond(old_message);
1329
thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
974
session->global_read_lock= GOT_GLOBAL_READ_LOCK;
1330
975
global_read_lock++;
1331
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
976
session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1334
979
We DON'T set global_read_lock_blocks_commit now, it will be set after
1441
1084
If we didn't succeed lock_global_read_lock(), or if we already suceeded
1442
1085
make_global_read_lock_block_commit(), do nothing.
1444
if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
1087
if (session->global_read_lock != GOT_GLOBAL_READ_LOCK)
1446
1089
pthread_mutex_lock(&LOCK_global_read_lock);
1447
1090
/* increment this BEFORE waiting on cond (otherwise race cond) */
1448
1091
global_read_lock_blocks_commit++;
1449
/* For testing we set up some blocking, to see if we can be killed */
1450
protect_against_global_read_lock++;
1451
old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1092
old_message= session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1452
1093
"Waiting for all running commits to finish");
1453
while (protect_against_global_read_lock && !thd->killed)
1094
while (protect_against_global_read_lock && !session->killed)
1454
1095
pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1455
protect_against_global_read_lock--;
1456
if ((error= test(thd->killed)))
1096
if ((error= test(session->killed)))
1457
1097
global_read_lock_blocks_commit--; // undo what we did
1459
thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1460
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1099
session->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1100
session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1484
1124
void broadcast_refresh(void)
1486
VOID(pthread_cond_broadcast(&COND_refresh));
1487
VOID(pthread_cond_broadcast(&COND_global_read_lock));
1492
Try to get transactional table locks for the tables in the list.
1495
try_transactional_lock()
1497
table_list List of tables to lock
1500
This is called if transactional table locks are requested for all
1501
tables in table_list and no non-transactional locks pre-exist.
1504
0 OK. All tables are transactional locked.
1505
1 Error: must fall back to non-transactional locks.
1506
-1 Error: no recovery possible.
1509
int try_transactional_lock(THD *thd, TABLE_LIST *table_list)
1515
/* Need to open the tables to be able to access engine methods. */
1516
if (open_tables(thd, &table_list, &dummy_counter, 0))
1518
/* purecov: begin tested */
1523
/* Required by InnoDB. */
1524
thd->in_lock_tables= true;
1526
if ((error= set_handler_table_locks(thd, table_list, true)))
1529
Not all transactional locks could be taken. If the error was
1530
something else but "unsupported by storage engine", abort the
1531
execution of this statement.
1533
if (error != HA_ERR_WRONG_COMMAND)
1539
Fall back to non-transactional locks because transactional locks
1540
are unsupported by a storage engine. No need to unlock the
1541
successfully taken transactional locks. They go away at end of
1548
/* We need to explicitly commit if autocommit mode is active. */
1549
(void) ha_autocommit_or_rollback(thd, 0);
1550
/* Close the tables. The locks (if taken) persist in the storage engines. */
1551
close_tables_for_reopen(thd, &table_list);
1552
thd->in_lock_tables= false;
1558
Check if lock method conversion was done and was allowed.
1561
check_transactional_lock()
1563
table_list List of tables to lock
1567
Lock method conversion can be done during parsing if one of the
1568
locks is non-transactional. It can also happen if non-transactional
1569
table locks exist when the statement is executed or if a storage
1570
engine does not support transactional table locks.
1572
Check if transactional table locks have been converted to
1573
non-transactional and if this was allowed. In a running transaction
1574
or in strict mode lock method conversion is not allowed - report an
1575
error. Otherwise it is allowed - issue a warning.
1578
0 OK. Proceed with non-transactional locks.
1579
-1 Error: Lock conversion is prohibited.
1582
int check_transactional_lock(THD *thd, TABLE_LIST *table_list)
1586
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1588
for (tlist= table_list; tlist; tlist= tlist->next_global)
1592
Unfortunately we cannot use tlist->placeholder() here. This method
1593
returns TRUE if the table is not open, which is always the case
1594
here. Whenever the definition of TABLE_LIST::placeholder() is
1595
changed, probably this condition needs to be changed too.
1597
if (tlist->derived || tlist->schema_table || !tlist->lock_transactional)
1602
/* We must not convert the lock method in strict mode. */
1604
my_error(ER_NO_AUTO_CONVERT_LOCK_STRICT, MYF(0),
1605
tlist->alias ? tlist->alias : tlist->table_name);
1610
/* We must not convert the lock method within an active transaction. */
1611
if (thd->active_transaction())
1613
my_error(ER_NO_AUTO_CONVERT_LOCK_TRANSACTION, MYF(0),
1614
tlist->alias ? tlist->alias : tlist->table_name);
1619
/* Warn about the conversion. */
1620
snprintf(warn_buff, sizeof(warn_buff), ER(ER_WARN_AUTO_CONVERT_LOCK),
1621
tlist->alias ? tlist->alias : tlist->table_name);
1622
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1623
ER_WARN_AUTO_CONVERT_LOCK, warn_buff);
1631
Set table locks in the table handler.
1634
set_handler_table_locks()
1636
table_list List of tables to lock
1637
transactional If to lock transactional or non-transactional
1641
!= 0 Error code from handler::lock_table().
1644
int set_handler_table_locks(THD *thd, TABLE_LIST *table_list,
1650
for (tlist= table_list; tlist; tlist= tlist->next_global)
1653
int lock_timeout= -1; /* Use default for non-transactional locks. */
1655
if (tlist->placeholder())
1658
assert((tlist->lock_type == TL_READ) ||
1659
(tlist->lock_type == TL_READ_NO_INSERT) ||
1660
(tlist->lock_type == TL_WRITE_DEFAULT) ||
1661
(tlist->lock_type == TL_WRITE) ||
1662
(tlist->lock_type == TL_WRITE_LOW_PRIORITY));
1665
Every tlist object has a proper lock_type set. Even if it came in
1666
the list as a base table from a view only.
1668
lock_type= ((tlist->lock_type <= TL_READ_NO_INSERT) ?
1669
HA_LOCK_IN_SHARE_MODE : HA_LOCK_IN_EXCLUSIVE_MODE);
1674
The lock timeout is not set if this table belongs to a view. We
1675
need to take it from the top-level view. After this loop
1676
iteration, lock_timeout is not needed any more. Not even if the
1677
locks are converted to non-transactional locks later.
1678
Non-transactional locks do not support a lock_timeout.
1680
lock_timeout= tlist->top_table()->lock_timeout;
1683
For warning/error reporting we need to set the intended lock
1684
method in the TABLE_LIST object. It will be used later by
1685
check_transactional_lock(). The lock method is not set if this
1686
table belongs to a view. We can safely set it to transactional
1687
locking here. Even for non-view tables. This function is not
1688
called if non-transactional locking was requested for any
1691
tlist->lock_transactional= true;
1695
Because we need to set the lock method (see above) for all
1696
involved tables, we cannot break the loop on an error.
1697
But we do not try more locks after the first error.
1698
However, for non-transactional locking handler::lock_table() is
1699
a hint only. So we continue to call it for other tables.
1701
if (!error || !transactional)
1703
error= tlist->table->file->lock_table(thd, lock_type, lock_timeout);
1704
if (error && transactional && (error != HA_ERR_WRONG_COMMAND))
1705
tlist->table->file->print_error(error, MYF(0));
1126
pthread_cond_broadcast(&COND_refresh);
1127
pthread_cond_broadcast(&COND_global_read_lock);
1714
1132
@} (end of group Locking)
1135
} /* namespace drizzled */