~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/lock.cc

Fixed depend problem

Show diffs side-by-side

added added

removed removed

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