~drizzle-trunk/drizzle/development

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