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