~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/lock.cc

Moved the last of the libdrizzleclient calls into Protocol.

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