214
session->set_proc_info("Notify start statement");
216
* Here, we advise all storage engines involved in the
217
* statement that we are starting a new statement
219
if (sql_lock->table_count)
221
size_t num_tables= sql_lock->table_count;
222
plugin::StorageEngine *engine;
223
set<size_t> involved_slots;
224
for (size_t x= 1; x <= num_tables; x++, tables++)
226
engine= (*tables)->cursor->engine;
227
if (involved_slots.count(engine->getId()) > 0)
228
continue; /* already added to involved engines */
229
involved_engines.push_back(engine);
230
involved_slots.insert(engine->getId());
233
for_each(involved_engines.begin(),
234
involved_engines.end(),
235
bind2nd(mem_fun(&plugin::StorageEngine::startStatement), session));
238
session->set_proc_info("External lock");
240
* Here, the call to lock_external() informs the
241
* all engines for all tables used in this statement
242
* of the type of lock that Drizzle intends to take on a
200
session->set_proc_info("System lock");
245
201
if (sql_lock->table_count && lock_external(session, sql_lock->table,
246
202
sql_lock->table_count))
473
422
effect is desired.
476
void mysql_lock_remove(Session *session, Table *table)
425
void mysql_lock_remove(Session *session, DRIZZLE_LOCK *locked,Table *table,
478
mysql_unlock_some_tables(session, &table, /* table count */ 1);
428
if (always_unlock == true)
429
mysql_unlock_some_tables(session, &table, /* table count */ 1);
433
for (i=0; i < locked->table_count; i++)
435
if (locked->table[i] == table)
437
uint32_t j, removed_locks, old_tables;
439
uint32_t lock_data_end;
441
assert(table->lock_position == i);
443
/* Unlock if not yet unlocked */
444
if (always_unlock == false)
445
mysql_unlock_some_tables(session, &table, /* table count */ 1);
447
/* Decrement table_count in advance, making below expressions easier */
448
old_tables= --locked->table_count;
450
/* The table has 'removed_locks' lock data elements in locked->locks */
451
removed_locks= table->lock_count;
453
/* Move down all table pointers above 'i'. */
454
memmove((locked->table+i), (locked->table+i+1),
455
(old_tables - i) * sizeof(Table*));
457
lock_data_end= table->lock_data_start + table->lock_count;
458
/* Move down all lock data pointers above 'table->lock_data_end-1' */
459
memmove((locked->locks + table->lock_data_start),
460
(locked->locks + lock_data_end),
461
(locked->lock_count - lock_data_end) *
462
sizeof(THR_LOCK_DATA*));
465
Fix moved table elements.
466
lock_position is the index in the 'locked->table' array,
467
it must be fixed by one.
468
table->lock_data_start is pointer to the lock data for this table
469
in the 'locked->locks' array, they must be fixed by 'removed_locks',
470
the lock data count of the removed table.
472
for (j= i ; j < old_tables; j++)
474
tbl= locked->table[j];
475
tbl->lock_position--;
476
assert(tbl->lock_position == j);
477
tbl->lock_data_start-= removed_locks;
480
/* Finally adjust lock_count. */
481
locked->lock_count-= removed_locks;
482
489
/** Abort all other threads waiting to get lock in table. */
484
void mysql_lock_abort(Session *session, Table *table)
491
void mysql_lock_abort(Session *session, Table *table, bool upgrade_lock)
486
493
DRIZZLE_LOCK *locked;
487
494
Table *write_lock_used;
539
DRIZZLE_LOCK *mysql_lock_merge(DRIZZLE_LOCK *a, DRIZZLE_LOCK *b)
541
DRIZZLE_LOCK *sql_lock;
542
Table **table, **end_table;
544
if (!(sql_lock= (DRIZZLE_LOCK*)
545
malloc(sizeof(*sql_lock)+
546
sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
547
sizeof(Table*)*(a->table_count+b->table_count))))
548
return NULL; // Fatal error
549
sql_lock->lock_count=a->lock_count+b->lock_count;
550
sql_lock->table_count=a->table_count+b->table_count;
551
sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
552
sql_lock->table=(Table**) (sql_lock->locks+sql_lock->lock_count);
553
memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
554
memcpy(sql_lock->locks+a->lock_count,b->locks,
555
b->lock_count*sizeof(*b->locks));
556
memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
557
memcpy(sql_lock->table+a->table_count,b->table,
558
b->table_count*sizeof(*b->table));
561
Now adjust lock_position and lock_data_start for all objects that was
562
moved in 'b' (as there is now all objects in 'a' before these).
564
for (table= sql_lock->table + a->table_count,
565
end_table= table + b->table_count;
569
(*table)->lock_position+= a->table_count;
570
(*table)->lock_data_start+= a->lock_count;
573
/* Delete old, not needed locks */
574
free((unsigned char*) a);
575
free((unsigned char*) b);
582
Find duplicate lock in tables.
584
Temporary tables are ignored here like they are ignored in
585
get_lock_data(). If we allow two opens on temporary tables later,
586
both functions should be checked.
588
@param session The current thread.
589
@param needle The table to check for duplicate lock.
590
@param haystack The list of tables to search for the dup lock.
593
This is mainly meant for MERGE tables in INSERT ... SELECT
594
situations. The 'real', underlying tables can be found only after
595
the MERGE tables are opened. This function assumes that the tables are
599
NULL No duplicate lock found.
601
!NULL First table from 'haystack' that matches a lock on 'needle'.
604
TableList *mysql_lock_have_duplicate(Session *session, TableList *needle,
607
DRIZZLE_LOCK *mylock;
611
THR_LOCK_DATA **lock_locks;
612
THR_LOCK_DATA **table_lock_data;
613
THR_LOCK_DATA **end_data;
614
THR_LOCK_DATA **lock_data2;
615
THR_LOCK_DATA **end_data2;
618
Table may not be defined for derived or view tables.
619
Table may not be part of a lock for delayed operations.
621
if (! (table= needle->table) || ! table->lock_count)
624
/* A temporary table does not have locks. */
625
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
628
/* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
629
if (!(mylock= session->lock))
632
/* If we have less than two tables, we cannot have duplicates. */
633
if (mylock->table_count < 2)
636
lock_locks= mylock->locks;
637
lock_tables= mylock->table;
639
/* Prepare table related variables that don't change in loop. */
640
assert((table->lock_position < mylock->table_count) &&
641
(table == lock_tables[table->lock_position]));
642
table_lock_data= lock_locks + table->lock_data_start;
643
end_data= table_lock_data + table->lock_count;
645
for (; haystack; haystack= haystack->next_global)
647
if (haystack->placeholder())
649
table2= haystack->table;
650
if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
653
/* All tables in list must be in lock. */
654
assert((table2->lock_position < mylock->table_count) &&
655
(table2 == lock_tables[table2->lock_position]));
657
for (lock_data2= lock_locks + table2->lock_data_start,
658
end_data2= lock_data2 + table2->lock_count;
659
lock_data2 < end_data2;
662
THR_LOCK_DATA **lock_data;
663
THR_LOCK *lock2= (*lock_data2)->lock;
665
for (lock_data= table_lock_data;
666
lock_data < end_data;
669
if ((*lock_data)->lock == lock2)
531
680
/** Unlock a set of external. */
533
682
static int unlock_external(Session *session, Table **table,uint32_t count)
803
/*****************************************************************************
804
Lock table based on the name.
805
This is used when we need total access to a closed, not open table
806
*****************************************************************************/
809
Lock and wait for the named lock.
811
@param session Thread handler
812
@param table_list Lock first table in this list
816
Works together with global read lock.
824
int lock_and_wait_for_table_name(Session *session, TableList *table_list)
829
if (wait_if_global_read_lock(session, 0, 1))
831
pthread_mutex_lock(&LOCK_open); /* lock and wait for table when we need total access to table */
832
if ((lock_retcode = lock_table_name(session, table_list, true)) < 0)
834
if (lock_retcode && wait_for_locked_table_names(session, table_list))
836
unlock_table_name(table_list);
842
pthread_mutex_unlock(&LOCK_open);
843
start_waiting_global_read_lock(session);
657
849
Put a not open table with an old refresh version in the table cache.