~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/lock.cc

  • Committer: Brian Aker
  • Date: 2008-08-01 19:01:50 UTC
  • Revision ID: brian@tangent.org-20080801190150-003gpp2343cn7cfz
Removed final trace of crypt() lock.

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