~vlad-lesin/percona-server/mysql-5.0.33-original

« back to all changes in this revision

Viewing changes to libmysqld/lock.cc

  • Committer: Vlad Lesin
  • Date: 2012-07-31 09:21:34 UTC
  • Revision ID: vladislav.lesin@percona.com-20120731092134-zfodx022b7992wsi
VirginĀ 5.0.33

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
 
6
   (at your option) any later version.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; if not, write to the Free Software
 
15
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
16
 
 
17
 
 
18
/* locking functions for mysql */
 
19
/*
 
20
  Because of the new concurrent inserts, we must first get external locks
 
21
  before getting internal locks.  If we do it in the other order, the status
 
22
  information is not up to date when called from the lock handler.
 
23
 
 
24
  GENERAL DESCRIPTION OF LOCKING
 
25
 
 
26
  When not using LOCK TABLES:
 
27
 
 
28
  - For each SQL statement mysql_lock_tables() is called for all involved
 
29
    tables.
 
30
    - mysql_lock_tables() will call
 
31
      table_handler->external_lock(thd,locktype) for each table.
 
32
      This is followed by a call to thr_multi_lock() for all tables.
 
33
 
 
34
  - When statement is done, we call mysql_unlock_tables().
 
35
    This will call thr_multi_unlock() followed by
 
36
    table_handler->external_lock(thd, F_UNLCK) for each table.
 
37
 
 
38
  - Note that mysql_unlock_tables() may be called several times as
 
39
    MySQL in some cases can free some tables earlier than others.
 
40
 
 
41
  - The above is true both for normal and temporary tables.
 
42
 
 
43
  - Temporary non transactional tables are never passed to thr_multi_lock()
 
44
    and we never call external_lock(thd, F_UNLOCK) on these.
 
45
 
 
46
  When using LOCK TABLES:
 
47
 
 
48
  - LOCK TABLE will call mysql_lock_tables() for all tables.
 
49
    mysql_lock_tables() will call
 
50
    table_handler->external_lock(thd,locktype) for each table.
 
51
    This is followed by a call to thr_multi_lock() for all tables.
 
52
 
 
53
  - For each statement, we will call table_handler->start_stmt(THD)
 
54
    to inform the table handler that we are using the table.
 
55
 
 
56
    The tables used can only be tables used in LOCK TABLES or a
 
57
    temporary table.
 
58
 
 
59
  - When statement is done, we will call ha_commit_stmt(thd);
 
60
 
 
61
  - When calling UNLOCK TABLES we call mysql_unlock_tables() for all
 
62
    tables used in LOCK TABLES
 
63
 
 
64
TODO:
 
65
  Change to use my_malloc() ONLY when using LOCK TABLES command or when
 
66
  we are forced to use mysql_lock_merge.
 
67
*/
 
68
 
 
69
#include "mysql_priv.h"
 
70
#include <hash.h>
 
71
#include <assert.h>
 
72
 
 
73
extern HASH open_cache;
 
74
 
 
75
/* flags for get_lock_data */
 
76
#define GET_LOCK_UNLOCK         1
 
77
#define GET_LOCK_STORE_LOCKS    2
 
78
 
 
79
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
 
80
                                 uint flags, TABLE **write_locked);
 
81
static void reset_lock_data(MYSQL_LOCK *sql_lock);
 
82
static int lock_external(THD *thd, TABLE **table,uint count);
 
83
static int unlock_external(THD *thd, TABLE **table,uint count);
 
84
static void print_lock_error(int error, const char *);
 
85
 
 
86
/*
 
87
  Lock tables.
 
88
 
 
89
  SYNOPSIS
 
90
    mysql_lock_tables()
 
91
    thd                         The current thread.
 
92
    tables                      An array of pointers to the tables to lock.
 
93
    count                       The number of tables to lock.
 
94
    flags                       Options:
 
95
      MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK      Ignore a global read lock
 
96
      MYSQL_LOCK_IGNORE_FLUSH                 Ignore a flush tables.
 
97
      MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN        Instead of reopening altered
 
98
                                              or dropped tables by itself,
 
99
                                              mysql_lock_tables() should
 
100
                                              notify upper level and rely
 
101
                                              on caller doing this.
 
102
    need_reopen                 Out parameter, TRUE if some tables were altered
 
103
                                or deleted and should be reopened by caller.
 
104
 
 
105
  RETURN
 
106
    A lock structure pointer on success.
 
107
    NULL on error or if some tables should be reopen.
 
108
*/
 
109
 
 
110
/* Map the return value of thr_lock to an error from errmsg.txt */
 
111
static int thr_lock_errno_to_mysql[]=
 
112
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
 
113
 
 
114
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
 
115
                              uint flags, bool *need_reopen)
 
116
{
 
117
  MYSQL_LOCK *sql_lock;
 
118
  TABLE *write_lock_used;
 
119
  int rc;
 
120
  DBUG_ENTER("mysql_lock_tables");
 
121
 
 
122
  *need_reopen= FALSE;
 
123
 
 
124
  for (;;)
 
125
  {
 
126
    if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS,
 
127
                                   &write_lock_used)))
 
128
      break;
 
129
 
 
130
    if (global_read_lock && write_lock_used &&
 
131
        ! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
 
132
    {
 
133
      /*
 
134
        Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
 
135
        Wait until the lock is gone
 
136
      */
 
137
      if (wait_if_global_read_lock(thd, 1, 1))
 
138
      {
 
139
        /* Clear the lock type of all lock data to avoid reusage. */
 
140
        reset_lock_data(sql_lock);
 
141
        my_free((gptr) sql_lock,MYF(0));
 
142
        sql_lock=0;
 
143
        break;
 
144
      }
 
145
      if (thd->version != refresh_version)
 
146
      {
 
147
        /* Clear the lock type of all lock data to avoid reusage. */
 
148
        reset_lock_data(sql_lock);
 
149
        my_free((gptr) sql_lock,MYF(0));
 
150
        goto retry;
 
151
      }
 
152
    }
 
153
 
 
154
    thd->proc_info="System lock";
 
155
    if (lock_external(thd, tables, count))
 
156
    {
 
157
      /* Clear the lock type of all lock data to avoid reusage. */
 
158
      reset_lock_data(sql_lock);
 
159
      my_free((gptr) sql_lock,MYF(0));
 
160
      sql_lock=0;
 
161
      break;
 
162
    }
 
163
    thd->proc_info="Table lock";
 
164
    thd->locked=1;
 
165
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
 
166
    memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
 
167
           sql_lock->lock_count * sizeof(*sql_lock->locks));
 
168
    /* Lock on the copied half of the lock data array. */
 
169
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
 
170
                                                     sql_lock->lock_count,
 
171
                                                     sql_lock->lock_count,
 
172
                                                     thd->lock_id)];
 
173
    if (rc > 1)                                 /* a timeout or a deadlock */
 
174
    {
 
175
      my_error(rc, MYF(0));
 
176
      my_free((gptr) sql_lock,MYF(0));
 
177
      sql_lock= 0;
 
178
      break;
 
179
    }
 
180
    else if (rc == 1)                           /* aborted */
 
181
    {
 
182
      thd->some_tables_deleted=1;               // Try again
 
183
      sql_lock->lock_count= 0;                  // Locks are already freed
 
184
    }
 
185
    else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
 
186
    {
 
187
      thd->locked=0;
 
188
      break;
 
189
    }
 
190
    else if (!thd->open_tables)
 
191
    {
 
192
      // Only using temporary tables, no need to unlock
 
193
      thd->some_tables_deleted=0;
 
194
      thd->locked=0;
 
195
      break;
 
196
    }
 
197
    thd->proc_info=0;
 
198
 
 
199
    /* some table was altered or deleted. reopen tables marked deleted */
 
200
    mysql_unlock_tables(thd,sql_lock);
 
201
    thd->locked=0;
 
202
retry:
 
203
    sql_lock=0;
 
204
    if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
 
205
    {
 
206
      *need_reopen= TRUE;
 
207
      break;
 
208
    }
 
209
    if (wait_for_tables(thd))
 
210
      break;                                    // Couldn't open tables
 
211
  }
 
212
  thd->proc_info=0;
 
213
  if (thd->killed)
 
214
  {
 
215
    thd->send_kill_message();
 
216
    if (sql_lock)
 
217
    {
 
218
      mysql_unlock_tables(thd,sql_lock);
 
219
      sql_lock=0;
 
220
    }
 
221
  }
 
222
 
 
223
  thd->lock_time();
 
224
  DBUG_RETURN (sql_lock);
 
225
}
 
226
 
 
227
 
 
228
static int lock_external(THD *thd, TABLE **tables, uint count)
 
229
{
 
230
  reg1 uint i;
 
231
  int lock_type,error;
 
232
  DBUG_ENTER("lock_external");
 
233
 
 
234
  for (i=1 ; i <= count ; i++, tables++)
 
235
  {
 
236
    DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
 
237
    lock_type=F_WRLCK;                          /* Lock exclusive */
 
238
    if ((*tables)->db_stat & HA_READ_ONLY ||
 
239
        ((*tables)->reginfo.lock_type >= TL_READ &&
 
240
         (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
 
241
      lock_type=F_RDLCK;
 
242
 
 
243
    if ((error=(*tables)->file->external_lock(thd,lock_type)))
 
244
    {
 
245
      print_lock_error(error, (*tables)->file->table_type());
 
246
      for (; i-- ; tables--)
 
247
      {
 
248
        (*tables)->file->external_lock(thd, F_UNLCK);
 
249
        (*tables)->current_lock=F_UNLCK;
 
250
      }
 
251
      DBUG_RETURN(error);
 
252
    }
 
253
    else
 
254
    {
 
255
      (*tables)->db_stat &= ~ HA_BLOCK_LOCK;
 
256
      (*tables)->current_lock= lock_type;
 
257
    }
 
258
  }
 
259
  DBUG_RETURN(0);
 
260
}
 
261
 
 
262
 
 
263
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
 
264
{
 
265
  DBUG_ENTER("mysql_unlock_tables");
 
266
  if (sql_lock->lock_count)
 
267
    thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
 
268
  if (sql_lock->table_count)
 
269
    VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count));
 
270
  my_free((gptr) sql_lock,MYF(0));
 
271
  DBUG_VOID_RETURN;
 
272
}
 
273
 
 
274
/*
 
275
  Unlock some of the tables locked by mysql_lock_tables
 
276
  This will work even if get_lock_data fails (next unlock will free all)
 
277
  */
 
278
 
 
279
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count)
 
280
{
 
281
  MYSQL_LOCK *sql_lock;
 
282
  TABLE *write_lock_used;
 
283
  if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK,
 
284
                               &write_lock_used)))
 
285
    mysql_unlock_tables(thd, sql_lock);
 
286
}
 
287
 
 
288
 
 
289
/*
 
290
** unlock all tables locked for read.
 
291
*/
 
292
 
 
293
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
 
294
{
 
295
  uint i,found;
 
296
  DBUG_ENTER("mysql_unlock_read_tables");
 
297
 
 
298
  /* Move all write locks first */
 
299
  THR_LOCK_DATA **lock=sql_lock->locks;
 
300
  for (i=found=0 ; i < sql_lock->lock_count ; i++)
 
301
  {
 
302
    if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
 
303
    {
 
304
      swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]);
 
305
      lock++;
 
306
      found++;
 
307
    }
 
308
  }
 
309
  /* unlock the read locked tables */
 
310
  if (i != found)
 
311
  {
 
312
    thr_multi_unlock(lock,i-found);
 
313
    sql_lock->lock_count= found;
 
314
  }
 
315
 
 
316
  /* Then do the same for the external locks */
 
317
  /* Move all write locked tables first */
 
318
  TABLE **table=sql_lock->table;
 
319
  for (i=found=0 ; i < sql_lock->table_count ; i++)
 
320
  {
 
321
    DBUG_ASSERT(sql_lock->table[i]->lock_position == i);
 
322
    if ((uint) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
 
323
    {
 
324
      swap_variables(TABLE *, *table, sql_lock->table[i]);
 
325
      table++;
 
326
      found++;
 
327
    }
 
328
  }
 
329
  /* Unlock all read locked tables */
 
330
  if (i != found)
 
331
  {
 
332
    VOID(unlock_external(thd,table,i-found));
 
333
    sql_lock->table_count=found;
 
334
  }
 
335
  /* Fix the lock positions in TABLE */
 
336
  table= sql_lock->table;
 
337
  found= 0;
 
338
  for (i= 0; i < sql_lock->table_count; i++)
 
339
  {
 
340
    TABLE *tbl= *table;
 
341
    tbl->lock_position= table - sql_lock->table;
 
342
    tbl->lock_data_start= found;
 
343
    found+= tbl->lock_count;
 
344
    table++;
 
345
  }
 
346
  DBUG_VOID_RETURN;
 
347
}
 
348
 
 
349
 
 
350
 
 
351
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table)
 
352
{
 
353
  mysql_unlock_some_tables(thd, &table,1);
 
354
  if (locked)
 
355
  {
 
356
    reg1 uint i;
 
357
    for (i=0; i < locked->table_count; i++)
 
358
    {
 
359
      if (locked->table[i] == table)
 
360
      {
 
361
        uint  j, removed_locks, old_tables;
 
362
        TABLE *tbl;
 
363
        uint lock_data_end;
 
364
 
 
365
        DBUG_ASSERT(table->lock_position == i);
 
366
 
 
367
        /* Decrement table_count in advance, making below expressions easier */
 
368
        old_tables= --locked->table_count;
 
369
 
 
370
        /* The table has 'removed_locks' lock data elements in locked->locks */
 
371
        removed_locks= table->lock_count;
 
372
 
 
373
        /* Move down all table pointers above 'i'. */
 
374
        bmove((char*) (locked->table+i),
 
375
              (char*) (locked->table+i+1),
 
376
              (old_tables - i) * sizeof(TABLE*));
 
377
 
 
378
        lock_data_end= table->lock_data_start + table->lock_count;
 
379
        /* Move down all lock data pointers above 'table->lock_data_end-1' */
 
380
        bmove((char*) (locked->locks + table->lock_data_start),
 
381
              (char*) (locked->locks + lock_data_end),
 
382
              (locked->lock_count - lock_data_end) *
 
383
              sizeof(THR_LOCK_DATA*));
 
384
 
 
385
        /*
 
386
          Fix moved table elements.
 
387
          lock_position is the index in the 'locked->table' array,
 
388
          it must be fixed by one.
 
389
          table->lock_data_start is pointer to the lock data for this table
 
390
          in the 'locked->locks' array, they must be fixed by 'removed_locks',
 
391
          the lock data count of the removed table.
 
392
        */
 
393
        for (j= i ; j < old_tables; j++)
 
394
        {
 
395
          tbl= locked->table[j];
 
396
          tbl->lock_position--;
 
397
          DBUG_ASSERT(tbl->lock_position == j);
 
398
          tbl->lock_data_start-= removed_locks;
 
399
        }
 
400
 
 
401
        /* Finally adjust lock_count. */
 
402
        locked->lock_count-= removed_locks;
 
403
        break;
 
404
      }
 
405
    }
 
406
  }
 
407
}
 
408
 
 
409
/* abort all other threads waiting to get lock in table */
 
410
 
 
411
void mysql_lock_abort(THD *thd, TABLE *table)
 
412
{
 
413
  MYSQL_LOCK *locked;
 
414
  TABLE *write_lock_used;
 
415
  if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
 
416
                             &write_lock_used)))
 
417
  {
 
418
    for (uint i=0; i < locked->lock_count; i++)
 
419
      thr_abort_locks(locked->locks[i]->lock);
 
420
    my_free((gptr) locked,MYF(0));
 
421
  }
 
422
}
 
423
 
 
424
 
 
425
/*
 
426
  Abort one thread / table combination
 
427
 
 
428
  SYNOPSIS
 
429
    mysql_lock_abort_for_thread()
 
430
    thd         Thread handler
 
431
    table       Table that should be removed from lock queue
 
432
 
 
433
  RETURN
 
434
    0  Table was not locked by another thread
 
435
    1  Table was locked by at least one other thread
 
436
*/
 
437
 
 
438
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
 
439
{
 
440
  MYSQL_LOCK *locked;
 
441
  TABLE *write_lock_used;
 
442
  bool result= FALSE;
 
443
  DBUG_ENTER("mysql_lock_abort_for_thread");
 
444
 
 
445
  if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
 
446
                             &write_lock_used)))
 
447
  {
 
448
    for (uint i=0; i < locked->lock_count; i++)
 
449
    {
 
450
      if (thr_abort_locks_for_thread(locked->locks[i]->lock,
 
451
                                     table->in_use->real_id))
 
452
        result= TRUE;
 
453
    }
 
454
    my_free((gptr) locked,MYF(0));
 
455
  }
 
456
  DBUG_RETURN(result);
 
457
}
 
458
 
 
459
 
 
460
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
 
461
{
 
462
  MYSQL_LOCK *sql_lock;
 
463
  TABLE **table, **end_table;
 
464
  DBUG_ENTER("mysql_lock_merge");
 
465
 
 
466
  if (!(sql_lock= (MYSQL_LOCK*)
 
467
        my_malloc(sizeof(*sql_lock)+
 
468
                  sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
 
469
                  sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
 
470
    DBUG_RETURN(0);                             // Fatal error
 
471
  sql_lock->lock_count=a->lock_count+b->lock_count;
 
472
  sql_lock->table_count=a->table_count+b->table_count;
 
473
  sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
 
474
  sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count);
 
475
  memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
 
476
  memcpy(sql_lock->locks+a->lock_count,b->locks,
 
477
         b->lock_count*sizeof(*b->locks));
 
478
  memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
 
479
  memcpy(sql_lock->table+a->table_count,b->table,
 
480
         b->table_count*sizeof(*b->table));
 
481
 
 
482
  /*
 
483
    Now adjust lock_position and lock_data_start for all objects that was
 
484
    moved in 'b' (as there is now all objects in 'a' before these).
 
485
  */
 
486
  for (table= sql_lock->table + a->table_count,
 
487
         end_table= table + b->table_count;
 
488
       table < end_table;
 
489
       table++)
 
490
  {
 
491
    (*table)->lock_position+=   a->table_count;
 
492
    (*table)->lock_data_start+= a->lock_count;
 
493
  }
 
494
 
 
495
  /* Delete old, not needed locks */
 
496
  my_free((gptr) a,MYF(0));
 
497
  my_free((gptr) b,MYF(0));
 
498
  DBUG_RETURN(sql_lock);
 
499
}
 
500
 
 
501
 
 
502
/*
 
503
  Find duplicate lock in tables.
 
504
 
 
505
  SYNOPSIS
 
506
    mysql_lock_have_duplicate()
 
507
    thd                         The current thread.
 
508
    needle                      The table to check for duplicate lock.
 
509
    haystack                    The list of tables to search for the dup lock.
 
510
 
 
511
  NOTE
 
512
    This is mainly meant for MERGE tables in INSERT ... SELECT
 
513
    situations. The 'real', underlying tables can be found only after
 
514
    the MERGE tables are opened. This function assumes that the tables are
 
515
    already locked.
 
516
 
 
517
    Temporary tables are ignored here like they are ignored in
 
518
    get_lock_data(). If we allow two opens on temporary tables later,
 
519
    both functions should be checked.
 
520
 
 
521
  RETURN
 
522
    NULL        No duplicate lock found.
 
523
    ! NULL      First table from 'haystack' that matches a lock on 'needle'.
 
524
*/
 
525
 
 
526
TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
 
527
                                      TABLE_LIST *haystack)
 
528
{
 
529
  MYSQL_LOCK            *mylock;
 
530
  TABLE                 **lock_tables;
 
531
  TABLE                 *table;
 
532
  TABLE                 *table2;
 
533
  THR_LOCK_DATA         **lock_locks;
 
534
  THR_LOCK_DATA         **table_lock_data;
 
535
  THR_LOCK_DATA         **end_data;
 
536
  THR_LOCK_DATA         **lock_data2;
 
537
  THR_LOCK_DATA         **end_data2;
 
538
  DBUG_ENTER("mysql_lock_have_duplicate");
 
539
 
 
540
  /*
 
541
    Table may not be defined for derived or view tables.
 
542
    Table may not be part of a lock for delayed operations.
 
543
  */
 
544
  if (! (table= needle->table) || ! table->lock_count)
 
545
    goto end;
 
546
 
 
547
  /* A temporary table does not have locks. */
 
548
  if (table->s->tmp_table == TMP_TABLE)
 
549
    goto end;
 
550
 
 
551
  /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
 
552
  if (! (mylock= thd->lock ? thd->lock : thd->locked_tables))
 
553
    goto end;
 
554
 
 
555
  /* If we have less than two tables, we cannot have duplicates. */
 
556
  if (mylock->table_count < 2)
 
557
    goto end;
 
558
 
 
559
  lock_locks=  mylock->locks;
 
560
  lock_tables= mylock->table;
 
561
 
 
562
  /* Prepare table related variables that don't change in loop. */
 
563
  DBUG_ASSERT((table->lock_position < mylock->table_count) &&
 
564
              (table == lock_tables[table->lock_position]));
 
565
  table_lock_data= lock_locks + table->lock_data_start;
 
566
  end_data= table_lock_data + table->lock_count;
 
567
 
 
568
  for (; haystack; haystack= haystack->next_global)
 
569
  {
 
570
    if (haystack->placeholder() || haystack->schema_table)
 
571
      continue;
 
572
    table2= haystack->table;
 
573
    if (table2->s->tmp_table == TMP_TABLE)
 
574
      continue;
 
575
 
 
576
    /* All tables in list must be in lock. */
 
577
    DBUG_ASSERT((table2->lock_position < mylock->table_count) &&
 
578
                (table2 == lock_tables[table2->lock_position]));
 
579
 
 
580
    for (lock_data2=  lock_locks + table2->lock_data_start,
 
581
           end_data2= lock_data2 + table2->lock_count;
 
582
         lock_data2 < end_data2;
 
583
         lock_data2++)
 
584
    {
 
585
      THR_LOCK_DATA **lock_data;
 
586
      THR_LOCK *lock2= (*lock_data2)->lock;
 
587
 
 
588
      for (lock_data= table_lock_data;
 
589
           lock_data < end_data;
 
590
           lock_data++)
 
591
      {
 
592
        if ((*lock_data)->lock == lock2)
 
593
        {
 
594
          DBUG_PRINT("info", ("haystack match: '%s'", haystack->table_name));
 
595
          DBUG_RETURN(haystack);
 
596
        }
 
597
      }
 
598
    }
 
599
  }
 
600
 
 
601
 end:
 
602
  DBUG_PRINT("info", ("no duplicate found"));
 
603
  DBUG_RETURN(NULL);
 
604
}
 
605
 
 
606
 
 
607
        /* unlock a set of external */
 
608
 
 
609
static int unlock_external(THD *thd, TABLE **table,uint count)
 
610
{
 
611
  int error,error_code;
 
612
  DBUG_ENTER("unlock_external");
 
613
 
 
614
  error_code=0;
 
615
  do
 
616
  {
 
617
    if ((*table)->current_lock != F_UNLCK)
 
618
    {
 
619
      (*table)->current_lock = F_UNLCK;
 
620
      if ((error=(*table)->file->external_lock(thd, F_UNLCK)))
 
621
      {
 
622
        error_code=error;
 
623
        print_lock_error(error_code, (*table)->file->table_type());
 
624
      }
 
625
    }
 
626
    table++;
 
627
  } while (--count);
 
628
  DBUG_RETURN(error_code);
 
629
}
 
630
 
 
631
 
 
632
/*
 
633
  Get lock structures from table structs and initialize locks
 
634
 
 
635
  SYNOPSIS
 
636
    get_lock_data()
 
637
    thd                 Thread handler
 
638
    table_ptr           Pointer to tables that should be locks
 
639
    flags               One of:
 
640
                        GET_LOCK_UNLOCK:      If we should send TL_IGNORE to
 
641
                                              store lock
 
642
                        GET_LOCK_STORE_LOCKS: Store lock info in TABLE
 
643
    write_lock_used     Store pointer to last table with WRITE_ALLOW_WRITE
 
644
*/
 
645
 
 
646
 
 
647
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
 
648
                                 uint flags, TABLE **write_lock_used)
 
649
{
 
650
  uint i,tables,lock_count;
 
651
  MYSQL_LOCK *sql_lock;
 
652
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
 
653
  TABLE **to, **table_buf;
 
654
  DBUG_ENTER("get_lock_data");
 
655
 
 
656
  *write_lock_used=0;
 
657
  for (i=tables=lock_count=0 ; i < count ; i++)
 
658
  {
 
659
    if (table_ptr[i]->s->tmp_table != TMP_TABLE)
 
660
    {
 
661
      tables+=table_ptr[i]->file->lock_count();
 
662
      lock_count++;
 
663
    }
 
664
    /*
 
665
      To be able to open and lock for reading system tables like 'mysql.proc',
 
666
      when we already have some tables opened and locked, and avoid deadlocks
 
667
      we have to disallow write-locking of these tables with any other tables.
 
668
    */
 
669
    if (table_ptr[i]->s->system_table &&
 
670
        table_ptr[i]->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE &&
 
671
        count != 1)
 
672
    {
 
673
      my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table_ptr[i]->s->db,
 
674
               table_ptr[i]->s->table_name);
 
675
      return 0;
 
676
    }
 
677
  }
 
678
 
 
679
  /*
 
680
    Allocating twice the number of pointers for lock data for use in
 
681
    thr_mulit_lock(). This function reorders the lock data, but cannot
 
682
    update the table values. So the second part of the array is copied
 
683
    from the first part immediately before calling thr_multi_lock().
 
684
  */
 
685
  if (!(sql_lock= (MYSQL_LOCK*)
 
686
        my_malloc(sizeof(*sql_lock) +
 
687
                  sizeof(THR_LOCK_DATA*) * tables * 2 +
 
688
                  sizeof(table_ptr) * lock_count,
 
689
                  MYF(0))))
 
690
    DBUG_RETURN(0);
 
691
  locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
 
692
  to= table_buf= sql_lock->table= (TABLE**) (locks + tables * 2);
 
693
  sql_lock->table_count=lock_count;
 
694
  sql_lock->lock_count=tables;
 
695
 
 
696
  for (i=0 ; i < count ; i++)
 
697
  {
 
698
    TABLE *table;
 
699
    enum thr_lock_type lock_type;
 
700
 
 
701
    if ((table=table_ptr[i])->s->tmp_table == TMP_TABLE)
 
702
      continue;
 
703
    lock_type= table->reginfo.lock_type;
 
704
    if (lock_type >= TL_WRITE_ALLOW_WRITE)
 
705
    {
 
706
      *write_lock_used=table;
 
707
      if (table->db_stat & HA_READ_ONLY)
 
708
      {
 
709
        my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
 
710
        /* Clear the lock type of the lock data that are stored already. */
 
711
        sql_lock->lock_count= locks - sql_lock->locks;
 
712
        reset_lock_data(sql_lock);
 
713
        my_free((gptr) sql_lock,MYF(0));
 
714
        DBUG_RETURN(0);
 
715
      }
 
716
    }
 
717
    THR_LOCK_DATA **org_locks = locks;
 
718
    locks_start= locks;
 
719
    locks= table->file->store_lock(thd, locks,
 
720
                                   (flags & GET_LOCK_UNLOCK) ? TL_IGNORE :
 
721
                                   lock_type);
 
722
    if (flags & GET_LOCK_STORE_LOCKS)
 
723
    {
 
724
      table->lock_position=   (uint) (to - table_buf);
 
725
      table->lock_data_start= (uint) (locks_start - locks_buf);
 
726
      table->lock_count=      (uint) (locks - locks_start);
 
727
    }
 
728
    *to++= table;
 
729
    if (locks)
 
730
      for ( ; org_locks != locks ; org_locks++)
 
731
        (*org_locks)->debug_print_param= (void *) table;
 
732
  }
 
733
  DBUG_RETURN(sql_lock);
 
734
}
 
735
 
 
736
 
 
737
/*
 
738
  Reset lock type in lock data.
 
739
 
 
740
  SYNOPSIS
 
741
    reset_lock_data()
 
742
      sql_lock                  The MySQL lock.
 
743
 
 
744
  DESCRIPTION
 
745
 
 
746
    After a locking error we want to quit the locking of the table(s).
 
747
    The test case in the bug report for Bug #18544 has the following
 
748
    cases: 1. Locking error in lock_external() due to InnoDB timeout.
 
749
    2. Locking error in get_lock_data() due to missing write permission.
 
750
    3. Locking error in wait_if_global_read_lock() due to lock conflict.
 
751
 
 
752
    In all these cases we have already set the lock type into the lock
 
753
    data of the open table(s). If the table(s) are in the open table
 
754
    cache, they could be reused with the non-zero lock type set. This
 
755
    could lead to ignoring a different lock type with the next lock.
 
756
 
 
757
    Clear the lock type of all lock data. This ensures that the next
 
758
    lock request will set its lock type properly.
 
759
 
 
760
  RETURN
 
761
    void
 
762
*/
 
763
 
 
764
static void reset_lock_data(MYSQL_LOCK *sql_lock)
 
765
{
 
766
  THR_LOCK_DATA **ldata;
 
767
  THR_LOCK_DATA **ldata_end;
 
768
 
 
769
  for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
 
770
       ldata < ldata_end;
 
771
       ldata++)
 
772
  {
 
773
    /* Reset lock type. */
 
774
    (*ldata)->type= TL_UNLOCK;
 
775
  }
 
776
}
 
777
 
 
778
 
 
779
/*****************************************************************************
 
780
  Lock table based on the name.
 
781
  This is used when we need total access to a closed, not open table
 
782
*****************************************************************************/
 
783
 
 
784
/*
 
785
  Lock and wait for the named lock.
 
786
 
 
787
  SYNOPSIS
 
788
    lock_and_wait_for_table_name()
 
789
    thd                 Thread handler
 
790
    table_list          Lock first table in this list
 
791
 
 
792
 
 
793
  NOTES
 
794
    Works together with global read lock.
 
795
 
 
796
  RETURN
 
797
    0   ok
 
798
    1   error
 
799
*/
 
800
 
 
801
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
 
802
{
 
803
  int lock_retcode;
 
804
  int error= -1;
 
805
  DBUG_ENTER("lock_and_wait_for_table_name");
 
806
 
 
807
  if (wait_if_global_read_lock(thd, 0, 1))
 
808
    DBUG_RETURN(1);
 
809
  VOID(pthread_mutex_lock(&LOCK_open));
 
810
  if ((lock_retcode = lock_table_name(thd, table_list)) < 0)
 
811
    goto end;
 
812
  if (lock_retcode && wait_for_locked_table_names(thd, table_list))
 
813
  {
 
814
    unlock_table_name(thd, table_list);
 
815
    goto end;
 
816
  }
 
817
  error=0;
 
818
 
 
819
end:
 
820
  pthread_mutex_unlock(&LOCK_open);
 
821
  start_waiting_global_read_lock(thd);
 
822
  DBUG_RETURN(error);
 
823
}
 
824
 
 
825
 
 
826
/*
 
827
  Put a not open table with an old refresh version in the table cache.
 
828
 
 
829
  SYNPOSIS
 
830
    lock_table_name()
 
831
    thd                 Thread handler
 
832
    table_list          Lock first table in this list
 
833
 
 
834
  WARNING
 
835
    If you are going to update the table, you should use
 
836
    lock_and_wait_for_table_name instead of this function as this works
 
837
    together with 'FLUSH TABLES WITH READ LOCK'
 
838
 
 
839
  NOTES
 
840
    This will force any other threads that uses the table to release it
 
841
    as soon as possible.
 
842
 
 
843
  REQUIREMENTS
 
844
    One must have a lock on LOCK_open !
 
845
 
 
846
  RETURN:
 
847
    < 0 error
 
848
    == 0 table locked
 
849
    > 0  table locked, but someone is using it
 
850
*/
 
851
 
 
852
int lock_table_name(THD *thd, TABLE_LIST *table_list)
 
853
{
 
854
  TABLE *table;
 
855
  char  key[MAX_DBKEY_LENGTH];
 
856
  char *db= table_list->db;
 
857
  int table_in_key_offset;
 
858
  uint  key_length;
 
859
  HASH_SEARCH_STATE state;
 
860
  DBUG_ENTER("lock_table_name");
 
861
  DBUG_PRINT("enter",("db: %s  name: %s", db, table_list->table_name));
 
862
 
 
863
  safe_mutex_assert_owner(&LOCK_open);
 
864
 
 
865
  table_in_key_offset= strmov(key, db) - key + 1;
 
866
  key_length= (uint)(strmov(key + table_in_key_offset, table_list->table_name)
 
867
                     - key) + 1;
 
868
 
 
869
 
 
870
  /* Only insert the table if we haven't insert it already */
 
871
  for (table=(TABLE*) hash_first(&open_cache, (byte*)key, key_length, &state);
 
872
       table ;
 
873
       table = (TABLE*) hash_next(&open_cache, (byte*)key, key_length, &state))
 
874
    if (table->in_use == thd)
 
875
      DBUG_RETURN(0);
 
876
 
 
877
  /*
 
878
    Create a table entry with the right key and with an old refresh version
 
879
    Note that we must use my_malloc() here as this is freed by the table
 
880
    cache
 
881
  */
 
882
  if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
 
883
                                  MYF(MY_WME | MY_ZEROFILL))))
 
884
    DBUG_RETURN(-1);
 
885
  table->s= &table->share_not_to_be_used;
 
886
  memcpy((table->s->table_cache_key= (char*) (table+1)), key, key_length);
 
887
  table->s->db= table->s->table_cache_key;
 
888
  table->s->table_name= table->s->table_cache_key + table_in_key_offset;
 
889
  table->s->key_length=key_length;
 
890
  table->in_use=thd;
 
891
  table->locked_by_name=1;
 
892
  table_list->table=table;
 
893
 
 
894
  if (my_hash_insert(&open_cache, (byte*) table))
 
895
  {
 
896
    my_free((gptr) table,MYF(0));
 
897
    DBUG_RETURN(-1);
 
898
  }
 
899
  
 
900
  /* Return 1 if table is in use */
 
901
  DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name,
 
902
                                           RTFC_NO_FLAG)));
 
903
}
 
904
 
 
905
 
 
906
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
 
907
{
 
908
  if (table_list->table)
 
909
  {
 
910
    hash_delete(&open_cache, (byte*) table_list->table);
 
911
    broadcast_refresh();
 
912
  }
 
913
}
 
914
 
 
915
 
 
916
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
 
917
{
 
918
  for (; table_list ; table_list=table_list->next_local)
 
919
  {
 
920
    if (table_list->table && table_is_used(table_list->table,0))
 
921
      return 1;
 
922
  }
 
923
  return 0;                                     // All tables are locked
 
924
}
 
925
 
 
926
 
 
927
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
 
928
{
 
929
  bool result=0;
 
930
  DBUG_ENTER("wait_for_locked_table_names");
 
931
  safe_mutex_assert_owner(&LOCK_open);
 
932
 
 
933
  while (locked_named_table(thd,table_list))
 
934
  {
 
935
    if (thd->killed)
 
936
    {
 
937
      result=1;
 
938
      break;
 
939
    }
 
940
    wait_for_refresh(thd);
 
941
    pthread_mutex_lock(&LOCK_open);
 
942
  }
 
943
  DBUG_RETURN(result);
 
944
}
 
945
 
 
946
 
 
947
/*
 
948
  Lock all tables in list with a name lock
 
949
 
 
950
  SYNOPSIS
 
951
    lock_table_names()
 
952
    thd                 Thread handle
 
953
    table_list          Names of tables to lock
 
954
 
 
955
  NOTES
 
956
    If you are just locking one table, you should use
 
957
    lock_and_wait_for_table_name().
 
958
 
 
959
  REQUIREMENTS
 
960
    One must have a lock on LOCK_open when calling this
 
961
 
 
962
  RETURN
 
963
    0   ok
 
964
    1   Fatal error (end of memory ?)
 
965
*/
 
966
 
 
967
bool lock_table_names(THD *thd, TABLE_LIST *table_list)
 
968
{
 
969
  bool got_all_locks=1;
 
970
  TABLE_LIST *lock_table;
 
971
 
 
972
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
 
973
  {
 
974
    int got_lock;
 
975
    if ((got_lock=lock_table_name(thd,lock_table)) < 0)
 
976
      goto end;                                 // Fatal error
 
977
    if (got_lock)
 
978
      got_all_locks=0;                          // Someone is using table
 
979
  }
 
980
 
 
981
  /* If some table was in use, wait until we got the lock */
 
982
  if (!got_all_locks && wait_for_locked_table_names(thd, table_list))
 
983
    goto end;
 
984
  return 0;
 
985
 
 
986
end:
 
987
  unlock_table_names(thd, table_list, lock_table);
 
988
  return 1;
 
989
}
 
990
 
 
991
 
 
992
/*
 
993
  Unlock all tables in list with a name lock
 
994
 
 
995
  SYNOPSIS
 
996
    unlock_table_names()
 
997
    thd                 Thread handle
 
998
    table_list          Names of tables to unlock
 
999
    last_table          Don't unlock any tables after this one.
 
1000
                        (default 0, which will unlock all tables)
 
1001
 
 
1002
  NOTES
 
1003
    One must have a lock on LOCK_open when calling this.
 
1004
    This function will broadcast refresh signals to inform other threads
 
1005
    that the name locks are removed.
 
1006
 
 
1007
  RETURN
 
1008
    0   ok
 
1009
    1   Fatal error (end of memory ?)
 
1010
*/
 
1011
 
 
1012
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
 
1013
                        TABLE_LIST *last_table)
 
1014
{
 
1015
  for (TABLE_LIST *table= table_list;
 
1016
       table != last_table;
 
1017
       table= table->next_local)
 
1018
    unlock_table_name(thd,table);
 
1019
  broadcast_refresh();
 
1020
}
 
1021
 
 
1022
 
 
1023
static void print_lock_error(int error, const char *table)
 
1024
{
 
1025
  int textno;
 
1026
  DBUG_ENTER("print_lock_error");
 
1027
 
 
1028
  switch (error) {
 
1029
  case HA_ERR_LOCK_WAIT_TIMEOUT:
 
1030
    textno=ER_LOCK_WAIT_TIMEOUT;
 
1031
    break;
 
1032
  case HA_ERR_READ_ONLY_TRANSACTION:
 
1033
    textno=ER_READ_ONLY_TRANSACTION;
 
1034
    break;
 
1035
  case HA_ERR_LOCK_DEADLOCK:
 
1036
    textno=ER_LOCK_DEADLOCK;
 
1037
    break;
 
1038
  case HA_ERR_WRONG_COMMAND:
 
1039
    textno=ER_ILLEGAL_HA;
 
1040
    break;
 
1041
  default:
 
1042
    textno=ER_CANT_LOCK;
 
1043
    break;
 
1044
  }
 
1045
 
 
1046
  if ( textno == ER_ILLEGAL_HA )
 
1047
    my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table);
 
1048
  else
 
1049
    my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error);
 
1050
 
 
1051
  DBUG_VOID_RETURN;
 
1052
}
 
1053
 
 
1054
 
 
1055
/****************************************************************************
 
1056
  Handling of global read locks
 
1057
 
 
1058
  Taking the global read lock is TWO steps (2nd step is optional; without
 
1059
  it, COMMIT of existing transactions will be allowed):
 
1060
  lock_global_read_lock() THEN make_global_read_lock_block_commit().
 
1061
 
 
1062
  The global locks are handled through the global variables:
 
1063
  global_read_lock
 
1064
    count of threads which have the global read lock (i.e. have completed at
 
1065
    least the first step above)
 
1066
  global_read_lock_blocks_commit
 
1067
    count of threads which have the global read lock and block
 
1068
    commits (i.e. are in or have completed the second step above)
 
1069
  waiting_for_read_lock
 
1070
    count of threads which want to take a global read lock but cannot
 
1071
  protect_against_global_read_lock
 
1072
    count of threads which have set protection against global read lock.
 
1073
 
 
1074
  access to them is protected with a mutex LOCK_global_read_lock
 
1075
 
 
1076
  (XXX: one should never take LOCK_open if LOCK_global_read_lock is
 
1077
  taken, otherwise a deadlock may occur. Other mutexes could be a
 
1078
  problem too - grep the code for global_read_lock if you want to use
 
1079
  any other mutex here) Also one must not hold LOCK_open when calling
 
1080
  wait_if_global_read_lock(). When the thread with the global read lock
 
1081
  tries to close its tables, it needs to take LOCK_open in
 
1082
  close_thread_table().
 
1083
 
 
1084
  How blocking of threads by global read lock is achieved: that's
 
1085
  advisory. Any piece of code which should be blocked by global read lock must
 
1086
  be designed like this:
 
1087
  - call to wait_if_global_read_lock(). When this returns 0, no global read
 
1088
  lock is owned; if argument abort_on_refresh was 0, none can be obtained.
 
1089
  - job
 
1090
  - if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
 
1091
  allow other threads to get the global read lock. I.e. removal of the
 
1092
  protection.
 
1093
  (Note: it's a bit like an implementation of rwlock).
 
1094
 
 
1095
  [ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
 
1096
  no better descriptive way ]
 
1097
 
 
1098
  Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
 
1099
  to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
 
1100
  log.
 
1101
 
 
1102
  Why getting the global read lock is two steps and not one. Because FLUSH
 
1103
  TABLES WITH READ LOCK needs to insert one other step between the two:
 
1104
  flushing tables. So the order is
 
1105
  1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
 
1106
  all new updates)
 
1107
  2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
 
1108
  currently opened and being updated to close (so it's possible that there is
 
1109
  a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
 
1110
  READ LOCK is, too).
 
1111
  3) make_global_read_lock_block_commit().
 
1112
  If we have merged 1) and 3) into 1), we would have had this deadlock:
 
1113
  imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
 
1114
  table t.
 
1115
  thd1: SELECT * FROM t FOR UPDATE;
 
1116
  thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
 
1117
  thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
 
1118
  table instance of thd2
 
1119
  thd1: COMMIT; # blocked by thd3.
 
1120
  thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
 
1121
 
 
1122
  Note that we need to support that one thread does
 
1123
  FLUSH TABLES WITH READ LOCK; and then COMMIT;
 
1124
  (that's what innobackup does, for some good reason).
 
1125
  So in this exceptional case the COMMIT should not be blocked by the FLUSH
 
1126
  TABLES WITH READ LOCK.
 
1127
 
 
1128
****************************************************************************/
 
1129
 
 
1130
volatile uint global_read_lock=0;
 
1131
volatile uint global_read_lock_blocks_commit=0;
 
1132
static volatile uint protect_against_global_read_lock=0;
 
1133
static volatile uint waiting_for_read_lock=0;
 
1134
 
 
1135
#define GOT_GLOBAL_READ_LOCK               1
 
1136
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
 
1137
 
 
1138
bool lock_global_read_lock(THD *thd)
 
1139
{
 
1140
  DBUG_ENTER("lock_global_read_lock");
 
1141
 
 
1142
  if (!thd->global_read_lock)
 
1143
  {
 
1144
    const char *old_message;
 
1145
    (void) pthread_mutex_lock(&LOCK_global_read_lock);
 
1146
    old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
 
1147
                                "Waiting to get readlock");
 
1148
    DBUG_PRINT("info",
 
1149
               ("waiting_for: %d  protect_against: %d",
 
1150
                waiting_for_read_lock, protect_against_global_read_lock));
 
1151
 
 
1152
    waiting_for_read_lock++;
 
1153
    while (protect_against_global_read_lock && !thd->killed)
 
1154
      pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
 
1155
    waiting_for_read_lock--;
 
1156
    if (thd->killed)
 
1157
    {
 
1158
      thd->exit_cond(old_message);
 
1159
      DBUG_RETURN(1);
 
1160
    }
 
1161
    thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
 
1162
    global_read_lock++;
 
1163
    thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1164
  }
 
1165
  /*
 
1166
    We DON'T set global_read_lock_blocks_commit now, it will be set after
 
1167
    tables are flushed (as the present function serves for FLUSH TABLES WITH
 
1168
    READ LOCK only). Doing things in this order is necessary to avoid
 
1169
    deadlocks (we must allow COMMIT until all tables are closed; we should not
 
1170
    forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
 
1171
    UPDATE and one does FLUSH TABLES WITH READ LOCK).
 
1172
  */
 
1173
  DBUG_RETURN(0);
 
1174
}
 
1175
 
 
1176
 
 
1177
void unlock_global_read_lock(THD *thd)
 
1178
{
 
1179
  uint tmp;
 
1180
  DBUG_ENTER("unlock_global_read_lock");
 
1181
  DBUG_PRINT("info",
 
1182
             ("global_read_lock: %u  global_read_lock_blocks_commit: %u",
 
1183
              global_read_lock, global_read_lock_blocks_commit));
 
1184
 
 
1185
  pthread_mutex_lock(&LOCK_global_read_lock);
 
1186
  tmp= --global_read_lock;
 
1187
  if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
 
1188
    --global_read_lock_blocks_commit;
 
1189
  pthread_mutex_unlock(&LOCK_global_read_lock);
 
1190
  /* Send the signal outside the mutex to avoid a context switch */
 
1191
  if (!tmp)
 
1192
  {
 
1193
    DBUG_PRINT("signal", ("Broadcasting COND_global_read_lock"));
 
1194
    pthread_cond_broadcast(&COND_global_read_lock);
 
1195
  }
 
1196
  thd->global_read_lock= 0;
 
1197
 
 
1198
  DBUG_VOID_RETURN;
 
1199
}
 
1200
 
 
1201
#define must_wait (global_read_lock &&                             \
 
1202
                   (is_not_commit ||                               \
 
1203
                    global_read_lock_blocks_commit))
 
1204
 
 
1205
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
 
1206
                              bool is_not_commit)
 
1207
{
 
1208
  const char *old_message;
 
1209
  bool result= 0, need_exit_cond;
 
1210
  DBUG_ENTER("wait_if_global_read_lock");
 
1211
 
 
1212
  LINT_INIT(old_message);
 
1213
  /*
 
1214
    Assert that we do not own LOCK_open. If we would own it, other
 
1215
    threads could not close their tables. This would make a pretty
 
1216
    deadlock.
 
1217
  */
 
1218
  safe_mutex_assert_not_owner(&LOCK_open);
 
1219
 
 
1220
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
 
1221
  if ((need_exit_cond= must_wait))
 
1222
  {
 
1223
    if (thd->global_read_lock)          // This thread had the read locks
 
1224
    {
 
1225
      if (is_not_commit)
 
1226
        my_message(ER_CANT_UPDATE_WITH_READLOCK,
 
1227
                   ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
 
1228
      (void) pthread_mutex_unlock(&LOCK_global_read_lock);
 
1229
      /*
 
1230
        We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
 
1231
        This allowance is needed to not break existing versions of innobackup
 
1232
        which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
 
1233
      */
 
1234
      DBUG_RETURN(is_not_commit);
 
1235
    }
 
1236
    old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
 
1237
                                "Waiting for release of readlock");
 
1238
    while (must_wait && ! thd->killed &&
 
1239
           (!abort_on_refresh || thd->version == refresh_version))
 
1240
    {
 
1241
      DBUG_PRINT("signal", ("Waiting for COND_global_read_lock"));
 
1242
      (void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
 
1243
      DBUG_PRINT("signal", ("Got COND_global_read_lock"));
 
1244
    }
 
1245
    if (thd->killed)
 
1246
      result=1;
 
1247
  }
 
1248
  if (!abort_on_refresh && !result)
 
1249
    protect_against_global_read_lock++;
 
1250
  /*
 
1251
    The following is only true in case of a global read locks (which is rare)
 
1252
    and if old_message is set
 
1253
  */
 
1254
  if (unlikely(need_exit_cond))
 
1255
    thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1256
  else
 
1257
    pthread_mutex_unlock(&LOCK_global_read_lock);
 
1258
  DBUG_RETURN(result);
 
1259
}
 
1260
 
 
1261
 
 
1262
void start_waiting_global_read_lock(THD *thd)
 
1263
{
 
1264
  bool tmp;
 
1265
  DBUG_ENTER("start_waiting_global_read_lock");
 
1266
  if (unlikely(thd->global_read_lock))
 
1267
    DBUG_VOID_RETURN;
 
1268
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
 
1269
  tmp= (!--protect_against_global_read_lock &&
 
1270
        (waiting_for_read_lock || global_read_lock_blocks_commit));
 
1271
  (void) pthread_mutex_unlock(&LOCK_global_read_lock);
 
1272
  if (tmp)
 
1273
    pthread_cond_broadcast(&COND_global_read_lock);
 
1274
  DBUG_VOID_RETURN;
 
1275
}
 
1276
 
 
1277
 
 
1278
bool make_global_read_lock_block_commit(THD *thd)
 
1279
{
 
1280
  bool error;
 
1281
  const char *old_message;
 
1282
  DBUG_ENTER("make_global_read_lock_block_commit");
 
1283
  /*
 
1284
    If we didn't succeed lock_global_read_lock(), or if we already suceeded
 
1285
    make_global_read_lock_block_commit(), do nothing.
 
1286
  */
 
1287
  if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
 
1288
    DBUG_RETURN(0);
 
1289
  pthread_mutex_lock(&LOCK_global_read_lock);
 
1290
  /* increment this BEFORE waiting on cond (otherwise race cond) */
 
1291
  global_read_lock_blocks_commit++;
 
1292
  /* For testing we set up some blocking, to see if we can be killed */
 
1293
  DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
 
1294
                  protect_against_global_read_lock++;);
 
1295
  old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
 
1296
                               "Waiting for all running commits to finish");
 
1297
  while (protect_against_global_read_lock && !thd->killed)
 
1298
    pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
 
1299
  DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
 
1300
                  protect_against_global_read_lock--;);
 
1301
  if ((error= test(thd->killed)))
 
1302
    global_read_lock_blocks_commit--; // undo what we did
 
1303
  else
 
1304
    thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
 
1305
  thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1306
  DBUG_RETURN(error);
 
1307
}
 
1308
 
 
1309
 
 
1310
/*
 
1311
  Broadcast COND_refresh and COND_global_read_lock.
 
1312
 
 
1313
  SYNOPSIS
 
1314
    broadcast_refresh()
 
1315
      void                      No parameters.
 
1316
 
 
1317
  DESCRIPTION
 
1318
    Due to a bug in a threading library it could happen that a signal
 
1319
    did not reach its target. A condition for this was that the same
 
1320
    condition variable was used with different mutexes in
 
1321
    pthread_cond_wait(). Some time ago we changed LOCK_open to
 
1322
    LOCK_global_read_lock in global read lock handling. So COND_refresh
 
1323
    was used with LOCK_open and LOCK_global_read_lock.
 
1324
 
 
1325
    We did now also change from COND_refresh to COND_global_read_lock
 
1326
    in global read lock handling. But now it is necessary to signal
 
1327
    both conditions at the same time.
 
1328
 
 
1329
  NOTE
 
1330
    When signalling COND_global_read_lock within the global read lock
 
1331
    handling, it is not necessary to also signal COND_refresh.
 
1332
 
 
1333
  RETURN
 
1334
    void
 
1335
*/
 
1336
 
 
1337
void broadcast_refresh(void)
 
1338
{
 
1339
  VOID(pthread_cond_broadcast(&COND_refresh));
 
1340
  VOID(pthread_cond_broadcast(&COND_global_read_lock));
 
1341
}
 
1342
 
 
1343