~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/lock.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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