~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/lock.cc

Removed dead variable, sorted authors file.

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_GLOBAL_READ_ONLY      Ignore SET GLOBAL READ_ONLY
112
 
      DRIZZLE_LOCK_IGNORE_FLUSH                 Ignore a flush tables.
113
 
      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
114
110
                                              or dropped tables by itself,
115
111
                                              mysql_lock_tables() should
116
112
                                              notify upper level and rely
127
123
static int thr_lock_errno_to_mysql[]=
128
124
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
129
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 __attribute__((__unused__)),
 
135
                            TABLE **tables, uint count,
 
136
                            uint flags __attribute__((__unused__)))
 
137
{
 
138
  uint system_count;
 
139
  uint i;
 
140
 
 
141
  system_count= 0;
 
142
 
 
143
  for (i=0 ; i<count; i++)
 
144
  {
 
145
    TABLE *t= tables[i];
 
146
 
 
147
    /* Protect against 'fake' partially initialized TABLE_SHARE */
 
148
    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
    return(1);
 
166
  }
 
167
 
 
168
  return(0);
 
169
}
 
170
 
130
171
 
131
172
/**
132
173
  Reset lock type in lock data and free.
148
189
        lock request will set its lock type properly.
149
190
*/
150
191
 
151
 
static void reset_lock_data_and_free(DRIZZLE_LOCK **mysql_lock)
 
192
static void reset_lock_data_and_free(MYSQL_LOCK **mysql_lock)
152
193
{
153
 
  DRIZZLE_LOCK *sql_lock= *mysql_lock;
 
194
  MYSQL_LOCK *sql_lock= *mysql_lock;
154
195
  THR_LOCK_DATA **ldata, **ldata_end;
155
196
 
156
197
  /* Clear the lock type of all lock data to avoid reusage. */
161
202
    /* Reset lock type. */
162
203
    (*ldata)->type= TL_UNLOCK;
163
204
  }
164
 
  free((unsigned char*) sql_lock);
 
205
  my_free((uchar*) sql_lock, MYF(0));
165
206
  *mysql_lock= 0;
166
207
}
167
208
 
168
209
 
169
 
DRIZZLE_LOCK *mysql_lock_tables(Session *session, Table **tables, uint32_t count,
170
 
                              uint32_t flags, bool *need_reopen)
 
210
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
 
211
                              uint flags, bool *need_reopen)
171
212
{
172
 
  DRIZZLE_LOCK *sql_lock;
173
 
  Table *write_lock_used;
 
213
  MYSQL_LOCK *sql_lock;
 
214
  TABLE *write_lock_used;
174
215
  int rc;
175
216
 
176
217
  *need_reopen= false;
177
218
 
 
219
  if (mysql_lock_tables_check(thd, tables, count, flags))
 
220
    return (NULL);
 
221
 
178
222
  for (;;)
179
223
  {
180
 
    if (! (sql_lock= get_lock_data(session, tables, count, GET_LOCK_STORE_LOCKS,
 
224
    if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS,
181
225
                                   &write_lock_used)))
182
226
      break;
183
227
 
184
228
    if (global_read_lock && write_lock_used &&
185
 
        ! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK))
 
229
        ! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
186
230
    {
187
231
      /*
188
232
        Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
189
233
        Wait until the lock is gone
190
234
      */
191
 
      if (wait_if_global_read_lock(session, 1, 1))
 
235
      if (wait_if_global_read_lock(thd, 1, 1))
192
236
      {
193
237
        /* Clear the lock type of all lock data to avoid reusage. */
194
238
        reset_lock_data_and_free(&sql_lock);
195
239
        break;
196
240
      }
197
 
      if (session->version != refresh_version)
 
241
      if (thd->version != refresh_version)
198
242
      {
199
243
        /* Clear the lock type of all lock data to avoid reusage. */
200
244
        reset_lock_data_and_free(&sql_lock);
202
246
      }
203
247
    }
204
248
 
205
 
    if (!(flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
 
249
    if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
206
250
        write_lock_used &&
207
251
        opt_readonly &&
208
 
        !session->slave_thread)
 
252
        !thd->slave_thread)
209
253
    {
210
254
      /*
211
255
        Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
216
260
      break;
217
261
    }
218
262
 
219
 
    session->set_proc_info("System lock");
220
 
    if (sql_lock->table_count && lock_external(session, sql_lock->table,
 
263
    thd_proc_info(thd, "System lock");
 
264
    if (sql_lock->table_count && lock_external(thd, sql_lock->table,
221
265
                                               sql_lock->table_count))
222
266
    {
223
267
      /* Clear the lock type of all lock data to avoid reusage. */
224
268
      reset_lock_data_and_free(&sql_lock);
225
269
      break;
226
270
    }
227
 
    session->set_proc_info("Table lock");
 
271
    thd_proc_info(thd, "Table lock");
228
272
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
229
273
    memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
230
274
           sql_lock->lock_count * sizeof(*sql_lock->locks));
232
276
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
233
277
                                                     sql_lock->lock_count,
234
278
                                                     sql_lock->lock_count,
235
 
                                                     session->lock_id)];
 
279
                                                     thd->lock_id)];
236
280
    if (rc > 1)                                 /* a timeout or a deadlock */
237
281
    {
238
282
      if (sql_lock->table_count)
239
 
        unlock_external(session, sql_lock->table, sql_lock->table_count);
 
283
        VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
240
284
      reset_lock_data_and_free(&sql_lock);
241
285
      my_error(rc, MYF(0));
242
286
      break;
243
287
    }
244
288
    else if (rc == 1)                           /* aborted */
245
289
    {
246
 
      session->some_tables_deleted=1;           // Try again
 
290
      thd->some_tables_deleted=1;               // Try again
247
291
      sql_lock->lock_count= 0;                  // Locks are already freed
248
292
      // Fall through: unlock, reset lock data, free and retry
249
293
    }
250
 
    else if (!session->some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
 
294
    else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
251
295
    {
252
296
      /*
253
297
        Thread was killed or lock aborted. Let upper level close all
255
299
      */
256
300
      break;
257
301
    }
258
 
    else if (!session->open_tables)
 
302
    else if (!thd->open_tables)
259
303
    {
260
304
      // Only using temporary tables, no need to unlock
261
 
      session->some_tables_deleted=0;
 
305
      thd->some_tables_deleted=0;
262
306
      break;
263
307
    }
264
 
    session->set_proc_info(0);
 
308
    thd_proc_info(thd, 0);
265
309
 
266
310
    /* going to retry, unlock all tables */
267
311
    if (sql_lock->lock_count)
268
312
        thr_multi_unlock(sql_lock->locks, sql_lock->lock_count);
269
313
 
270
314
    if (sql_lock->table_count)
271
 
      unlock_external(session, sql_lock->table, sql_lock->table_count);
 
315
      VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
272
316
 
273
317
    /*
274
318
      If thr_multi_lock fails it resets lock type for tables, which
277
321
    */
278
322
    reset_lock_data_and_free(&sql_lock);
279
323
retry:
280
 
    if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
 
324
    if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
281
325
    {
282
326
      *need_reopen= true;
283
327
      break;
284
328
    }
285
 
    if (wait_for_tables(session))
 
329
    if (wait_for_tables(thd))
286
330
      break;                                    // Couldn't open tables
287
331
  }
288
 
  session->set_proc_info(0);
289
 
  if (session->killed)
 
332
  thd_proc_info(thd, 0);
 
333
  if (thd->killed)
290
334
  {
291
 
    session->send_kill_message();
 
335
    thd->send_kill_message();
292
336
    if (sql_lock)
293
337
    {
294
 
      mysql_unlock_tables(session,sql_lock);
 
338
      mysql_unlock_tables(thd,sql_lock);
295
339
      sql_lock=0;
296
340
    }
297
341
  }
298
342
 
299
 
  session->set_time_after_lock();
 
343
  thd->set_time_after_lock();
300
344
  return (sql_lock);
301
345
}
302
346
 
303
347
 
304
 
static int lock_external(Session *session, Table **tables, uint32_t count)
 
348
static int lock_external(THD *thd, TABLE **tables, uint count)
305
349
{
306
 
  register uint32_t i;
 
350
  register uint i;
307
351
  int lock_type,error;
308
352
  for (i=1 ; i <= count ; i++, tables++)
309
353
  {
314
358
         (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
315
359
      lock_type=F_RDLCK;
316
360
 
317
 
    if ((error=(*tables)->file->ha_external_lock(session,lock_type)))
 
361
    if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
318
362
    {
319
363
      print_lock_error(error, (*tables)->file->table_type());
320
364
      while (--i)
321
365
      {
322
366
        tables--;
323
 
        (*tables)->file->ha_external_lock(session, F_UNLCK);
 
367
        (*tables)->file->ha_external_lock(thd, F_UNLCK);
324
368
        (*tables)->current_lock=F_UNLCK;
325
369
      }
326
370
      return(error);
335
379
}
336
380
 
337
381
 
338
 
void mysql_unlock_tables(Session *session, DRIZZLE_LOCK *sql_lock)
 
382
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
339
383
{
340
384
  if (sql_lock->lock_count)
341
385
    thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
342
386
  if (sql_lock->table_count)
343
 
    unlock_external(session,sql_lock->table,sql_lock->table_count);
344
 
  free((unsigned char*) sql_lock);
 
387
    VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count));
 
388
  my_free((uchar*) sql_lock,MYF(0));
345
389
  return;
346
390
}
347
391
 
351
395
  This will work even if get_lock_data fails (next unlock will free all)
352
396
*/
353
397
 
354
 
void mysql_unlock_some_tables(Session *session, Table **table,uint32_t count)
 
398
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count)
355
399
{
356
 
  DRIZZLE_LOCK *sql_lock;
357
 
  Table *write_lock_used;
358
 
  if ((sql_lock= get_lock_data(session, table, count, GET_LOCK_UNLOCK,
 
400
  MYSQL_LOCK *sql_lock;
 
401
  TABLE *write_lock_used;
 
402
  if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK,
359
403
                               &write_lock_used)))
360
 
    mysql_unlock_tables(session, sql_lock);
 
404
    mysql_unlock_tables(thd, sql_lock);
361
405
}
362
406
 
363
407
 
365
409
  unlock all tables locked for read.
366
410
*/
367
411
 
368
 
void mysql_unlock_read_tables(Session *session, DRIZZLE_LOCK *sql_lock)
 
412
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
369
413
{
370
 
  uint32_t i,found;
 
414
  uint i,found;
371
415
 
372
416
  /* Move all write locks first */
373
417
  THR_LOCK_DATA **lock=sql_lock->locks;
375
419
  {
376
420
    if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
377
421
    {
378
 
      std::swap(*lock, sql_lock->locks[i]);
 
422
      swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]);
379
423
      lock++;
380
424
      found++;
381
425
    }
389
433
 
390
434
  /* Then do the same for the external locks */
391
435
  /* Move all write locked tables first */
392
 
  Table **table=sql_lock->table;
 
436
  TABLE **table=sql_lock->table;
393
437
  for (i=found=0 ; i < sql_lock->table_count ; i++)
394
438
  {
395
439
    assert(sql_lock->table[i]->lock_position == i);
396
440
    if ((uint) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
397
441
    {
398
 
      std::swap(*table, sql_lock->table[i]);
 
442
      swap_variables(TABLE *, *table, sql_lock->table[i]);
399
443
      table++;
400
444
      found++;
401
445
    }
403
447
  /* Unlock all read locked tables */
404
448
  if (i != found)
405
449
  {
406
 
    unlock_external(session,table,i-found);
 
450
    VOID(unlock_external(thd,table,i-found));
407
451
    sql_lock->table_count=found;
408
452
  }
409
 
  /* Fix the lock positions in Table */
 
453
  /* Fix the lock positions in TABLE */
410
454
  table= sql_lock->table;
411
455
  found= 0;
412
456
  for (i= 0; i < sql_lock->table_count; i++)
413
457
  {
414
 
    Table *tbl= *table;
 
458
    TABLE *tbl= *table;
415
459
    tbl->lock_position= table - sql_lock->table;
416
460
    tbl->lock_data_start= found;
417
461
    found+= tbl->lock_count;
434
478
  unlock_external() we call handler::external_lock(F_UNLCK) only
435
479
  if table->current_lock is not F_UNLCK.
436
480
 
437
 
  @param  session             thread context
 
481
  @param  thd             thread context
438
482
  @param  locked          list of locked tables
439
483
  @param  table           the table to unlock
440
484
  @param  always_unlock   specify explicitly if the legacy side
441
485
                          effect is desired.
442
486
*/
443
487
 
444
 
void mysql_lock_remove(Session *session, DRIZZLE_LOCK *locked,Table *table,
 
488
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
445
489
                       bool always_unlock)
446
490
{
447
491
  if (always_unlock == true)
448
 
    mysql_unlock_some_tables(session, &table, /* table count */ 1);
 
492
    mysql_unlock_some_tables(thd, &table, /* table count */ 1);
449
493
  if (locked)
450
494
  {
451
 
    register uint32_t i;
 
495
    register uint i;
452
496
    for (i=0; i < locked->table_count; i++)
453
497
    {
454
498
      if (locked->table[i] == table)
455
499
      {
456
 
        uint32_t  j, removed_locks, old_tables;
457
 
        Table *tbl;
458
 
        uint32_t lock_data_end;
 
500
        uint  j, removed_locks, old_tables;
 
501
        TABLE *tbl;
 
502
        uint lock_data_end;
459
503
 
460
504
        assert(table->lock_position == i);
461
505
 
462
506
        /* Unlock if not yet unlocked */
463
507
        if (always_unlock == false)
464
 
          mysql_unlock_some_tables(session, &table, /* table count */ 1);
 
508
          mysql_unlock_some_tables(thd, &table, /* table count */ 1);
465
509
 
466
510
        /* Decrement table_count in advance, making below expressions easier */
467
511
        old_tables= --locked->table_count;
470
514
        removed_locks= table->lock_count;
471
515
 
472
516
        /* Move down all table pointers above 'i'. */
473
 
        memmove((locked->table+i), (locked->table+i+1),
474
 
                (old_tables - i) * sizeof(Table*));
 
517
        bmove((char*) (locked->table+i),
 
518
              (char*) (locked->table+i+1),
 
519
              (old_tables - i) * sizeof(TABLE*));
475
520
 
476
521
        lock_data_end= table->lock_data_start + table->lock_count;
477
522
        /* Move down all lock data pointers above 'table->lock_data_end-1' */
478
 
        memmove((locked->locks + table->lock_data_start),
479
 
                (locked->locks + lock_data_end),
480
 
                (locked->lock_count - lock_data_end) *
481
 
                sizeof(THR_LOCK_DATA*));
 
523
        bmove((char*) (locked->locks + table->lock_data_start),
 
524
              (char*) (locked->locks + lock_data_end),
 
525
              (locked->lock_count - lock_data_end) *
 
526
              sizeof(THR_LOCK_DATA*));
482
527
 
483
528
        /*
484
529
          Fix moved table elements.
506
551
 
507
552
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
508
553
 
509
 
void mysql_lock_downgrade_write(Session *session, Table *table,
 
554
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
510
555
                                thr_lock_type new_lock_type)
511
556
{
512
 
  DRIZZLE_LOCK *locked;
513
 
  Table *write_lock_used;
514
 
  if ((locked = get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
 
557
  MYSQL_LOCK *locked;
 
558
  TABLE *write_lock_used;
 
559
  if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
515
560
                              &write_lock_used)))
516
561
  {
517
 
    for (uint32_t i=0; i < locked->lock_count; i++)
 
562
    for (uint i=0; i < locked->lock_count; i++)
518
563
      thr_downgrade_write_lock(locked->locks[i], new_lock_type);
519
 
    free((unsigned char*) locked);
 
564
    my_free((uchar*) locked,MYF(0));
520
565
  }
521
566
}
522
567
 
523
568
 
524
569
/** Abort all other threads waiting to get lock in table. */
525
570
 
526
 
void mysql_lock_abort(Session *session, Table *table, bool upgrade_lock)
 
571
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
527
572
{
528
 
  DRIZZLE_LOCK *locked;
529
 
  Table *write_lock_used;
 
573
  MYSQL_LOCK *locked;
 
574
  TABLE *write_lock_used;
530
575
 
531
 
  if ((locked= get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
 
576
  if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
532
577
                             &write_lock_used)))
533
578
  {
534
 
    for (uint32_t i=0; i < locked->lock_count; i++)
 
579
    for (uint i=0; i < locked->lock_count; i++)
535
580
      thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
536
 
    free((unsigned char*) locked);
 
581
    my_free((uchar*) locked,MYF(0));
537
582
  }
538
583
  return;
539
584
}
542
587
/**
543
588
  Abort one thread / table combination.
544
589
 
545
 
  @param session           Thread handler
 
590
  @param thd       Thread handler
546
591
  @param table     Table that should be removed from lock queue
547
592
 
548
593
  @retval
551
596
    1  Table was locked by at least one other thread
552
597
*/
553
598
 
554
 
bool mysql_lock_abort_for_thread(Session *session, Table *table)
 
599
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
555
600
{
556
 
  DRIZZLE_LOCK *locked;
557
 
  Table *write_lock_used;
 
601
  MYSQL_LOCK *locked;
 
602
  TABLE *write_lock_used;
558
603
  bool result= false;
559
604
 
560
 
  if ((locked= get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
 
605
  if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
561
606
                             &write_lock_used)))
562
607
  {
563
 
    for (uint32_t i=0; i < locked->lock_count; i++)
 
608
    for (uint i=0; i < locked->lock_count; i++)
564
609
    {
565
610
      if (thr_abort_locks_for_thread(locked->locks[i]->lock,
566
611
                                     table->in_use->thread_id))
567
612
        result= true;
568
613
    }
569
 
    free((unsigned char*) locked);
 
614
    my_free((uchar*) locked,MYF(0));
570
615
  }
571
616
  return(result);
572
617
}
573
618
 
574
619
 
575
 
DRIZZLE_LOCK *mysql_lock_merge(DRIZZLE_LOCK *a,DRIZZLE_LOCK *b)
 
620
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
576
621
{
577
 
  DRIZZLE_LOCK *sql_lock;
578
 
  Table **table, **end_table;
 
622
  MYSQL_LOCK *sql_lock;
 
623
  TABLE **table, **end_table;
579
624
 
580
 
  if (!(sql_lock= (DRIZZLE_LOCK*)
581
 
        malloc(sizeof(*sql_lock)+
582
 
               sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
583
 
               sizeof(Table*)*(a->table_count+b->table_count))))
 
625
  if (!(sql_lock= (MYSQL_LOCK*)
 
626
        my_malloc(sizeof(*sql_lock)+
 
627
                  sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
 
628
                  sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
584
629
    return(0);                          // Fatal error
585
630
  sql_lock->lock_count=a->lock_count+b->lock_count;
586
631
  sql_lock->table_count=a->table_count+b->table_count;
587
632
  sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
588
 
  sql_lock->table=(Table**) (sql_lock->locks+sql_lock->lock_count);
 
633
  sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count);
589
634
  memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
590
635
  memcpy(sql_lock->locks+a->lock_count,b->locks,
591
636
         b->lock_count*sizeof(*b->locks));
592
637
  memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
593
638
  memcpy(sql_lock->table+a->table_count,b->table,
594
 
         b->table_count*sizeof(*b->table));
 
639
         b->table_count*sizeof(*b->table));
595
640
 
596
641
  /*
597
642
    Now adjust lock_position and lock_data_start for all objects that was
607
652
  }
608
653
 
609
654
  /* Delete old, not needed locks */
610
 
  free((unsigned char*) a);
611
 
  free((unsigned char*) b);
 
655
  my_free((uchar*) a,MYF(0));
 
656
  my_free((uchar*) b,MYF(0));
612
657
  return(sql_lock);
613
658
}
614
659
 
620
665
  get_lock_data(). If we allow two opens on temporary tables later,
621
666
  both functions should be checked.
622
667
 
623
 
  @param session                 The current thread.
 
668
  @param thd                 The current thread.
624
669
  @param needle              The table to check for duplicate lock.
625
670
  @param haystack            The list of tables to search for the dup lock.
626
671
 
636
681
    !NULL   First table from 'haystack' that matches a lock on 'needle'.
637
682
*/
638
683
 
639
 
TableList *mysql_lock_have_duplicate(Session *session, TableList *needle,
640
 
                                      TableList *haystack)
 
684
TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
 
685
                                      TABLE_LIST *haystack)
641
686
{
642
 
  DRIZZLE_LOCK            *mylock;
643
 
  Table                 **lock_tables;
644
 
  Table                 *table;
645
 
  Table                 *table2;
 
687
  MYSQL_LOCK            *mylock;
 
688
  TABLE                 **lock_tables;
 
689
  TABLE                 *table;
 
690
  TABLE                 *table2;
646
691
  THR_LOCK_DATA         **lock_locks;
647
692
  THR_LOCK_DATA         **table_lock_data;
648
693
  THR_LOCK_DATA         **end_data;
661
706
    goto end;
662
707
 
663
708
  /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
664
 
  if (! (mylock= session->lock ? session->lock : session->locked_tables))
 
709
  if (! (mylock= thd->lock ? thd->lock : thd->locked_tables))
665
710
    goto end;
666
711
 
667
712
  /* If we have less than two tables, we cannot have duplicates. */
716
761
 
717
762
/** Unlock a set of external. */
718
763
 
719
 
static int unlock_external(Session *session, Table **table,uint32_t count)
 
764
static int unlock_external(THD *thd, TABLE **table,uint count)
720
765
{
721
766
  int error,error_code;
722
767
 
726
771
    if ((*table)->current_lock != F_UNLCK)
727
772
    {
728
773
      (*table)->current_lock = F_UNLCK;
729
 
      if ((error=(*table)->file->ha_external_lock(session, F_UNLCK)))
 
774
      if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK)))
730
775
      {
731
776
        error_code=error;
732
777
        print_lock_error(error_code, (*table)->file->table_type());
741
786
/**
742
787
  Get lock structures from table structs and initialize locks.
743
788
 
744
 
  @param session                    Thread handler
 
789
  @param thd                Thread handler
745
790
  @param table_ptr          Pointer to tables that should be locks
746
791
  @param flags              One of:
747
792
           - GET_LOCK_UNLOCK      : If we should send TL_IGNORE to store lock
748
 
           - GET_LOCK_STORE_LOCKS : Store lock info in Table
 
793
           - GET_LOCK_STORE_LOCKS : Store lock info in TABLE
749
794
  @param write_lock_used   Store pointer to last table with WRITE_ALLOW_WRITE
750
795
*/
751
796
 
752
 
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
753
 
                                 uint32_t flags, Table **write_lock_used)
 
797
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
 
798
                                 uint flags, TABLE **write_lock_used)
754
799
{
755
 
  uint32_t i,tables,lock_count;
756
 
  DRIZZLE_LOCK *sql_lock;
 
800
  uint i,tables,lock_count;
 
801
  MYSQL_LOCK *sql_lock;
757
802
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
758
 
  Table **to, **table_buf;
 
803
  TABLE **to, **table_buf;
759
804
 
760
805
  assert((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
761
806
 
762
807
  *write_lock_used=0;
763
808
  for (i=tables=lock_count=0 ; i < count ; i++)
764
809
  {
765
 
    Table *t= table_ptr[i];
 
810
    TABLE *t= table_ptr[i];
766
811
 
767
812
    if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
768
813
    {
777
822
    update the table values. So the second part of the array is copied
778
823
    from the first part immediately before calling thr_multi_lock().
779
824
  */
780
 
  if (!(sql_lock= (DRIZZLE_LOCK*)
781
 
        malloc(sizeof(*sql_lock) +
782
 
               sizeof(THR_LOCK_DATA*) * tables * 2 +
783
 
               sizeof(table_ptr) * lock_count)))
 
825
  if (!(sql_lock= (MYSQL_LOCK*)
 
826
        my_malloc(sizeof(*sql_lock) +
 
827
                  sizeof(THR_LOCK_DATA*) * tables * 2 +
 
828
                  sizeof(table_ptr) * lock_count,
 
829
                  MYF(0))))
784
830
    return(0);
785
831
  locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
786
 
  to= table_buf= sql_lock->table= (Table**) (locks + tables * 2);
 
832
  to= table_buf= sql_lock->table= (TABLE**) (locks + tables * 2);
787
833
  sql_lock->table_count=lock_count;
788
834
 
789
835
  for (i=0 ; i < count ; i++)
790
836
  {
791
 
    Table *table;
 
837
    TABLE *table;
792
838
    enum thr_lock_type lock_type;
793
839
 
794
840
    if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
807
853
        return(0);
808
854
      }
809
855
    }
 
856
    THR_LOCK_DATA **org_locks = locks;
810
857
    locks_start= locks;
811
 
    locks= table->file->store_lock(session, locks,
 
858
    locks= table->file->store_lock(thd, locks,
812
859
                                   (flags & GET_LOCK_UNLOCK) ? TL_IGNORE :
813
860
                                   lock_type);
814
861
    if (flags & GET_LOCK_STORE_LOCKS)
818
865
      table->lock_count=      (uint) (locks - locks_start);
819
866
    }
820
867
    *to++= table;
 
868
    if (locks)
 
869
      for ( ; org_locks != locks ; org_locks++)
 
870
        (*org_locks)->debug_print_param= (void *) table;
821
871
  }
822
872
  /*
823
873
    We do not use 'tables', because there are cases where store_lock()
846
896
/**
847
897
  Lock and wait for the named lock.
848
898
 
849
 
  @param session                        Thread handler
 
899
  @param thd                    Thread handler
850
900
  @param table_list             Lock first table in this list
851
901
 
852
902
 
859
909
    1   error
860
910
*/
861
911
 
862
 
int lock_and_wait_for_table_name(Session *session, TableList *table_list)
 
912
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
863
913
{
864
914
  int lock_retcode;
865
915
  int error= -1;
866
916
 
867
 
  if (wait_if_global_read_lock(session, 0, 1))
 
917
  if (wait_if_global_read_lock(thd, 0, 1))
868
918
    return(1);
869
 
  pthread_mutex_lock(&LOCK_open);
870
 
  if ((lock_retcode = lock_table_name(session, table_list, true)) < 0)
 
919
  VOID(pthread_mutex_lock(&LOCK_open));
 
920
  if ((lock_retcode = lock_table_name(thd, table_list, true)) < 0)
871
921
    goto end;
872
 
  if (lock_retcode && wait_for_locked_table_names(session, table_list))
 
922
  if (lock_retcode && wait_for_locked_table_names(thd, table_list))
873
923
  {
874
 
    unlock_table_name(session, table_list);
 
924
    unlock_table_name(thd, table_list);
875
925
    goto end;
876
926
  }
877
927
  error=0;
878
928
 
879
929
end:
880
930
  pthread_mutex_unlock(&LOCK_open);
881
 
  start_waiting_global_read_lock(session);
 
931
  start_waiting_global_read_lock(thd);
882
932
  return(error);
883
933
}
884
934
 
886
936
/**
887
937
  Put a not open table with an old refresh version in the table cache.
888
938
 
889
 
  @param session                        Thread handler
 
939
  @param thd                    Thread handler
890
940
  @param table_list             Lock first table in this list
891
941
  @param check_in_use           Do we need to check if table already in use by us
892
942
 
910
960
    > 0  table locked, but someone is using it
911
961
*/
912
962
 
913
 
int lock_table_name(Session *session, TableList *table_list, bool check_in_use)
 
963
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
914
964
{
915
 
  Table *table;
 
965
  TABLE *table;
916
966
  char  key[MAX_DBKEY_LENGTH];
917
967
  char *db= table_list->db;
918
 
  uint32_t  key_length;
 
968
  uint  key_length;
919
969
  bool  found_locked_table= false;
920
970
  HASH_SEARCH_STATE state;
921
971
 
922
 
  key_length= create_table_def_key(session, key, table_list, 0);
 
972
  key_length= create_table_def_key(thd, key, table_list, 0);
923
973
 
924
974
  if (check_in_use)
925
975
  {
926
976
    /* Only insert the table if we haven't insert it already */
927
 
    for (table=(Table*) hash_first(&open_cache, (unsigned char*)key,
 
977
    for (table=(TABLE*) hash_first(&open_cache, (uchar*)key,
928
978
                                   key_length, &state);
929
979
         table ;
930
 
         table = (Table*) hash_next(&open_cache,(unsigned char*) key,
 
980
         table = (TABLE*) hash_next(&open_cache,(uchar*) key,
931
981
                                    key_length, &state))
932
982
    {
933
983
      if (table->reginfo.lock_type < TL_WRITE)
934
984
      {
935
 
        if (table->in_use == session)
 
985
        if (table->in_use == thd)
936
986
          found_locked_table= true;
937
987
        continue;
938
988
      }
939
989
 
940
 
      if (table->in_use == session)
 
990
      if (table->in_use == thd)
941
991
      {
942
992
        table->s->version= 0;                  // Ensure no one can use this
943
993
        table->locked_by_name= 1;
946
996
    }
947
997
  }
948
998
 
949
 
  if (session->locked_tables && session->locked_tables->table_count &&
950
 
      ! find_temporary_table(session, table_list->db, table_list->table_name))
 
999
  if (thd->locked_tables && thd->locked_tables->table_count &&
 
1000
      ! find_temporary_table(thd, table_list->db, table_list->table_name))
951
1001
  {
952
1002
    if (found_locked_table)
953
1003
      my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias);
957
1007
    return(-1);
958
1008
  }
959
1009
 
960
 
  if (!(table= table_cache_insert_placeholder(session, key, key_length)))
 
1010
  if (!(table= table_cache_insert_placeholder(thd, key, key_length)))
961
1011
    return(-1);
962
1012
 
963
1013
  table_list->table=table;
964
1014
 
965
1015
  /* Return 1 if table is in use */
966
 
  return(test(remove_table_from_cache(session, db, table_list->table_name,
 
1016
  return(test(remove_table_from_cache(thd, db, table_list->table_name,
967
1017
             check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
968
1018
}
969
1019
 
970
1020
 
971
 
void unlock_table_name(Session *session __attribute__((unused)),
972
 
                       TableList *table_list)
 
1021
void unlock_table_name(THD *thd __attribute__((__unused__)),
 
1022
                       TABLE_LIST *table_list)
973
1023
{
974
1024
  if (table_list->table)
975
1025
  {
976
 
    hash_delete(&open_cache, (unsigned char*) table_list->table);
 
1026
    hash_delete(&open_cache, (uchar*) table_list->table);
977
1027
    broadcast_refresh();
978
1028
  }
979
1029
}
980
1030
 
981
1031
 
982
 
static bool locked_named_table(Session *session __attribute__((unused)),
983
 
                               TableList *table_list)
 
1032
static bool locked_named_table(THD *thd __attribute__((__unused__)),
 
1033
                               TABLE_LIST *table_list)
984
1034
{
985
1035
  for (; table_list ; table_list=table_list->next_local)
986
1036
  {
987
 
    Table *table= table_list->table;
 
1037
    TABLE *table= table_list->table;
988
1038
    if (table)
989
1039
    {
990
 
      Table *save_next= table->next;
 
1040
      TABLE *save_next= table->next;
991
1041
      bool result;
992
1042
      table->next= 0;
993
1043
      result= table_is_used(table_list->table, 0);
1000
1050
}
1001
1051
 
1002
1052
 
1003
 
bool wait_for_locked_table_names(Session *session, TableList *table_list)
 
1053
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
1004
1054
{
1005
1055
  bool result=0;
1006
1056
 
1007
1057
  safe_mutex_assert_owner(&LOCK_open);
1008
1058
 
1009
 
  while (locked_named_table(session,table_list))
 
1059
  while (locked_named_table(thd,table_list))
1010
1060
  {
1011
 
    if (session->killed)
 
1061
    if (thd->killed)
1012
1062
    {
1013
1063
      result=1;
1014
1064
      break;
1015
1065
    }
1016
 
    wait_for_condition(session, &LOCK_open, &COND_refresh);
 
1066
    wait_for_condition(thd, &LOCK_open, &COND_refresh);
1017
1067
    pthread_mutex_lock(&LOCK_open);
1018
1068
  }
1019
1069
  return(result);
1026
1076
  REQUIREMENTS
1027
1077
  - One must have a lock on LOCK_open when calling this
1028
1078
 
1029
 
  @param session                        Thread handle
 
1079
  @param thd                    Thread handle
1030
1080
  @param table_list             Names of tables to lock
1031
1081
 
1032
1082
  @note
1039
1089
    1   Fatal error (end of memory ?)
1040
1090
*/
1041
1091
 
1042
 
bool lock_table_names(Session *session, TableList *table_list)
 
1092
bool lock_table_names(THD *thd, TABLE_LIST *table_list)
1043
1093
{
1044
1094
  bool got_all_locks=1;
1045
 
  TableList *lock_table;
 
1095
  TABLE_LIST *lock_table;
1046
1096
 
1047
1097
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
1048
1098
  {
1049
1099
    int got_lock;
1050
 
    if ((got_lock=lock_table_name(session,lock_table, true)) < 0)
 
1100
    if ((got_lock=lock_table_name(thd,lock_table, true)) < 0)
1051
1101
      goto end;                                 // Fatal error
1052
1102
    if (got_lock)
1053
1103
      got_all_locks=0;                          // Someone is using table
1054
1104
  }
1055
1105
 
1056
1106
  /* If some table was in use, wait until we got the lock */
1057
 
  if (!got_all_locks && wait_for_locked_table_names(session, table_list))
 
1107
  if (!got_all_locks && wait_for_locked_table_names(thd, table_list))
1058
1108
    goto end;
1059
1109
  return 0;
1060
1110
 
1061
1111
end:
1062
 
  unlock_table_names(session, table_list, lock_table);
 
1112
  unlock_table_names(thd, table_list, lock_table);
1063
1113
  return 1;
1064
1114
}
1065
1115
 
1067
1117
/**
1068
1118
  Unlock all tables in list with a name lock.
1069
1119
 
1070
 
  @param session        Thread handle.
 
1120
  @param thd        Thread handle.
1071
1121
  @param table_list Names of tables to lock.
1072
1122
 
1073
 
  @note
1074
 
    This function needs to be protected by LOCK_open. If we're
 
1123
  @note 
 
1124
    This function needs to be protected by LOCK_open. If we're 
1075
1125
    under LOCK TABLES, this function does not work as advertised. Namely,
1076
1126
    it does not exclude other threads from using this table and does not
1077
1127
    put an exclusive name lock on this table into the table cache.
1083
1133
  @retval FALSE Name lock successfully acquired.
1084
1134
*/
1085
1135
 
1086
 
bool lock_table_names_exclusively(Session *session, TableList *table_list)
 
1136
bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list)
1087
1137
{
1088
 
  if (lock_table_names(session, table_list))
 
1138
  if (lock_table_names(thd, table_list))
1089
1139
    return true;
1090
1140
 
1091
1141
  /*
1092
1142
    Upgrade the table name locks from semi-exclusive to exclusive locks.
1093
1143
  */
1094
 
  for (TableList *table= table_list; table; table= table->next_global)
 
1144
  for (TABLE_LIST *table= table_list; table; table= table->next_global)
1095
1145
  {
1096
1146
    if (table->table)
1097
1147
      table->table->open_placeholder= 1;
1103
1153
/**
1104
1154
  Test is 'table' is protected by an exclusive name lock.
1105
1155
 
1106
 
  @param[in] session        The current thread handler
 
1156
  @param[in] thd        The current thread handler
1107
1157
  @param[in] table_list Table container containing the single table to be
1108
1158
                        tested
1109
1159
 
1115
1165
*/
1116
1166
 
1117
1167
bool
1118
 
is_table_name_exclusively_locked_by_this_thread(Session *session,
1119
 
                                                TableList *table_list)
 
1168
is_table_name_exclusively_locked_by_this_thread(THD *thd,
 
1169
                                                TABLE_LIST *table_list)
1120
1170
{
1121
1171
  char  key[MAX_DBKEY_LENGTH];
1122
 
  uint32_t  key_length;
1123
 
 
1124
 
  key_length= create_table_def_key(session, key, table_list, 0);
1125
 
 
1126
 
  return is_table_name_exclusively_locked_by_this_thread(session, (unsigned char *)key,
 
1172
  uint  key_length;
 
1173
 
 
1174
  key_length= create_table_def_key(thd, key, table_list, 0);
 
1175
 
 
1176
  return is_table_name_exclusively_locked_by_this_thread(thd, (uchar *)key,
1127
1177
                                                         key_length);
1128
1178
}
1129
1179
 
1131
1181
/**
1132
1182
  Test is 'table key' is protected by an exclusive name lock.
1133
1183
 
1134
 
  @param[in] session        The current thread handler.
 
1184
  @param[in] thd        The current thread handler.
1135
1185
  @param[in] key
1136
1186
  @param[in] key_length
1137
1187
 
1142
1192
 */
1143
1193
 
1144
1194
bool
1145
 
is_table_name_exclusively_locked_by_this_thread(Session *session, unsigned char *key,
 
1195
is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
1146
1196
                                                int key_length)
1147
1197
{
1148
1198
  HASH_SEARCH_STATE state;
1149
 
  Table *table;
 
1199
  TABLE *table;
1150
1200
 
1151
 
  for (table= (Table*) hash_first(&open_cache, key,
 
1201
  for (table= (TABLE*) hash_first(&open_cache, key,
1152
1202
                                  key_length, &state);
1153
1203
       table ;
1154
 
       table= (Table*) hash_next(&open_cache, key,
 
1204
       table= (TABLE*) hash_next(&open_cache, key,
1155
1205
                                 key_length, &state))
1156
1206
  {
1157
 
    if (table->in_use == session &&
 
1207
    if (table->in_use == thd &&
1158
1208
        table->open_placeholder == 1 &&
1159
1209
        table->s->version == 0)
1160
1210
      return true;
1167
1217
  Unlock all tables in list with a name lock.
1168
1218
 
1169
1219
  @param
1170
 
    session                     Thread handle
 
1220
    thd                 Thread handle
1171
1221
  @param
1172
1222
    table_list          Names of tables to unlock
1173
1223
  @param
1187
1237
    1   Fatal error (end of memory ?)
1188
1238
*/
1189
1239
 
1190
 
void unlock_table_names(Session *session, TableList *table_list,
1191
 
                        TableList *last_table)
 
1240
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
 
1241
                        TABLE_LIST *last_table)
1192
1242
{
1193
 
  for (TableList *table= table_list;
 
1243
  for (TABLE_LIST *table= table_list;
1194
1244
       table != last_table;
1195
1245
       table= table->next_local)
1196
 
    unlock_table_name(session,table);
 
1246
    unlock_table_name(thd,table);
1197
1247
  broadcast_refresh();
1198
1248
  return;
1199
1249
}
1290
1340
  If we have merged 1) and 3) into 1), we would have had this deadlock:
1291
1341
  imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
1292
1342
  table t.
1293
 
  session1: SELECT * FROM t FOR UPDATE;
1294
 
  session2: UPDATE t SET a=1; # blocked by row-level locks of session1
1295
 
  session3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
1296
 
  table instance of session2
1297
 
  session1: COMMIT; # blocked by session3.
1298
 
  session1 blocks session2 which blocks session3 which blocks session1: deadlock.
 
1343
  thd1: SELECT * FROM t FOR UPDATE;
 
1344
  thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
 
1345
  thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
 
1346
  table instance of thd2
 
1347
  thd1: COMMIT; # blocked by thd3.
 
1348
  thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
1299
1349
 
1300
1350
  Note that we need to support that one thread does
1301
1351
  FLUSH TABLES WITH READ LOCK; and then COMMIT;
1305
1355
 
1306
1356
****************************************************************************/
1307
1357
 
1308
 
volatile uint32_t global_read_lock=0;
1309
 
volatile uint32_t global_read_lock_blocks_commit=0;
1310
 
static volatile uint32_t protect_against_global_read_lock=0;
1311
 
static volatile uint32_t waiting_for_read_lock=0;
 
1358
volatile uint global_read_lock=0;
 
1359
volatile uint global_read_lock_blocks_commit=0;
 
1360
static volatile uint protect_against_global_read_lock=0;
 
1361
static volatile uint waiting_for_read_lock=0;
1312
1362
 
1313
1363
#define GOT_GLOBAL_READ_LOCK               1
1314
1364
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
1315
1365
 
1316
 
bool lock_global_read_lock(Session *session)
 
1366
bool lock_global_read_lock(THD *thd)
1317
1367
{
1318
 
  if (!session->global_read_lock)
 
1368
  if (!thd->global_read_lock)
1319
1369
  {
1320
1370
    const char *old_message;
1321
1371
    (void) pthread_mutex_lock(&LOCK_global_read_lock);
1322
 
    old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
 
1372
    old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1323
1373
                                "Waiting to get readlock");
1324
1374
 
1325
1375
    waiting_for_read_lock++;
1326
 
    while (protect_against_global_read_lock && !session->killed)
 
1376
    while (protect_against_global_read_lock && !thd->killed)
1327
1377
      pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1328
1378
    waiting_for_read_lock--;
1329
 
    if (session->killed)
 
1379
    if (thd->killed)
1330
1380
    {
1331
 
      session->exit_cond(old_message);
 
1381
      thd->exit_cond(old_message);
1332
1382
      return(1);
1333
1383
    }
1334
 
    session->global_read_lock= GOT_GLOBAL_READ_LOCK;
 
1384
    thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
1335
1385
    global_read_lock++;
1336
 
    session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1386
    thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1337
1387
  }
1338
1388
  /*
1339
1389
    We DON'T set global_read_lock_blocks_commit now, it will be set after
1347
1397
}
1348
1398
 
1349
1399
 
1350
 
void unlock_global_read_lock(Session *session)
 
1400
void unlock_global_read_lock(THD *thd)
1351
1401
{
1352
 
  uint32_t tmp;
 
1402
  uint tmp;
1353
1403
 
1354
1404
  pthread_mutex_lock(&LOCK_global_read_lock);
1355
1405
  tmp= --global_read_lock;
1356
 
  if (session->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
 
1406
  if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1357
1407
    --global_read_lock_blocks_commit;
1358
1408
  pthread_mutex_unlock(&LOCK_global_read_lock);
1359
1409
  /* Send the signal outside the mutex to avoid a context switch */
1361
1411
  {
1362
1412
    pthread_cond_broadcast(&COND_global_read_lock);
1363
1413
  }
1364
 
  session->global_read_lock= 0;
 
1414
  thd->global_read_lock= 0;
1365
1415
 
1366
1416
  return;
1367
1417
}
1370
1420
                   (is_not_commit ||                               \
1371
1421
                    global_read_lock_blocks_commit))
1372
1422
 
1373
 
bool wait_if_global_read_lock(Session *session, bool abort_on_refresh,
 
1423
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
1374
1424
                              bool is_not_commit)
1375
1425
{
1376
1426
  const char *old_message= NULL;
1386
1436
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
1387
1437
  if ((need_exit_cond= must_wait))
1388
1438
  {
1389
 
    if (session->global_read_lock)              // This thread had the read locks
 
1439
    if (thd->global_read_lock)          // This thread had the read locks
1390
1440
    {
1391
1441
      if (is_not_commit)
1392
1442
        my_message(ER_CANT_UPDATE_WITH_READLOCK,
1399
1449
      */
1400
1450
      return(is_not_commit);
1401
1451
    }
1402
 
    old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
 
1452
    old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1403
1453
                                "Waiting for release of readlock");
1404
 
    while (must_wait && ! session->killed &&
1405
 
           (!abort_on_refresh || session->version == refresh_version))
 
1454
    while (must_wait && ! thd->killed &&
 
1455
           (!abort_on_refresh || thd->version == refresh_version))
1406
1456
    {
1407
1457
      (void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1408
1458
    }
1409
 
    if (session->killed)
 
1459
    if (thd->killed)
1410
1460
      result=1;
1411
1461
  }
1412
1462
  if (!abort_on_refresh && !result)
1416
1466
    and if old_message is set
1417
1467
  */
1418
1468
  if (unlikely(need_exit_cond))
1419
 
    session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1469
    thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1420
1470
  else
1421
1471
    pthread_mutex_unlock(&LOCK_global_read_lock);
1422
1472
  return(result);
1423
1473
}
1424
1474
 
1425
1475
 
1426
 
void start_waiting_global_read_lock(Session *session)
 
1476
void start_waiting_global_read_lock(THD *thd)
1427
1477
{
1428
1478
  bool tmp;
1429
 
  if (unlikely(session->global_read_lock))
 
1479
  if (unlikely(thd->global_read_lock))
1430
1480
    return;
1431
1481
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
1432
1482
  tmp= (!--protect_against_global_read_lock &&
1438
1488
}
1439
1489
 
1440
1490
 
1441
 
bool make_global_read_lock_block_commit(Session *session)
 
1491
bool make_global_read_lock_block_commit(THD *thd)
1442
1492
{
1443
1493
  bool error;
1444
1494
  const char *old_message;
1446
1496
    If we didn't succeed lock_global_read_lock(), or if we already suceeded
1447
1497
    make_global_read_lock_block_commit(), do nothing.
1448
1498
  */
1449
 
  if (session->global_read_lock != GOT_GLOBAL_READ_LOCK)
 
1499
  if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
1450
1500
    return(0);
1451
1501
  pthread_mutex_lock(&LOCK_global_read_lock);
1452
1502
  /* increment this BEFORE waiting on cond (otherwise race cond) */
1453
1503
  global_read_lock_blocks_commit++;
1454
1504
  /* For testing we set up some blocking, to see if we can be killed */
1455
1505
  protect_against_global_read_lock++;
1456
 
  old_message= session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
 
1506
  old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1457
1507
                               "Waiting for all running commits to finish");
1458
 
  while (protect_against_global_read_lock && !session->killed)
 
1508
  while (protect_against_global_read_lock && !thd->killed)
1459
1509
    pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1460
1510
  protect_against_global_read_lock--;
1461
 
  if ((error= test(session->killed)))
 
1511
  if ((error= test(thd->killed)))
1462
1512
    global_read_lock_blocks_commit--; // undo what we did
1463
1513
  else
1464
 
    session->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1465
 
  session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1514
    thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
 
1515
  thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1466
1516
  return(error);
1467
1517
}
1468
1518
 
1488
1538
 
1489
1539
void broadcast_refresh(void)
1490
1540
{
1491
 
  pthread_cond_broadcast(&COND_refresh);
1492
 
  pthread_cond_broadcast(&COND_global_read_lock);
 
1541
  VOID(pthread_cond_broadcast(&COND_refresh));
 
1542
  VOID(pthread_cond_broadcast(&COND_global_read_lock));
1493
1543
}
1494
1544
 
1495
1545
 
1498
1548
 
1499
1549
  SYNOPSIS
1500
1550
    try_transactional_lock()
1501
 
      session                       Thread handle
 
1551
      thd                       Thread handle
1502
1552
      table_list                List of tables to lock
1503
1553
 
1504
1554
  DESCRIPTION
1511
1561
    -1                  Error: no recovery possible.
1512
1562
*/
1513
1563
 
1514
 
int try_transactional_lock(Session *session, TableList *table_list)
 
1564
int try_transactional_lock(THD *thd, TABLE_LIST *table_list)
1515
1565
{
1516
 
  uint32_t          dummy_counter;
 
1566
  uint          dummy_counter;
1517
1567
  int           error;
1518
1568
  int           result= 0;
1519
1569
 
1520
1570
  /* Need to open the tables to be able to access engine methods. */
1521
 
  if (open_tables(session, &table_list, &dummy_counter, 0))
 
1571
  if (open_tables(thd, &table_list, &dummy_counter, 0))
1522
1572
  {
1523
1573
    /* purecov: begin tested */
1524
1574
    return(-1);
1526
1576
  }
1527
1577
 
1528
1578
  /* Required by InnoDB. */
1529
 
  session->in_lock_tables= true;
 
1579
  thd->in_lock_tables= true;
1530
1580
 
1531
 
  if ((error= set_handler_table_locks(session, table_list, true)))
 
1581
  if ((error= set_handler_table_locks(thd, table_list, true)))
1532
1582
  {
1533
1583
    /*
1534
1584
      Not all transactional locks could be taken. If the error was
1551
1601
 
1552
1602
 err:
1553
1603
  /* We need to explicitly commit if autocommit mode is active. */
1554
 
  (void) ha_autocommit_or_rollback(session, 0);
 
1604
  (void) ha_autocommit_or_rollback(thd, 0);
1555
1605
  /* Close the tables. The locks (if taken) persist in the storage engines. */
1556
 
  close_tables_for_reopen(session, &table_list);
1557
 
  session->in_lock_tables= false;
 
1606
  close_tables_for_reopen(thd, &table_list);
 
1607
  thd->in_lock_tables= false;
1558
1608
  return(result);
1559
1609
}
1560
1610
 
1564
1614
 
1565
1615
  SYNOPSIS
1566
1616
    check_transactional_lock()
1567
 
      session                       Thread handle
 
1617
      thd                       Thread handle
1568
1618
      table_list                List of tables to lock
1569
1619
 
1570
1620
  DESCRIPTION
1584
1634
    -1                  Error: Lock conversion is prohibited.
1585
1635
*/
1586
1636
 
1587
 
int check_transactional_lock(Session *session, TableList *table_list)
 
1637
int check_transactional_lock(THD *thd, TABLE_LIST *table_list)
1588
1638
{
1589
 
  TableList    *tlist;
 
1639
  TABLE_LIST    *tlist;
1590
1640
  int           result= 0;
1591
 
  char          warn_buff[DRIZZLE_ERRMSG_SIZE];
 
1641
  char          warn_buff[MYSQL_ERRMSG_SIZE];
1592
1642
 
1593
1643
  for (tlist= table_list; tlist; tlist= tlist->next_global)
1594
1644
  {
1596
1646
    /*
1597
1647
      Unfortunately we cannot use tlist->placeholder() here. This method
1598
1648
      returns TRUE if the table is not open, which is always the case
1599
 
      here. Whenever the definition of TableList::placeholder() is
 
1649
      here. Whenever the definition of TABLE_LIST::placeholder() is
1600
1650
      changed, probably this condition needs to be changed too.
1601
1651
    */
1602
1652
    if (tlist->derived || tlist->schema_table || !tlist->lock_transactional)
1613
1663
    }
1614
1664
 
1615
1665
    /* We must not convert the lock method within an active transaction. */
1616
 
    if (session->active_transaction())
 
1666
    if (thd->active_transaction())
1617
1667
    {
1618
1668
      my_error(ER_NO_AUTO_CONVERT_LOCK_TRANSACTION, MYF(0),
1619
1669
               tlist->alias ? tlist->alias : tlist->table_name);
1624
1674
    /* Warn about the conversion. */
1625
1675
    snprintf(warn_buff, sizeof(warn_buff), ER(ER_WARN_AUTO_CONVERT_LOCK),
1626
1676
             tlist->alias ? tlist->alias : tlist->table_name);
1627
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1677
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1628
1678
                 ER_WARN_AUTO_CONVERT_LOCK, warn_buff);
1629
1679
  }
1630
1680
 
1637
1687
 
1638
1688
  SYNOPSIS
1639
1689
    set_handler_table_locks()
1640
 
      session                       Thread handle
 
1690
      thd                       Thread handle
1641
1691
      table_list                List of tables to lock
1642
1692
      transactional             If to lock transactional or non-transactional
1643
1693
 
1646
1696
    != 0                Error code from handler::lock_table().
1647
1697
*/
1648
1698
 
1649
 
int set_handler_table_locks(Session *session, TableList *table_list,
 
1699
int set_handler_table_locks(THD *thd, TABLE_LIST *table_list,
1650
1700
                            bool transactional)
1651
1701
{
1652
 
  TableList    *tlist;
 
1702
  TABLE_LIST    *tlist;
1653
1703
  int           error= 0;
1654
1704
 
1655
1705
  for (tlist= table_list; tlist; tlist= tlist->next_global)
1686
1736
 
1687
1737
      /*
1688
1738
        For warning/error reporting we need to set the intended lock
1689
 
        method in the TableList object. It will be used later by
 
1739
        method in the TABLE_LIST object. It will be used later by
1690
1740
        check_transactional_lock(). The lock method is not set if this
1691
1741
        table belongs to a view. We can safely set it to transactional
1692
1742
        locking here. Even for non-view tables. This function is not
1705
1755
    */
1706
1756
    if (!error || !transactional)
1707
1757
    {
1708
 
      error= tlist->table->file->lock_table(session, lock_type, lock_timeout);
 
1758
      error= tlist->table->file->lock_table(thd, lock_type, lock_timeout);
1709
1759
      if (error && transactional && (error != HA_ERR_WRONG_COMMAND))
1710
1760
        tlist->table->file->print_error(error, MYF(0));
1711
1761
    }