~drizzle-trunk/drizzle/development

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
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
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
30
  - For each SQL statement mysql_lock_tables() is called for all involved
31
    tables.
32
    - mysql_lock_tables() will call
33
      table_handler->external_lock(thd,locktype) for each table.
34
      This is followed by a call to thr_multi_lock() for all tables.
35
36
  - When statement is done, we call mysql_unlock_tables().
37
    This will call thr_multi_unlock() followed by
38
    table_handler->external_lock(thd, F_UNLCK) for each table.
39
40
  - Note that mysql_unlock_tables() may be called several times as
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()
46
    and we never call external_lock(thd, F_UNLOCK) on these.
47
48
  When using LOCK TABLES:
49
50
  - LOCK TABLE will call mysql_lock_tables() for all tables.
51
    mysql_lock_tables() will call
52
    table_handler->external_lock(thd,locktype) for each table.
53
    This is followed by a call to thr_multi_lock() for all tables.
54
55
  - For each statement, we will call table_handler->start_stmt(THD)
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
61
  - When statement is done, we will call ha_commit_stmt(thd);
62
63
  - When calling UNLOCK TABLES we call mysql_unlock_tables() for all
64
    tables used in LOCK TABLES
65
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,
68
  excluding one that caused failure. That means handler must cleanup itself
69
  in case external_lock() fails.
70
71
  @todo
72
  Change to use my_malloc() ONLY when using LOCK TABLES command or when
73
  we are forced to use mysql_lock_merge.
74
*/
75
76
#include "mysql_priv.h"
77
#include <hash.h>
78
#include <assert.h>
79
80
/**
81
  @defgroup Locking Locking
82
  @{
83
*/
84
85
extern HASH open_cache;
86
87
/* flags for get_lock_data */
88
#define GET_LOCK_UNLOCK         1
89
#define GET_LOCK_STORE_LOCKS    2
90
91
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
92
				 uint flags, TABLE **write_locked);
93
static int lock_external(THD *thd, TABLE **table,uint count);
94
static int unlock_external(THD *thd, TABLE **table,uint count);
95
static void print_lock_error(int error, const char *);
96
97
/*
98
  Lock tables.
99
100
  SYNOPSIS
101
    mysql_lock_tables()
102
    thd                         The current thread.
103
    tables                      An array of pointers to the tables to lock.
104
    count                       The number of tables to lock.
105
    flags                       Options:
106
      MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK      Ignore a global read lock
107
      MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY      Ignore SET GLOBAL READ_ONLY
108
      MYSQL_LOCK_IGNORE_FLUSH                 Ignore a flush tables.
109
      MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN        Instead of reopening altered
110
                                              or dropped tables by itself,
111
                                              mysql_lock_tables() should
112
                                              notify upper level and rely
113
                                              on caller doing this.
114
    need_reopen                 Out parameter, TRUE if some tables were altered
115
                                or deleted and should be reopened by caller.
116
117
  RETURN
118
    A lock structure pointer on success.
119
    NULL on error or if some tables should be reopen.
120
*/
121
122
/* Map the return value of thr_lock to an error from errmsg.txt */
123
static int thr_lock_errno_to_mysql[]=
124
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
125
126
/**
127
  Perform semantic checks for mysql_lock_tables.
128
  @param thd The current thread
129
  @param tables The tables to lock
130
  @param count The number of tables to lock
131
  @param flags Lock flags
132
  @return 0 if all the check passed, non zero if a check failed.
133
*/
134
int mysql_lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
135
{
136
  uint system_count;
137
  uint i;
138
139
  DBUG_ENTER("mysql_lock_tables_check");
140
141
  system_count= 0;
142
143
  for (i=0 ; i<count; i++)
144
  {
145
    TABLE *t= tables[i];
146
147
    /* Protect against 'fake' partially initialized TABLE_SHARE */
148
    DBUG_ASSERT(t->s->table_category != TABLE_UNKNOWN_CATEGORY);
149
150
    if ((t->s->table_category == TABLE_CATEGORY_SYSTEM) &&
151
        (t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE))
152
    {
153
      system_count++;
154
    }
155
  }
156
157
  /*
158
    Locking of system tables is restricted:
159
    locking a mix of system and non-system tables in the same lock
160
    is prohibited, to prevent contention.
161
  */
162
  if ((system_count > 0) && (system_count < count))
163
  {
164
    my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
165
    DBUG_RETURN(1);
166
  }
167
168
  DBUG_RETURN(0);
169
}
170
171
172
/**
173
  Reset lock type in lock data and free.
174
175
  @param mysql_lock Lock structures to reset.
176
177
  @note After a locking error we want to quit the locking of the table(s).
178
        The test case in the bug report for Bug #18544 has the following
179
        cases: 1. Locking error in lock_external() due to InnoDB timeout.
180
        2. Locking error in get_lock_data() due to missing write permission.
181
        3. Locking error in wait_if_global_read_lock() due to lock conflict.
182
183
  @note In all these cases we have already set the lock type into the lock
184
        data of the open table(s). If the table(s) are in the open table
185
        cache, they could be reused with the non-zero lock type set. This
186
        could lead to ignoring a different lock type with the next lock.
187
188
  @note Clear the lock type of all lock data. This ensures that the next
189
        lock request will set its lock type properly.
190
*/
191
192
static void reset_lock_data_and_free(MYSQL_LOCK **mysql_lock)
193
{
194
  MYSQL_LOCK *sql_lock= *mysql_lock;
195
  THR_LOCK_DATA **ldata, **ldata_end;
196
197
  /* Clear the lock type of all lock data to avoid reusage. */
198
  for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
199
       ldata < ldata_end;
200
       ldata++)
201
  {
202
    /* Reset lock type. */
203
    (*ldata)->type= TL_UNLOCK;
204
  }
205
  my_free((uchar*) sql_lock, MYF(0));
206
  *mysql_lock= 0;
207
}
208
209
210
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
211
                              uint flags, bool *need_reopen)
212
{
213
  MYSQL_LOCK *sql_lock;
214
  TABLE *write_lock_used;
215
  int rc;
216
217
  DBUG_ENTER("mysql_lock_tables");
218
219
  *need_reopen= FALSE;
220
221
  if (mysql_lock_tables_check(thd, tables, count, flags))
222
    DBUG_RETURN (NULL);
223
224
  for (;;)
225
  {
226
    if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS,
227
                                   &write_lock_used)))
228
      break;
229
230
    if (global_read_lock && write_lock_used &&
231
        ! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
232
    {
233
      /*
234
	Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
235
	Wait until the lock is gone
236
      */
237
      if (wait_if_global_read_lock(thd, 1, 1))
238
      {
239
        /* Clear the lock type of all lock data to avoid reusage. */
240
        reset_lock_data_and_free(&sql_lock);
241
	break;
242
      }
243
      if (thd->version != refresh_version)
244
      {
245
        /* Clear the lock type of all lock data to avoid reusage. */
246
        reset_lock_data_and_free(&sql_lock);
247
	goto retry;
248
      }
249
    }
250
251
    if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
252
        write_lock_used &&
253
        opt_readonly &&
254
        !thd->slave_thread)
255
    {
256
      /*
257
	Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
258
        We do not wait for READ_ONLY=0, and fail.
259
      */
260
      reset_lock_data_and_free(&sql_lock);
261
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
262
      break;
263
    }
264
265
    thd_proc_info(thd, "System lock");
266
    DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
267
    if (sql_lock->table_count && lock_external(thd, sql_lock->table,
268
                                               sql_lock->table_count))
269
    {
270
      /* Clear the lock type of all lock data to avoid reusage. */
271
      reset_lock_data_and_free(&sql_lock);
272
      break;
273
    }
274
    thd_proc_info(thd, "Table lock");
275
    DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
276
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
277
    memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
278
           sql_lock->lock_count * sizeof(*sql_lock->locks));
279
    /* Lock on the copied half of the lock data array. */
280
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
281
                                                     sql_lock->lock_count,
282
                                                     sql_lock->lock_count,
283
                                                     thd->lock_id)];
284
    if (rc > 1)                                 /* a timeout or a deadlock */
285
    {
286
      if (sql_lock->table_count)
287
        VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
288
      reset_lock_data_and_free(&sql_lock);
289
      my_error(rc, MYF(0));
290
      break;
291
    }
292
    else if (rc == 1)                           /* aborted */
293
    {
294
      thd->some_tables_deleted=1;		// Try again
295
      sql_lock->lock_count= 0;                  // Locks are already freed
296
      // Fall through: unlock, reset lock data, free and retry
297
    }
298
    else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
299
    {
300
      /*
301
        Thread was killed or lock aborted. Let upper level close all
302
        used tables and retry or give error.
303
      */
304
      break;
305
    }
306
    else if (!thd->open_tables)
307
    {
308
      // Only using temporary tables, no need to unlock
309
      thd->some_tables_deleted=0;
310
      break;
311
    }
312
    thd_proc_info(thd, 0);
313
314
    /* going to retry, unlock all tables */
315
    if (sql_lock->lock_count)
316
        thr_multi_unlock(sql_lock->locks, sql_lock->lock_count);
317
318
    if (sql_lock->table_count)
319
      VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
320
321
    /*
322
      If thr_multi_lock fails it resets lock type for tables, which
323
      were locked before (and including) one that caused error. Lock
324
      type for other tables preserved.
325
    */
326
    reset_lock_data_and_free(&sql_lock);
327
retry:
328
    if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
329
    {
330
      *need_reopen= TRUE;
331
      break;
332
    }
333
    if (wait_for_tables(thd))
334
      break;					// Couldn't open tables
335
  }
336
  thd_proc_info(thd, 0);
337
  if (thd->killed)
338
  {
339
    thd->send_kill_message();
340
    if (sql_lock)
341
    {
342
      mysql_unlock_tables(thd,sql_lock);
343
      sql_lock=0;
344
    }
345
  }
346
347
  thd->set_time_after_lock();
348
  DBUG_RETURN (sql_lock);
349
}
350
351
352
static int lock_external(THD *thd, TABLE **tables, uint count)
353
{
354
  register uint i;
355
  int lock_type,error;
356
  DBUG_ENTER("lock_external");
357
358
  DBUG_PRINT("info", ("count %d", count));
359
  for (i=1 ; i <= count ; i++, tables++)
360
  {
361
    DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
362
    lock_type=F_WRLCK;				/* Lock exclusive */
363
    if ((*tables)->db_stat & HA_READ_ONLY ||
364
	((*tables)->reginfo.lock_type >= TL_READ &&
365
	 (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
366
      lock_type=F_RDLCK;
367
368
    if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
369
    {
370
      print_lock_error(error, (*tables)->file->table_type());
371
      while (--i)
372
      {
373
        tables--;
374
	(*tables)->file->ha_external_lock(thd, F_UNLCK);
375
	(*tables)->current_lock=F_UNLCK;
376
      }
377
      DBUG_RETURN(error);
378
    }
379
    else
380
    {
381
      (*tables)->db_stat &= ~ HA_BLOCK_LOCK;
382
      (*tables)->current_lock= lock_type;
383
    }
384
  }
385
  DBUG_RETURN(0);
386
}
387
388
389
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
390
{
391
  DBUG_ENTER("mysql_unlock_tables");
392
  if (sql_lock->lock_count)
393
    thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
394
  if (sql_lock->table_count)
395
    VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count));
396
  my_free((uchar*) sql_lock,MYF(0));
397
  DBUG_VOID_RETURN;
398
}
399
400
/**
401
  Unlock some of the tables locked by mysql_lock_tables.
402
403
  This will work even if get_lock_data fails (next unlock will free all)
404
*/
405
406
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count)
407
{
408
  MYSQL_LOCK *sql_lock;
409
  TABLE *write_lock_used;
410
  if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK,
411
                               &write_lock_used)))
412
    mysql_unlock_tables(thd, sql_lock);
413
}
414
415
416
/**
417
  unlock all tables locked for read.
418
*/
419
420
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
421
{
422
  uint i,found;
423
  DBUG_ENTER("mysql_unlock_read_tables");
424
425
  /* Move all write locks first */
426
  THR_LOCK_DATA **lock=sql_lock->locks;
427
  for (i=found=0 ; i < sql_lock->lock_count ; i++)
428
  {
429
    if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
430
    {
431
      swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]);
432
      lock++;
433
      found++;
434
    }
435
  }
436
  /* unlock the read locked tables */
437
  if (i != found)
438
  {
439
    thr_multi_unlock(lock,i-found);
440
    sql_lock->lock_count= found;
441
  }
442
443
  /* Then do the same for the external locks */
444
  /* Move all write locked tables first */
445
  TABLE **table=sql_lock->table;
446
  for (i=found=0 ; i < sql_lock->table_count ; i++)
447
  {
448
    DBUG_ASSERT(sql_lock->table[i]->lock_position == i);
449
    if ((uint) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
450
    {
451
      swap_variables(TABLE *, *table, sql_lock->table[i]);
452
      table++;
453
      found++;
454
    }
455
  }
456
  /* Unlock all read locked tables */
457
  if (i != found)
458
  {
459
    VOID(unlock_external(thd,table,i-found));
460
    sql_lock->table_count=found;
461
  }
462
  /* Fix the lock positions in TABLE */
463
  table= sql_lock->table;
464
  found= 0;
465
  for (i= 0; i < sql_lock->table_count; i++)
466
  {
467
    TABLE *tbl= *table;
468
    tbl->lock_position= table - sql_lock->table;
469
    tbl->lock_data_start= found;
470
    found+= tbl->lock_count;
471
    table++;
472
  }
473
  DBUG_VOID_RETURN;
474
}
475
476
477
/**
478
  Try to find the table in the list of locked tables.
479
  In case of success, unlock the table and remove it from this list.
480
481
  @note This function has a legacy side effect: the table is
482
  unlocked even if it is not found in the locked list.
483
  It's not clear if this side effect is intentional or still
484
  desirable. It might lead to unmatched calls to
485
  unlock_external(). Moreover, a discrepancy can be left
486
  unnoticed by the storage engine, because in
487
  unlock_external() we call handler::external_lock(F_UNLCK) only
488
  if table->current_lock is not F_UNLCK.
489
490
  @param  thd             thread context
491
  @param  locked          list of locked tables
492
  @param  table           the table to unlock
493
  @param  always_unlock   specify explicitly if the legacy side
494
                          effect is desired.
495
*/
496
497
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
498
                       bool always_unlock)
499
{
500
  if (always_unlock == TRUE)
501
    mysql_unlock_some_tables(thd, &table, /* table count */ 1);
502
  if (locked)
503
  {
504
    register uint i;
505
    for (i=0; i < locked->table_count; i++)
506
    {
507
      if (locked->table[i] == table)
508
      {
509
        uint  j, removed_locks, old_tables;
510
        TABLE *tbl;
511
        uint lock_data_end;
512
513
        DBUG_ASSERT(table->lock_position == i);
514
515
        /* Unlock if not yet unlocked */
516
        if (always_unlock == FALSE)
517
          mysql_unlock_some_tables(thd, &table, /* table count */ 1);
518
519
        /* Decrement table_count in advance, making below expressions easier */
520
        old_tables= --locked->table_count;
521
522
        /* The table has 'removed_locks' lock data elements in locked->locks */
523
        removed_locks= table->lock_count;
524
525
        /* Move down all table pointers above 'i'. */
526
	bmove((char*) (locked->table+i),
527
	      (char*) (locked->table+i+1),
528
	      (old_tables - i) * sizeof(TABLE*));
529
530
        lock_data_end= table->lock_data_start + table->lock_count;
531
        /* Move down all lock data pointers above 'table->lock_data_end-1' */
532
        bmove((char*) (locked->locks + table->lock_data_start),
533
              (char*) (locked->locks + lock_data_end),
534
              (locked->lock_count - lock_data_end) *
535
              sizeof(THR_LOCK_DATA*));
536
537
        /*
538
          Fix moved table elements.
539
          lock_position is the index in the 'locked->table' array,
540
          it must be fixed by one.
541
          table->lock_data_start is pointer to the lock data for this table
542
          in the 'locked->locks' array, they must be fixed by 'removed_locks',
543
          the lock data count of the removed table.
544
        */
545
        for (j= i ; j < old_tables; j++)
546
        {
547
          tbl= locked->table[j];
548
          tbl->lock_position--;
549
          DBUG_ASSERT(tbl->lock_position == j);
550
          tbl->lock_data_start-= removed_locks;
551
        }
552
553
        /* Finally adjust lock_count. */
554
        locked->lock_count-= removed_locks;
555
	break;
556
      }
557
    }
558
  }
559
}
560
561
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
562
563
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
564
                                thr_lock_type new_lock_type)
565
{
566
  MYSQL_LOCK *locked;
567
  TABLE *write_lock_used;
568
  if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
569
                              &write_lock_used)))
570
  {
571
    for (uint i=0; i < locked->lock_count; i++)
572
      thr_downgrade_write_lock(locked->locks[i], new_lock_type);
573
    my_free((uchar*) locked,MYF(0));
574
  }
575
}
576
577
578
/** Abort all other threads waiting to get lock in table. */
579
580
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
581
{
582
  MYSQL_LOCK *locked;
583
  TABLE *write_lock_used;
584
  DBUG_ENTER("mysql_lock_abort");
585
586
  if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
587
                             &write_lock_used)))
588
  {
589
    for (uint i=0; i < locked->lock_count; i++)
590
      thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
591
    my_free((uchar*) locked,MYF(0));
592
  }
593
  DBUG_VOID_RETURN;
594
}
595
596
597
/**
598
  Abort one thread / table combination.
599
600
  @param thd	   Thread handler
601
  @param table	   Table that should be removed from lock queue
602
603
  @retval
604
    0  Table was not locked by another thread
605
  @retval
606
    1  Table was locked by at least one other thread
607
*/
608
609
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
610
{
611
  MYSQL_LOCK *locked;
612
  TABLE *write_lock_used;
613
  bool result= FALSE;
614
  DBUG_ENTER("mysql_lock_abort_for_thread");
615
616
  if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
617
                             &write_lock_used)))
618
  {
619
    for (uint i=0; i < locked->lock_count; i++)
620
    {
621
      if (thr_abort_locks_for_thread(locked->locks[i]->lock,
622
                                     table->in_use->thread_id))
623
        result= TRUE;
624
    }
625
    my_free((uchar*) locked,MYF(0));
626
  }
627
  DBUG_RETURN(result);
628
}
629
630
631
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
632
{
633
  MYSQL_LOCK *sql_lock;
634
  TABLE **table, **end_table;
635
  DBUG_ENTER("mysql_lock_merge");
636
637
  if (!(sql_lock= (MYSQL_LOCK*)
638
	my_malloc(sizeof(*sql_lock)+
639
		  sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
640
		  sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
641
    DBUG_RETURN(0);				// Fatal error
642
  sql_lock->lock_count=a->lock_count+b->lock_count;
643
  sql_lock->table_count=a->table_count+b->table_count;
644
  sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
645
  sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count);
646
  memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
647
  memcpy(sql_lock->locks+a->lock_count,b->locks,
648
	 b->lock_count*sizeof(*b->locks));
649
  memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
650
  memcpy(sql_lock->table+a->table_count,b->table,
651
	 b->table_count*sizeof(*b->table));
652
653
  /*
654
    Now adjust lock_position and lock_data_start for all objects that was
655
    moved in 'b' (as there is now all objects in 'a' before these).
656
  */
657
  for (table= sql_lock->table + a->table_count,
658
         end_table= table + b->table_count;
659
       table < end_table;
660
       table++)
661
  {
662
    (*table)->lock_position+=   a->table_count;
663
    (*table)->lock_data_start+= a->lock_count;
664
  }
665
666
  /* Delete old, not needed locks */
667
  my_free((uchar*) a,MYF(0));
668
  my_free((uchar*) b,MYF(0));
669
  DBUG_RETURN(sql_lock);
670
}
671
672
673
/**
674
  Find duplicate lock in tables.
675
676
  Temporary tables are ignored here like they are ignored in
677
  get_lock_data(). If we allow two opens on temporary tables later,
678
  both functions should be checked.
679
680
  @param thd                 The current thread.
681
  @param needle              The table to check for duplicate lock.
682
  @param haystack            The list of tables to search for the dup lock.
683
684
  @note
685
    This is mainly meant for MERGE tables in INSERT ... SELECT
686
    situations. The 'real', underlying tables can be found only after
687
    the MERGE tables are opened. This function assumes that the tables are
688
    already locked.
689
690
  @retval
691
    NULL    No duplicate lock found.
692
  @retval
693
    !NULL   First table from 'haystack' that matches a lock on 'needle'.
694
*/
695
696
TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
697
                                      TABLE_LIST *haystack)
698
{
699
  MYSQL_LOCK            *mylock;
700
  TABLE                 **lock_tables;
701
  TABLE                 *table;
702
  TABLE                 *table2;
703
  THR_LOCK_DATA         **lock_locks;
704
  THR_LOCK_DATA         **table_lock_data;
705
  THR_LOCK_DATA         **end_data;
706
  THR_LOCK_DATA         **lock_data2;
707
  THR_LOCK_DATA         **end_data2;
708
  DBUG_ENTER("mysql_lock_have_duplicate");
709
710
  /*
711
    Table may not be defined for derived or view tables.
712
    Table may not be part of a lock for delayed operations.
713
  */
714
  if (! (table= needle->table) || ! table->lock_count)
715
    goto end;
716
717
  /* A temporary table does not have locks. */
718
  if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
719
    goto end;
720
721
  /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
722
  if (! (mylock= thd->lock ? thd->lock : thd->locked_tables))
723
    goto end;
724
725
  /* If we have less than two tables, we cannot have duplicates. */
726
  if (mylock->table_count < 2)
727
    goto end;
728
729
  lock_locks=  mylock->locks;
730
  lock_tables= mylock->table;
731
732
  /* Prepare table related variables that don't change in loop. */
733
  DBUG_ASSERT((table->lock_position < mylock->table_count) &&
734
              (table == lock_tables[table->lock_position]));
735
  table_lock_data= lock_locks + table->lock_data_start;
736
  end_data= table_lock_data + table->lock_count;
737
738
  for (; haystack; haystack= haystack->next_global)
739
  {
740
    if (haystack->placeholder())
741
      continue;
742
    table2= haystack->table;
743
    if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
744
      continue;
745
746
    /* All tables in list must be in lock. */
747
    DBUG_ASSERT((table2->lock_position < mylock->table_count) &&
748
                (table2 == lock_tables[table2->lock_position]));
749
750
    for (lock_data2=  lock_locks + table2->lock_data_start,
751
           end_data2= lock_data2 + table2->lock_count;
752
         lock_data2 < end_data2;
753
         lock_data2++)
754
    {
755
      THR_LOCK_DATA **lock_data;
756
      THR_LOCK *lock2= (*lock_data2)->lock;
757
758
      for (lock_data= table_lock_data;
759
           lock_data < end_data;
760
           lock_data++)
761
      {
762
        if ((*lock_data)->lock == lock2)
763
        {
764
          DBUG_PRINT("info", ("haystack match: '%s'", haystack->table_name));
765
          DBUG_RETURN(haystack);
766
        }
767
      }
768
    }
769
  }
770
771
 end:
772
  DBUG_PRINT("info", ("no duplicate found"));
773
  DBUG_RETURN(NULL);
774
}
775
776
777
/** Unlock a set of external. */
778
779
static int unlock_external(THD *thd, TABLE **table,uint count)
780
{
781
  int error,error_code;
782
  DBUG_ENTER("unlock_external");
783
784
  error_code=0;
785
  do
786
  {
787
    if ((*table)->current_lock != F_UNLCK)
788
    {
789
      (*table)->current_lock = F_UNLCK;
790
      if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK)))
791
      {
792
	error_code=error;
793
	print_lock_error(error_code, (*table)->file->table_type());
794
      }
795
    }
796
    table++;
797
  } while (--count);
798
  DBUG_RETURN(error_code);
799
}
800
801
802
/**
803
  Get lock structures from table structs and initialize locks.
804
805
  @param thd		    Thread handler
806
  @param table_ptr	    Pointer to tables that should be locks
807
  @param flags		    One of:
808
           - GET_LOCK_UNLOCK      : If we should send TL_IGNORE to store lock
809
           - GET_LOCK_STORE_LOCKS : Store lock info in TABLE
810
  @param write_lock_used   Store pointer to last table with WRITE_ALLOW_WRITE
811
*/
812
813
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
814
				 uint flags, TABLE **write_lock_used)
815
{
816
  uint i,tables,lock_count;
817
  MYSQL_LOCK *sql_lock;
818
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
819
  TABLE **to, **table_buf;
820
  DBUG_ENTER("get_lock_data");
821
822
  DBUG_ASSERT((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
823
824
  DBUG_PRINT("info", ("count %d", count));
825
  *write_lock_used=0;
826
  for (i=tables=lock_count=0 ; i < count ; i++)
827
  {
828
    TABLE *t= table_ptr[i];
829
830
    if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
831
    {
832
      tables+= t->file->lock_count();
833
      lock_count++;
834
    }
835
  }
836
837
  /*
838
    Allocating twice the number of pointers for lock data for use in
839
    thr_mulit_lock(). This function reorders the lock data, but cannot
840
    update the table values. So the second part of the array is copied
841
    from the first part immediately before calling thr_multi_lock().
842
  */
843
  if (!(sql_lock= (MYSQL_LOCK*)
844
	my_malloc(sizeof(*sql_lock) +
845
		  sizeof(THR_LOCK_DATA*) * tables * 2 +
846
                  sizeof(table_ptr) * lock_count,
847
		  MYF(0))))
848
    DBUG_RETURN(0);
849
  locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
850
  to= table_buf= sql_lock->table= (TABLE**) (locks + tables * 2);
851
  sql_lock->table_count=lock_count;
852
853
  for (i=0 ; i < count ; i++)
854
  {
855
    TABLE *table;
856
    enum thr_lock_type lock_type;
857
858
    if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
859
      continue;
860
    lock_type= table->reginfo.lock_type;
861
    DBUG_ASSERT (lock_type != TL_WRITE_DEFAULT);
862
    if (lock_type >= TL_WRITE_ALLOW_WRITE)
863
    {
864
      *write_lock_used=table;
865
      if (table->db_stat & HA_READ_ONLY)
866
      {
867
	my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
868
        /* Clear the lock type of the lock data that are stored already. */
869
        sql_lock->lock_count= locks - sql_lock->locks;
870
        reset_lock_data_and_free(&sql_lock);
871
	DBUG_RETURN(0);
872
      }
873
    }
874
    THR_LOCK_DATA **org_locks = locks;
875
    locks_start= locks;
876
    locks= table->file->store_lock(thd, locks,
877
                                   (flags & GET_LOCK_UNLOCK) ? TL_IGNORE :
878
                                   lock_type);
879
    if (flags & GET_LOCK_STORE_LOCKS)
880
    {
881
      table->lock_position=   (uint) (to - table_buf);
882
      table->lock_data_start= (uint) (locks_start - locks_buf);
883
      table->lock_count=      (uint) (locks - locks_start);
884
    }
885
    *to++= table;
886
    if (locks)
887
      for ( ; org_locks != locks ; org_locks++)
888
	(*org_locks)->debug_print_param= (void *) table;
889
  }
890
  /*
891
    We do not use 'tables', because there are cases where store_lock()
892
    returns less locks than lock_count() claimed. This can happen when
893
    a FLUSH TABLES tries to abort locks from a MERGE table of another
894
    thread. When that thread has just opened the table, but not yet
895
    attached its children, it cannot return the locks. lock_count()
896
    always returns the number of locks that an attached table has.
897
    This is done to avoid the reverse situation: If lock_count() would
898
    return 0 for a non-attached MERGE table, and that table becomes
899
    attached between the calls to lock_count() and store_lock(), then
900
    we would have allocated too little memory for the lock data. Now
901
    we may allocate too much, but better safe than memory overrun.
902
    And in the FLUSH case, the memory is released quickly anyway.
903
  */
904
  sql_lock->lock_count= locks - locks_buf;
905
  DBUG_PRINT("info", ("sql_lock->table_count %d sql_lock->lock_count %d",
906
                      sql_lock->table_count, sql_lock->lock_count));
907
  DBUG_RETURN(sql_lock);
908
}
909
910
911
/*****************************************************************************
912
  Lock table based on the name.
913
  This is used when we need total access to a closed, not open table
914
*****************************************************************************/
915
916
/**
917
  Lock and wait for the named lock.
918
919
  @param thd			Thread handler
920
  @param table_list		Lock first table in this list
921
922
923
  @note
924
    Works together with global read lock.
925
926
  @retval
927
    0	ok
928
  @retval
929
    1	error
930
*/
931
932
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
933
{
934
  int lock_retcode;
935
  int error= -1;
936
  DBUG_ENTER("lock_and_wait_for_table_name");
937
938
  if (wait_if_global_read_lock(thd, 0, 1))
939
    DBUG_RETURN(1);
940
  VOID(pthread_mutex_lock(&LOCK_open));
941
  if ((lock_retcode = lock_table_name(thd, table_list, TRUE)) < 0)
942
    goto end;
943
  if (lock_retcode && wait_for_locked_table_names(thd, table_list))
944
  {
945
    unlock_table_name(thd, table_list);
946
    goto end;
947
  }
948
  error=0;
949
950
end:
951
  pthread_mutex_unlock(&LOCK_open);
952
  start_waiting_global_read_lock(thd);
953
  DBUG_RETURN(error);
954
}
955
956
957
/**
958
  Put a not open table with an old refresh version in the table cache.
959
960
  @param thd			Thread handler
961
  @param table_list		Lock first table in this list
962
  @param check_in_use           Do we need to check if table already in use by us
963
964
  @note
965
    One must have a lock on LOCK_open!
966
967
  @warning
968
    If you are going to update the table, you should use
969
    lock_and_wait_for_table_name instead of this function as this works
970
    together with 'FLUSH TABLES WITH READ LOCK'
971
972
  @note
973
    This will force any other threads that uses the table to release it
974
    as soon as possible.
975
976
  @return
977
    < 0 error
978
  @return
979
    == 0 table locked
980
  @return
981
    > 0  table locked, but someone is using it
982
*/
983
984
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
985
{
986
  TABLE *table;
987
  char  key[MAX_DBKEY_LENGTH];
988
  char *db= table_list->db;
989
  uint  key_length;
990
  bool  found_locked_table= FALSE;
991
  HASH_SEARCH_STATE state;
992
  DBUG_ENTER("lock_table_name");
993
  DBUG_PRINT("enter",("db: %s  name: %s", db, table_list->table_name));
994
995
  key_length= create_table_def_key(thd, key, table_list, 0);
996
997
  if (check_in_use)
998
  {
999
    /* Only insert the table if we haven't insert it already */
1000
    for (table=(TABLE*) hash_first(&open_cache, (uchar*)key,
1001
                                   key_length, &state);
1002
         table ;
1003
         table = (TABLE*) hash_next(&open_cache,(uchar*) key,
1004
                                    key_length, &state))
1005
    {
1006
      if (table->reginfo.lock_type < TL_WRITE)
1007
      {
1008
        if (table->in_use == thd)
1009
          found_locked_table= TRUE;
1010
        continue;
1011
      }
1012
1013
      if (table->in_use == thd)
1014
      {
1015
        DBUG_PRINT("info", ("Table is in use"));
1016
        table->s->version= 0;                  // Ensure no one can use this
1017
        table->locked_by_name= 1;
1018
        DBUG_RETURN(0);
1019
      }
1020
    }
1021
  }
1022
1023
  if (thd->locked_tables && thd->locked_tables->table_count &&
1024
      ! find_temporary_table(thd, table_list->db, table_list->table_name))
1025
  {
1026
    if (found_locked_table)
1027
      my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias);
1028
    else
1029
      my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_list->alias);
1030
1031
    DBUG_RETURN(-1);
1032
  }
1033
1034
  if (!(table= table_cache_insert_placeholder(thd, key, key_length)))
1035
    DBUG_RETURN(-1);
1036
1037
  table_list->table=table;
1038
1039
  /* Return 1 if table is in use */
1040
  DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name,
1041
             check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
1042
}
1043
1044
1045
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
1046
{
1047
  if (table_list->table)
1048
  {
1049
    hash_delete(&open_cache, (uchar*) table_list->table);
1050
    broadcast_refresh();
1051
  }
1052
}
1053
1054
1055
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
1056
{
1057
  for (; table_list ; table_list=table_list->next_local)
1058
  {
1059
    TABLE *table= table_list->table;
1060
    if (table)
1061
    {
1062
      TABLE *save_next= table->next;
1063
      bool result;
1064
      table->next= 0;
1065
      result= table_is_used(table_list->table, 0);
1066
      table->next= save_next;
1067
      if (result)
1068
        return 1;
1069
    }
1070
  }
1071
  return 0;					// All tables are locked
1072
}
1073
1074
1075
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
1076
{
1077
  bool result=0;
1078
  DBUG_ENTER("wait_for_locked_table_names");
1079
1080
  safe_mutex_assert_owner(&LOCK_open);
1081
1082
  while (locked_named_table(thd,table_list))
1083
  {
1084
    if (thd->killed)
1085
    {
1086
      result=1;
1087
      break;
1088
    }
1089
    wait_for_condition(thd, &LOCK_open, &COND_refresh);
1090
    pthread_mutex_lock(&LOCK_open);
1091
  }
1092
  DBUG_RETURN(result);
1093
}
1094
1095
1096
/**
1097
  Lock all tables in list with a name lock.
1098
1099
  REQUIREMENTS
1100
  - One must have a lock on LOCK_open when calling this
1101
1102
  @param thd			Thread handle
1103
  @param table_list		Names of tables to lock
1104
1105
  @note
1106
    If you are just locking one table, you should use
1107
    lock_and_wait_for_table_name().
1108
1109
  @retval
1110
    0	ok
1111
  @retval
1112
    1	Fatal error (end of memory ?)
1113
*/
1114
1115
bool lock_table_names(THD *thd, TABLE_LIST *table_list)
1116
{
1117
  bool got_all_locks=1;
1118
  TABLE_LIST *lock_table;
1119
1120
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
1121
  {
1122
    int got_lock;
1123
    if ((got_lock=lock_table_name(thd,lock_table, TRUE)) < 0)
1124
      goto end;					// Fatal error
1125
    if (got_lock)
1126
      got_all_locks=0;				// Someone is using table
1127
  }
1128
1129
  /* If some table was in use, wait until we got the lock */
1130
  if (!got_all_locks && wait_for_locked_table_names(thd, table_list))
1131
    goto end;
1132
  return 0;
1133
1134
end:
1135
  unlock_table_names(thd, table_list, lock_table);
1136
  return 1;
1137
}
1138
1139
1140
/**
1141
  Unlock all tables in list with a name lock.
1142
1143
  @param thd        Thread handle.
1144
  @param table_list Names of tables to lock.
1145
1146
  @note 
1147
    This function needs to be protected by LOCK_open. If we're 
1148
    under LOCK TABLES, this function does not work as advertised. Namely,
1149
    it does not exclude other threads from using this table and does not
1150
    put an exclusive name lock on this table into the table cache.
1151
1152
  @see lock_table_names
1153
  @see unlock_table_names
1154
1155
  @retval TRUE An error occured.
1156
  @retval FALSE Name lock successfully acquired.
1157
*/
1158
1159
bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list)
1160
{
1161
  if (lock_table_names(thd, table_list))
1162
    return TRUE;
1163
1164
  /*
1165
    Upgrade the table name locks from semi-exclusive to exclusive locks.
1166
  */
1167
  for (TABLE_LIST *table= table_list; table; table= table->next_global)
1168
  {
1169
    if (table->table)
1170
      table->table->open_placeholder= 1;
1171
  }
1172
  return FALSE;
1173
}
1174
1175
1176
/**
1177
  Test is 'table' is protected by an exclusive name lock.
1178
1179
  @param[in] thd        The current thread handler
1180
  @param[in] table_list Table container containing the single table to be
1181
                        tested
1182
1183
  @note Needs to be protected by LOCK_open mutex.
1184
1185
  @return Error status code
1186
    @retval TRUE Table is protected
1187
    @retval FALSE Table is not protected
1188
*/
1189
1190
bool
1191
is_table_name_exclusively_locked_by_this_thread(THD *thd,
1192
                                                TABLE_LIST *table_list)
1193
{
1194
  char  key[MAX_DBKEY_LENGTH];
1195
  uint  key_length;
1196
1197
  key_length= create_table_def_key(thd, key, table_list, 0);
1198
1199
  return is_table_name_exclusively_locked_by_this_thread(thd, (uchar *)key,
1200
                                                         key_length);
1201
}
1202
1203
1204
/**
1205
  Test is 'table key' is protected by an exclusive name lock.
1206
1207
  @param[in] thd        The current thread handler.
1208
  @param[in] key
1209
  @param[in] key_length
1210
1211
  @note Needs to be protected by LOCK_open mutex
1212
1213
  @retval TRUE Table is protected
1214
  @retval FALSE Table is not protected
1215
 */
1216
1217
bool
1218
is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
1219
                                                int key_length)
1220
{
1221
  HASH_SEARCH_STATE state;
1222
  TABLE *table;
1223
1224
  for (table= (TABLE*) hash_first(&open_cache, key,
1225
                                  key_length, &state);
1226
       table ;
1227
       table= (TABLE*) hash_next(&open_cache, key,
1228
                                 key_length, &state))
1229
  {
1230
    if (table->in_use == thd &&
1231
        table->open_placeholder == 1 &&
1232
        table->s->version == 0)
1233
      return TRUE;
1234
  }
1235
1236
  return FALSE;
1237
}
1238
1239
/**
1240
  Unlock all tables in list with a name lock.
1241
1242
  @param
1243
    thd			Thread handle
1244
  @param
1245
    table_list		Names of tables to unlock
1246
  @param
1247
    last_table		Don't unlock any tables after this one.
1248
			        (default 0, which will unlock all tables)
1249
1250
  @note
1251
    One must have a lock on LOCK_open when calling this.
1252
1253
  @note
1254
    This function will broadcast refresh signals to inform other threads
1255
    that the name locks are removed.
1256
1257
  @retval
1258
    0	ok
1259
  @retval
1260
    1	Fatal error (end of memory ?)
1261
*/
1262
1263
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
1264
			TABLE_LIST *last_table)
1265
{
1266
  DBUG_ENTER("unlock_table_names");
1267
  for (TABLE_LIST *table= table_list;
1268
       table != last_table;
1269
       table= table->next_local)
1270
    unlock_table_name(thd,table);
1271
  broadcast_refresh();
1272
  DBUG_VOID_RETURN;
1273
}
1274
1275
1276
static void print_lock_error(int error, const char *table)
1277
{
1278
  int textno;
1279
  DBUG_ENTER("print_lock_error");
1280
1281
  switch (error) {
1282
  case HA_ERR_LOCK_WAIT_TIMEOUT:
1283
    textno=ER_LOCK_WAIT_TIMEOUT;
1284
    break;
1285
  case HA_ERR_READ_ONLY_TRANSACTION:
1286
    textno=ER_READ_ONLY_TRANSACTION;
1287
    break;
1288
  case HA_ERR_LOCK_DEADLOCK:
1289
    textno=ER_LOCK_DEADLOCK;
1290
    break;
1291
  case HA_ERR_WRONG_COMMAND:
1292
    textno=ER_ILLEGAL_HA;
1293
    break;
1294
  default:
1295
    textno=ER_CANT_LOCK;
1296
    break;
1297
  }
1298
1299
  if ( textno == ER_ILLEGAL_HA )
1300
    my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table);
1301
  else
1302
    my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error);
1303
1304
  DBUG_VOID_RETURN;
1305
}
1306
1307
1308
/****************************************************************************
1309
  Handling of global read locks
1310
1311
  Taking the global read lock is TWO steps (2nd step is optional; without
1312
  it, COMMIT of existing transactions will be allowed):
1313
  lock_global_read_lock() THEN make_global_read_lock_block_commit().
1314
1315
  The global locks are handled through the global variables:
1316
  global_read_lock
1317
    count of threads which have the global read lock (i.e. have completed at
1318
    least the first step above)
1319
  global_read_lock_blocks_commit
1320
    count of threads which have the global read lock and block
1321
    commits (i.e. are in or have completed the second step above)
1322
  waiting_for_read_lock
1323
    count of threads which want to take a global read lock but cannot
1324
  protect_against_global_read_lock
1325
    count of threads which have set protection against global read lock.
1326
1327
  access to them is protected with a mutex LOCK_global_read_lock
1328
1329
  (XXX: one should never take LOCK_open if LOCK_global_read_lock is
1330
  taken, otherwise a deadlock may occur. Other mutexes could be a
1331
  problem too - grep the code for global_read_lock if you want to use
1332
  any other mutex here) Also one must not hold LOCK_open when calling
1333
  wait_if_global_read_lock(). When the thread with the global read lock
1334
  tries to close its tables, it needs to take LOCK_open in
1335
  close_thread_table().
1336
1337
  How blocking of threads by global read lock is achieved: that's
1338
  advisory. Any piece of code which should be blocked by global read lock must
1339
  be designed like this:
1340
  - call to wait_if_global_read_lock(). When this returns 0, no global read
1341
  lock is owned; if argument abort_on_refresh was 0, none can be obtained.
1342
  - job
1343
  - if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
1344
  allow other threads to get the global read lock. I.e. removal of the
1345
  protection.
1346
  (Note: it's a bit like an implementation of rwlock).
1347
1348
  [ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
1349
  no better descriptive way ]
1350
1351
  Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
1352
  to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
1353
  log.
1354
1355
  Why getting the global read lock is two steps and not one. Because FLUSH
1356
  TABLES WITH READ LOCK needs to insert one other step between the two:
1357
  flushing tables. So the order is
1358
  1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
1359
  all new updates)
1360
  2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
1361
  currently opened and being updated to close (so it's possible that there is
1362
  a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
1363
  READ LOCK is, too).
1364
  3) make_global_read_lock_block_commit().
1365
  If we have merged 1) and 3) into 1), we would have had this deadlock:
1366
  imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
1367
  table t.
1368
  thd1: SELECT * FROM t FOR UPDATE;
1369
  thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
1370
  thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
1371
  table instance of thd2
1372
  thd1: COMMIT; # blocked by thd3.
1373
  thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
1374
1375
  Note that we need to support that one thread does
1376
  FLUSH TABLES WITH READ LOCK; and then COMMIT;
1377
  (that's what innobackup does, for some good reason).
1378
  So in this exceptional case the COMMIT should not be blocked by the FLUSH
1379
  TABLES WITH READ LOCK.
1380
1381
****************************************************************************/
1382
1383
volatile uint global_read_lock=0;
1384
volatile uint global_read_lock_blocks_commit=0;
1385
static volatile uint protect_against_global_read_lock=0;
1386
static volatile uint waiting_for_read_lock=0;
1387
1388
#define GOT_GLOBAL_READ_LOCK               1
1389
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
1390
1391
bool lock_global_read_lock(THD *thd)
1392
{
1393
  DBUG_ENTER("lock_global_read_lock");
1394
1395
  if (!thd->global_read_lock)
1396
  {
1397
    const char *old_message;
1398
    (void) pthread_mutex_lock(&LOCK_global_read_lock);
1399
    old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1400
                                "Waiting to get readlock");
1401
    DBUG_PRINT("info",
1402
	       ("waiting_for: %d  protect_against: %d",
1403
		waiting_for_read_lock, protect_against_global_read_lock));
1404
1405
    waiting_for_read_lock++;
1406
    while (protect_against_global_read_lock && !thd->killed)
1407
      pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1408
    waiting_for_read_lock--;
1409
    if (thd->killed)
1410
    {
1411
      thd->exit_cond(old_message);
1412
      DBUG_RETURN(1);
1413
    }
1414
    thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
1415
    global_read_lock++;
1416
    thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1417
  }
1418
  /*
1419
    We DON'T set global_read_lock_blocks_commit now, it will be set after
1420
    tables are flushed (as the present function serves for FLUSH TABLES WITH
1421
    READ LOCK only). Doing things in this order is necessary to avoid
1422
    deadlocks (we must allow COMMIT until all tables are closed; we should not
1423
    forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
1424
    UPDATE and one does FLUSH TABLES WITH READ LOCK).
1425
  */
1426
  DBUG_RETURN(0);
1427
}
1428
1429
1430
void unlock_global_read_lock(THD *thd)
1431
{
1432
  uint tmp;
1433
  DBUG_ENTER("unlock_global_read_lock");
1434
  DBUG_PRINT("info",
1435
             ("global_read_lock: %u  global_read_lock_blocks_commit: %u",
1436
              global_read_lock, global_read_lock_blocks_commit));
1437
1438
  pthread_mutex_lock(&LOCK_global_read_lock);
1439
  tmp= --global_read_lock;
1440
  if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1441
    --global_read_lock_blocks_commit;
1442
  pthread_mutex_unlock(&LOCK_global_read_lock);
1443
  /* Send the signal outside the mutex to avoid a context switch */
1444
  if (!tmp)
1445
  {
1446
    DBUG_PRINT("signal", ("Broadcasting COND_global_read_lock"));
1447
    pthread_cond_broadcast(&COND_global_read_lock);
1448
  }
1449
  thd->global_read_lock= 0;
1450
1451
  DBUG_VOID_RETURN;
1452
}
1453
1454
#define must_wait (global_read_lock &&                             \
1455
                   (is_not_commit ||                               \
1456
                    global_read_lock_blocks_commit))
1457
1458
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
1459
                              bool is_not_commit)
1460
{
1461
  const char *old_message= NULL;
1462
  bool result= 0, need_exit_cond;
1463
  DBUG_ENTER("wait_if_global_read_lock");
1464
1465
  /*
1466
    Assert that we do not own LOCK_open. If we would own it, other
1467
    threads could not close their tables. This would make a pretty
1468
    deadlock.
1469
  */
1470
  safe_mutex_assert_not_owner(&LOCK_open);
1471
1472
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
1473
  if ((need_exit_cond= must_wait))
1474
  {
1475
    if (thd->global_read_lock)		// This thread had the read locks
1476
    {
1477
      if (is_not_commit)
1478
        my_message(ER_CANT_UPDATE_WITH_READLOCK,
1479
                   ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
1480
      (void) pthread_mutex_unlock(&LOCK_global_read_lock);
1481
      /*
1482
        We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
1483
        This allowance is needed to not break existing versions of innobackup
1484
        which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
1485
      */
1486
      DBUG_RETURN(is_not_commit);
1487
    }
1488
    old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1489
				"Waiting for release of readlock");
1490
    while (must_wait && ! thd->killed &&
1491
	   (!abort_on_refresh || thd->version == refresh_version))
1492
    {
1493
      DBUG_PRINT("signal", ("Waiting for COND_global_read_lock"));
1494
      (void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1495
      DBUG_PRINT("signal", ("Got COND_global_read_lock"));
1496
    }
1497
    if (thd->killed)
1498
      result=1;
1499
  }
1500
  if (!abort_on_refresh && !result)
1501
    protect_against_global_read_lock++;
1502
  /*
1503
    The following is only true in case of a global read locks (which is rare)
1504
    and if old_message is set
1505
  */
1506
  if (unlikely(need_exit_cond))
1507
    thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1508
  else
1509
    pthread_mutex_unlock(&LOCK_global_read_lock);
1510
  DBUG_RETURN(result);
1511
}
1512
1513
1514
void start_waiting_global_read_lock(THD *thd)
1515
{
1516
  bool tmp;
1517
  DBUG_ENTER("start_waiting_global_read_lock");
1518
  if (unlikely(thd->global_read_lock))
1519
    DBUG_VOID_RETURN;
1520
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
1521
  tmp= (!--protect_against_global_read_lock &&
1522
        (waiting_for_read_lock || global_read_lock_blocks_commit));
1523
  (void) pthread_mutex_unlock(&LOCK_global_read_lock);
1524
  if (tmp)
1525
    pthread_cond_broadcast(&COND_global_read_lock);
1526
  DBUG_VOID_RETURN;
1527
}
1528
1529
1530
bool make_global_read_lock_block_commit(THD *thd)
1531
{
1532
  bool error;
1533
  const char *old_message;
1534
  DBUG_ENTER("make_global_read_lock_block_commit");
1535
  /*
1536
    If we didn't succeed lock_global_read_lock(), or if we already suceeded
1537
    make_global_read_lock_block_commit(), do nothing.
1538
  */
1539
  if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
1540
    DBUG_RETURN(0);
1541
  pthread_mutex_lock(&LOCK_global_read_lock);
1542
  /* increment this BEFORE waiting on cond (otherwise race cond) */
1543
  global_read_lock_blocks_commit++;
1544
  /* For testing we set up some blocking, to see if we can be killed */
1545
  DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1546
                  protect_against_global_read_lock++;);
1547
  old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1548
                               "Waiting for all running commits to finish");
1549
  while (protect_against_global_read_lock && !thd->killed)
1550
    pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1551
  DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1552
                  protect_against_global_read_lock--;);
1553
  if ((error= test(thd->killed)))
1554
    global_read_lock_blocks_commit--; // undo what we did
1555
  else
1556
    thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1557
  thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1558
  DBUG_RETURN(error);
1559
}
1560
1561
1562
/**
1563
  Broadcast COND_refresh and COND_global_read_lock.
1564
1565
    Due to a bug in a threading library it could happen that a signal
1566
    did not reach its target. A condition for this was that the same
1567
    condition variable was used with different mutexes in
1568
    pthread_cond_wait(). Some time ago we changed LOCK_open to
1569
    LOCK_global_read_lock in global read lock handling. So COND_refresh
1570
    was used with LOCK_open and LOCK_global_read_lock.
1571
1572
    We did now also change from COND_refresh to COND_global_read_lock
1573
    in global read lock handling. But now it is necessary to signal
1574
    both conditions at the same time.
1575
1576
  @note
1577
    When signalling COND_global_read_lock within the global read lock
1578
    handling, it is not necessary to also signal COND_refresh.
1579
*/
1580
1581
void broadcast_refresh(void)
1582
{
1583
  VOID(pthread_cond_broadcast(&COND_refresh));
1584
  VOID(pthread_cond_broadcast(&COND_global_read_lock));
1585
}
1586
1587
1588
/*
1589
  Try to get transactional table locks for the tables in the list.
1590
1591
  SYNOPSIS
1592
    try_transactional_lock()
1593
      thd                       Thread handle
1594
      table_list                List of tables to lock
1595
1596
  DESCRIPTION
1597
    This is called if transactional table locks are requested for all
1598
    tables in table_list and no non-transactional locks pre-exist.
1599
1600
  RETURN
1601
    0                   OK. All tables are transactional locked.
1602
    1                   Error: must fall back to non-transactional locks.
1603
    -1                  Error: no recovery possible.
1604
*/
1605
1606
int try_transactional_lock(THD *thd, TABLE_LIST *table_list)
1607
{
1608
  uint          dummy_counter;
1609
  int           error;
1610
  int           result= 0;
1611
  DBUG_ENTER("try_transactional_lock");
1612
1613
  /* Need to open the tables to be able to access engine methods. */
1614
  if (open_tables(thd, &table_list, &dummy_counter, 0))
1615
  {
1616
    /* purecov: begin tested */
1617
    DBUG_PRINT("lock_info", ("aborting, open_tables failed"));
1618
    DBUG_RETURN(-1);
1619
    /* purecov: end */
1620
  }
1621
1622
  /* Required by InnoDB. */
1623
  thd->in_lock_tables= TRUE;
1624
1625
  if ((error= set_handler_table_locks(thd, table_list, TRUE)))
1626
  {
1627
    /*
1628
      Not all transactional locks could be taken. If the error was
1629
      something else but "unsupported by storage engine", abort the
1630
      execution of this statement.
1631
    */
1632
    if (error != HA_ERR_WRONG_COMMAND)
1633
    {
1634
      DBUG_PRINT("lock_info", ("aborting, lock_table failed"));
1635
      result= -1;
1636
      goto err;
1637
    }
1638
    /*
1639
      Fall back to non-transactional locks because transactional locks
1640
      are unsupported by a storage engine. No need to unlock the
1641
      successfully taken transactional locks. They go away at end of
1642
      transaction anyway.
1643
    */
1644
    DBUG_PRINT("lock_info", ("fall back to non-trans lock: no SE support"));
1645
    result= 1;
1646
  }
1647
1648
 err:
1649
  /* We need to explicitly commit if autocommit mode is active. */
1650
  (void) ha_autocommit_or_rollback(thd, 0);
1651
  /* Close the tables. The locks (if taken) persist in the storage engines. */
1652
  close_tables_for_reopen(thd, &table_list);
1653
  thd->in_lock_tables= FALSE;
1654
  DBUG_PRINT("lock_info", ("result: %d", result));
1655
  DBUG_RETURN(result);
1656
}
1657
1658
1659
/*
1660
  Check if lock method conversion was done and was allowed.
1661
1662
  SYNOPSIS
1663
    check_transactional_lock()
1664
      thd                       Thread handle
1665
      table_list                List of tables to lock
1666
1667
  DESCRIPTION
1668
1669
    Lock method conversion can be done during parsing if one of the
1670
    locks is non-transactional. It can also happen if non-transactional
1671
    table locks exist when the statement is executed or if a storage
1672
    engine does not support transactional table locks.
1673
1674
    Check if transactional table locks have been converted to
1675
    non-transactional and if this was allowed. In a running transaction
1676
    or in strict mode lock method conversion is not allowed - report an
1677
    error. Otherwise it is allowed - issue a warning.
1678
1679
  RETURN
1680
    0                   OK. Proceed with non-transactional locks.
1681
    -1                  Error: Lock conversion is prohibited.
1682
*/
1683
1684
int check_transactional_lock(THD *thd, TABLE_LIST *table_list)
1685
{
1686
  TABLE_LIST    *tlist;
1687
  int           result= 0;
1688
  char          warn_buff[MYSQL_ERRMSG_SIZE];
1689
  DBUG_ENTER("check_transactional_lock");
1690
1691
  for (tlist= table_list; tlist; tlist= tlist->next_global)
1692
  {
1693
    DBUG_PRINT("lock_info", ("checking table: '%s'", tlist->table_name));
1694
1695
    /*
1696
      Unfortunately we cannot use tlist->placeholder() here. This method
1697
      returns TRUE if the table is not open, which is always the case
1698
      here. Whenever the definition of TABLE_LIST::placeholder() is
1699
      changed, probably this condition needs to be changed too.
1700
    */
1701
    if (tlist->derived || tlist->schema_table || !tlist->lock_transactional)
1702
    {
1703
      DBUG_PRINT("lock_info", ("skipping placeholder: %d  transactional: %d",
1704
                               tlist->placeholder(),
1705
                               tlist->lock_transactional));
1706
      continue;
1707
    }
1708
1709
    /* We must not convert the lock method in strict mode. */
1710
    {
1711
      my_error(ER_NO_AUTO_CONVERT_LOCK_STRICT, MYF(0),
1712
               tlist->alias ? tlist->alias : tlist->table_name);
1713
      result= -1;
1714
      continue;
1715
    }
1716
1717
    /* We must not convert the lock method within an active transaction. */
1718
    if (thd->active_transaction())
1719
    {
1720
      my_error(ER_NO_AUTO_CONVERT_LOCK_TRANSACTION, MYF(0),
1721
               tlist->alias ? tlist->alias : tlist->table_name);
1722
      result= -1;
1723
      continue;
1724
    }
1725
1726
    /* Warn about the conversion. */
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
1727
    snprintf(warn_buff, sizeof(warn_buff), ER(ER_WARN_AUTO_CONVERT_LOCK),
1728
             tlist->alias ? tlist->alias : tlist->table_name);
1 by brian
clean slate
1729
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1730
                 ER_WARN_AUTO_CONVERT_LOCK, warn_buff);
1731
  }
1732
1733
  DBUG_PRINT("lock_info", ("result: %d", result));
1734
  DBUG_RETURN(result);
1735
}
1736
1737
1738
/*
1739
  Set table locks in the table handler.
1740
1741
  SYNOPSIS
1742
    set_handler_table_locks()
1743
      thd                       Thread handle
1744
      table_list                List of tables to lock
1745
      transactional             If to lock transactional or non-transactional
1746
1747
  RETURN
1748
    0                   OK.
1749
    != 0                Error code from handler::lock_table().
1750
*/
1751
1752
int set_handler_table_locks(THD *thd, TABLE_LIST *table_list,
1753
                            bool transactional)
1754
{
1755
  TABLE_LIST    *tlist;
1756
  int           error= 0;
1757
  DBUG_ENTER("set_handler_table_locks");
1758
  DBUG_PRINT("lock_info", ("transactional: %d", transactional));
1759
1760
  for (tlist= table_list; tlist; tlist= tlist->next_global)
1761
  {
1762
    int lock_type;
1763
    int lock_timeout= -1; /* Use default for non-transactional locks. */
1764
1765
    if (tlist->placeholder())
1766
      continue;
1767
1768
    DBUG_ASSERT((tlist->lock_type == TL_READ) ||
1769
                (tlist->lock_type == TL_READ_NO_INSERT) ||
1770
                (tlist->lock_type == TL_WRITE_DEFAULT) ||
1771
                (tlist->lock_type == TL_WRITE) ||
1772
                (tlist->lock_type == TL_WRITE_LOW_PRIORITY));
1773
1774
    /*
1775
      Every tlist object has a proper lock_type set. Even if it came in
1776
      the list as a base table from a view only.
1777
    */
1778
    lock_type= ((tlist->lock_type <= TL_READ_NO_INSERT) ?
1779
                HA_LOCK_IN_SHARE_MODE : HA_LOCK_IN_EXCLUSIVE_MODE);
1780
1781
    if (transactional)
1782
    {
1783
      /*
1784
        The lock timeout is not set if this table belongs to a view. We
1785
        need to take it from the top-level view. After this loop
1786
        iteration, lock_timeout is not needed any more. Not even if the
1787
        locks are converted to non-transactional locks later.
1788
        Non-transactional locks do not support a lock_timeout.
1789
      */
1790
      lock_timeout= tlist->top_table()->lock_timeout;
1791
      DBUG_PRINT("lock_info",
1792
                 ("table: '%s'  tlist==top_table: %d  lock_timeout: %d",
1793
                  tlist->table_name, tlist==tlist->top_table(), lock_timeout));
1794
1795
      /*
1796
        For warning/error reporting we need to set the intended lock
1797
        method in the TABLE_LIST object. It will be used later by
1798
        check_transactional_lock(). The lock method is not set if this
1799
        table belongs to a view. We can safely set it to transactional
1800
        locking here. Even for non-view tables. This function is not
1801
        called if non-transactional locking was requested for any
1802
        object.
1803
      */
1804
      tlist->lock_transactional= TRUE;
1805
    }
1806
1807
    /*
1808
      Because we need to set the lock method (see above) for all
1809
      involved tables, we cannot break the loop on an error.
1810
      But we do not try more locks after the first error.
1811
      However, for non-transactional locking handler::lock_table() is
1812
      a hint only. So we continue to call it for other tables.
1813
    */
1814
    if (!error || !transactional)
1815
    {
1816
      error= tlist->table->file->lock_table(thd, lock_type, lock_timeout);
1817
      if (error && transactional && (error != HA_ERR_WRONG_COMMAND))
1818
        tlist->table->file->print_error(error, MYF(0));
1819
    }
1820
  }
1821
1822
  DBUG_RETURN(error);
1823
}
1824
1825
1826
/**
1827
  @} (end of group Locking)
1828
*/