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