~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/locking/global.cc

  • Committer: Brian Aker
  • Date: 2010-11-08 20:10:51 UTC
  • mfrom: (1910.2.8 merge)
  • Revision ID: brian@tangent.org-20101108201051-fmplr6oke3c088kf
Encapsulation around locking/kill

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
  When not using LOCK TABLES:
29
29
 
30
 
  - For each SQL statement mysql_lock_tables() is called for all involved
 
30
  - For each SQL statement lockTables() is called for all involved
31
31
    tables.
32
 
    - mysql_lock_tables() will call
 
32
    - lockTables() will call
33
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
 
  - When statement is done, we call mysql_unlock_tables().
 
36
  - When statement is done, we call unlockTables().
37
37
    This will call DrizzleLock::unlock() followed by
38
38
    table_handler->external_lock(session, F_UNLCK) for each table.
39
39
 
40
 
  - Note that mysql_unlock_tables() may be called several times as
 
40
  - Note that unlockTables() may be called several times as
41
41
    MySQL in some cases can free some tables earlier than others.
42
42
 
43
43
  - The above is true both for normal and temporary tables.
47
47
 
48
48
  When using LOCK TABLES:
49
49
 
50
 
  - LOCK Table will call mysql_lock_tables() for all tables.
51
 
    mysql_lock_tables() will call
 
50
  - LOCK Table will call lockTables() for all tables.
 
51
    lockTables() will call
52
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
 
60
60
 
61
61
  - When statement is done, we will call ha_commit_stmt(session);
62
62
 
63
 
  - When calling UNLOCK TABLES we call mysql_unlock_tables() for all
 
63
  - When calling UNLOCK TABLES we call unlockTables() for all
64
64
    tables used in LOCK TABLES
65
65
 
66
66
  If table_handler->external_lock(session, locktype) fails, we call
105
105
  @{
106
106
*/
107
107
 
108
 
static DrizzleLock *get_lock_data(Session *session, Table **table,
109
 
                                  uint32_t count,
110
 
                                  bool should_lock, Table **write_locked);
111
 
static int lock_external(Session *session, Table **table,uint32_t count);
112
 
static int unlock_external(Session *session, Table **table,uint32_t count);
113
108
static void print_lock_error(int error, const char *);
114
109
 
115
110
/*
116
111
  Lock tables.
117
112
 
118
113
  SYNOPSIS
119
 
    mysql_lock_tables()
120
 
    session                         The current thread.
 
114
    lockTables()
121
115
    tables                      An array of pointers to the tables to lock.
122
116
    count                       The number of tables to lock.
123
117
    flags                       Options:
125
119
      DRIZZLE_LOCK_IGNORE_FLUSH                 Ignore a flush tables.
126
120
      DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN        Instead of reopening altered
127
121
                                              or dropped tables by itself,
128
 
                                              mysql_lock_tables() should
 
122
                                              lockTables() should
129
123
                                              notify upper level and rely
130
124
                                              on caller doing this.
131
125
    need_reopen                 Out parameter, TRUE if some tables were altered
178
172
}
179
173
 
180
174
 
181
 
DrizzleLock *mysql_lock_tables(Session *session, Table **tables, uint32_t count,
182
 
                                uint32_t flags, bool *need_reopen)
 
175
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
183
176
{
184
177
  DrizzleLock *sql_lock;
185
178
  Table *write_lock_used;
190
183
 
191
184
  for (;;)
192
185
  {
193
 
    if (! (sql_lock= get_lock_data(session, tables, count, true,
 
186
    if (! (sql_lock= get_lock_data(tables, count, true,
194
187
                                   &write_lock_used)))
195
188
      break;
196
189
 
201
194
        Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
202
195
        Wait until the lock is gone
203
196
      */
204
 
      if (wait_if_global_read_lock(session, 1, 1))
 
197
      if (wait_if_global_read_lock(1, 1))
205
198
      {
206
199
        /* Clear the lock type of all lock data to avoid reusage. */
207
200
        reset_lock_data_and_free(&sql_lock);
208
201
        break;
209
202
      }
210
 
      if (session->version != refresh_version)
 
203
      if (version != refresh_version)
211
204
      {
212
205
        /* Clear the lock type of all lock data to avoid reusage. */
213
206
        reset_lock_data_and_free(&sql_lock);
215
208
      }
216
209
    }
217
210
    
218
 
    session->set_proc_info("Notify start statement");
 
211
    set_proc_info("Notify start statement");
219
212
    /*
220
213
     * Here, we advise all storage engines involved in the
221
214
     * statement that we are starting a new statement
236
229
 
237
230
      for_each(involved_engines.begin(),
238
231
               involved_engines.end(),
239
 
               bind2nd(mem_fun(&plugin::StorageEngine::startStatement), session));
 
232
               bind2nd(mem_fun(&plugin::StorageEngine::startStatement), this));
240
233
    }
241
234
 
242
 
    session->set_proc_info("External lock");
 
235
    set_proc_info("External lock");
243
236
    /*
244
237
     * Here, the call to lock_external() informs the
245
238
     * all engines for all tables used in this statement
246
239
     * of the type of lock that Drizzle intends to take on a 
247
240
     * specific table.
248
241
     */
249
 
    if (sql_lock->table_count && lock_external(session, sql_lock->getTable(),
250
 
                                               sql_lock->table_count))
 
242
    if (sql_lock->table_count && lock_external(sql_lock->getTable(), sql_lock->table_count))
251
243
    {
252
244
      /* Clear the lock type of all lock data to avoid reusage. */
253
245
      reset_lock_data_and_free(&sql_lock);
254
246
      break;
255
247
    }
256
 
    session->set_proc_info("Table lock");
 
248
    set_proc_info("Table lock");
257
249
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
258
250
    memcpy(sql_lock->getLocks() + sql_lock->lock_count,
259
251
           sql_lock->getLocks(),
262
254
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->getLocks() +
263
255
                                                     sql_lock->lock_count,
264
256
                                                     sql_lock->lock_count,
265
 
                                                     session->lock_id)];
 
257
                                                     this->lock_id)];
266
258
    if (rc > 1)                                 /* a timeout or a deadlock */
267
259
    {
268
260
      if (sql_lock->table_count)
269
 
        unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
 
261
        unlock_external(sql_lock->getTable(), sql_lock->table_count);
270
262
      reset_lock_data_and_free(&sql_lock);
271
263
      my_error(rc, MYF(0));
272
264
      break;
273
265
    }
274
266
    else if (rc == 1)                           /* aborted */
275
267
    {
276
 
      session->some_tables_deleted=1;           // Try again
 
268
      some_tables_deleted= 1;           // Try again
277
269
      sql_lock->lock_count= 0;                  // Locks are already freed
278
270
      // Fall through: unlock, reset lock data, free and retry
279
271
    }
280
 
    else if (!session->some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
 
272
    else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
281
273
    {
282
274
      /*
283
275
        Thread was killed or lock aborted. Let upper level close all
285
277
      */
286
278
      break;
287
279
    }
288
 
    else if (!session->open_tables)
 
280
    else if (not open_tables)
289
281
    {
290
282
      // Only using temporary tables, no need to unlock
291
 
      session->some_tables_deleted= 0;
 
283
      some_tables_deleted= 0;
292
284
      break;
293
285
    }
294
 
    session->set_proc_info(0);
 
286
    set_proc_info(0);
295
287
 
296
288
    /* going to retry, unlock all tables */
297
289
    if (sql_lock->lock_count)
298
290
        sql_lock->unlock(sql_lock->lock_count);
299
291
 
300
292
    if (sql_lock->table_count)
301
 
      unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
 
293
      unlock_external(sql_lock->getTable(), sql_lock->table_count);
302
294
 
303
295
    /*
304
296
      If thr_multi_lock fails it resets lock type for tables, which
313
305
     */
314
306
    for_each(involved_engines.begin(),
315
307
             involved_engines.end(),
316
 
             bind2nd(mem_fun(&plugin::StorageEngine::endStatement), session));
 
308
             bind2nd(mem_fun(&plugin::StorageEngine::endStatement), this));
317
309
retry:
318
310
    if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
319
311
    {
320
312
      *need_reopen= true;
321
313
      break;
322
314
    }
323
 
    if (wait_for_tables(session))
 
315
 
 
316
    if (wait_for_tables(this))
 
317
    {
324
318
      break;                                    // Couldn't open tables
 
319
    }
325
320
  }
326
 
  session->set_proc_info(0);
327
 
  if (session->killed)
 
321
 
 
322
  set_proc_info(0);
 
323
  if (getKilled())
328
324
  {
329
 
    session->send_kill_message();
 
325
    send_kill_message();
330
326
    if (sql_lock)
331
327
    {
332
 
      mysql_unlock_tables(session,sql_lock);
 
328
      unlockTables(sql_lock);
333
329
      sql_lock= NULL;
334
330
    }
335
331
  }
336
 
  session->set_time_after_lock();
 
332
  set_time_after_lock();
337
333
  return (sql_lock);
338
334
}
339
335
 
340
336
 
341
 
static int lock_external(Session *session, Table **tables, uint32_t count)
 
337
int Session::lock_external(Table **tables, uint32_t count)
342
338
{
343
339
  int lock_type,error;
344
340
  for (uint32_t i= 1 ; i <= count ; i++, tables++)
350
346
         (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
351
347
      lock_type=F_RDLCK;
352
348
 
353
 
    if ((error=(*tables)->cursor->ha_external_lock(session,lock_type)))
 
349
    if ((error=(*tables)->cursor->ha_external_lock(this,lock_type)))
354
350
    {
355
351
      print_lock_error(error, (*tables)->cursor->getEngine()->getName().c_str());
356
352
      while (--i)
357
353
      {
358
354
        tables--;
359
 
        (*tables)->cursor->ha_external_lock(session, F_UNLCK);
 
355
        (*tables)->cursor->ha_external_lock(this, F_UNLCK);
360
356
        (*tables)->current_lock=F_UNLCK;
361
357
      }
362
358
      return error;
371
367
}
372
368
 
373
369
 
374
 
void mysql_unlock_tables(Session *session, DrizzleLock *sql_lock)
 
370
void Session::unlockTables(DrizzleLock *sql_lock)
375
371
{
376
372
  if (sql_lock->lock_count)
377
373
    sql_lock->unlock(sql_lock->lock_count);
378
374
  if (sql_lock->table_count)
379
 
    unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
 
375
    unlock_external(sql_lock->getTable(), sql_lock->table_count);
380
376
  delete sql_lock;
381
377
}
382
378
 
383
379
/**
384
 
  Unlock some of the tables locked by mysql_lock_tables.
 
380
  Unlock some of the tables locked by lockTables.
385
381
 
386
382
  This will work even if get_lock_data fails (next unlock will free all)
387
383
*/
388
384
 
389
 
void mysql_unlock_some_tables(Session *session, Table **table, uint32_t count)
 
385
void Session::unlockSomeTables(Table **table, uint32_t count)
390
386
{
391
387
  DrizzleLock *sql_lock;
392
388
  Table *write_lock_used;
393
 
  if ((sql_lock= get_lock_data(session, table, count, false,
 
389
  if ((sql_lock= get_lock_data(table, count, false,
394
390
                               &write_lock_used)))
395
 
    mysql_unlock_tables(session, sql_lock);
 
391
    unlockTables(sql_lock);
396
392
}
397
393
 
398
394
 
400
396
  unlock all tables locked for read.
401
397
*/
402
398
 
403
 
void mysql_unlock_read_tables(Session *session, DrizzleLock *sql_lock)
 
399
void Session::unlockReadTables(DrizzleLock *sql_lock)
404
400
{
405
401
  uint32_t i,found;
406
402
 
407
403
  /* Move all write locks first */
408
 
  THR_LOCK_DATA **lock=sql_lock->getLocks();
 
404
  THR_LOCK_DATA **lock_local= sql_lock->getLocks();
409
405
  for (i=found=0 ; i < sql_lock->lock_count ; i++)
410
406
  {
411
407
    if (sql_lock->getLocks()[i]->type >= TL_WRITE_ALLOW_READ)
412
408
    {
413
 
      std::swap(*lock, sql_lock->getLocks()[i]);
414
 
      lock++;
 
409
      std::swap(*lock_local, sql_lock->getLocks()[i]);
 
410
      lock_local++;
415
411
      found++;
416
412
    }
417
413
  }
438
434
  /* Unlock all read locked tables */
439
435
  if (i != found)
440
436
  {
441
 
    unlock_external(session,table,i-found);
 
437
    unlock_external(table, i - found);
442
438
    sql_lock->table_count=found;
443
439
  }
444
440
  /* Fix the lock positions in Table */
452
448
    found+= tbl->lock_count;
453
449
    table++;
454
450
  }
455
 
  return;
456
451
}
457
452
 
458
453
 
476
471
                          effect is desired.
477
472
*/
478
473
 
479
 
void mysql_lock_remove(Session *session, Table *table)
 
474
void Session::removeLock(Table *table)
480
475
{
481
 
  mysql_unlock_some_tables(session, &table, /* table count */ 1);
 
476
  unlockSomeTables(&table, /* table count */ 1);
482
477
}
483
478
 
484
479
 
485
480
/** Abort all other threads waiting to get lock in table. */
486
481
 
487
 
void mysql_lock_abort(Session *session, Table *table)
 
482
void Session::abortLock(Table *table)
488
483
{
489
484
  DrizzleLock *locked;
490
485
  Table *write_lock_used;
491
486
 
492
 
  if ((locked= get_lock_data(session, &table, 1, false,
 
487
  if ((locked= get_lock_data(&table, 1, false,
493
488
                             &write_lock_used)))
494
489
  {
495
490
    for (uint32_t x= 0; x < locked->lock_count; x++)
511
506
    1  Table was locked by at least one other thread
512
507
*/
513
508
 
514
 
bool mysql_lock_abort_for_thread(Session *session, Table *table)
 
509
bool Session::abortLockForThread(Table *table)
515
510
{
516
511
  DrizzleLock *locked;
517
512
  Table *write_lock_used;
518
513
  bool result= false;
519
514
 
520
 
  if ((locked= get_lock_data(session, &table, 1, false,
 
515
  if ((locked= get_lock_data(&table, 1, false,
521
516
                             &write_lock_used)))
522
517
  {
523
518
    for (uint32_t i= 0; i < locked->lock_count; i++)
532
527
 
533
528
/** Unlock a set of external. */
534
529
 
535
 
static int unlock_external(Session *session, Table **table, uint32_t count)
 
530
int Session::unlock_external(Table **table, uint32_t count)
536
531
{
537
532
  int error,error_code;
538
533
 
542
537
    if ((*table)->current_lock != F_UNLCK)
543
538
    {
544
539
      (*table)->current_lock = F_UNLCK;
545
 
      if ((error=(*table)->cursor->ha_external_lock(session, F_UNLCK)))
 
540
      if ((error=(*table)->cursor->ha_external_lock(this, F_UNLCK)))
546
541
      {
547
542
        error_code=error;
548
543
        print_lock_error(error_code, (*table)->cursor->getEngine()->getName().c_str());
565
560
  @param write_lock_used   Store pointer to last table with WRITE_ALLOW_WRITE
566
561
*/
567
562
 
568
 
static DrizzleLock *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
569
 
                                 bool should_lock, Table **write_lock_used)
 
563
DrizzleLock *Session::get_lock_data(Table **table_ptr, uint32_t count,
 
564
                                    bool should_lock, Table **write_lock_used)
570
565
{
571
566
  uint32_t lock_count;
572
567
  DrizzleLock *sql_lock;
622
617
      }
623
618
    }
624
619
    locks_start= locks;
625
 
    locks= table->cursor->store_lock(session, locks,
626
 
                                   should_lock == false ? TL_IGNORE : lock_type);
 
620
    locks= table->cursor->store_lock(this, locks, should_lock == false ? TL_IGNORE : lock_type);
627
621
    if (should_lock)
628
622
    {
629
623
      table->lock_position=   (uint32_t) (to - table_buf);
656
650
/**
657
651
  Put a not open table with an old refresh version in the table cache.
658
652
 
659
 
  @param session                        Thread handler
660
653
  @param table_list             Lock first table in this list
661
654
  @param check_in_use           Do we need to check if table already in use by us
662
655
 
680
673
    > 0  table locked, but someone is using it
681
674
*/
682
675
 
683
 
static int lock_table_name(Session *session, TableList *table_list)
 
676
int Session::lock_table_name(TableList *table_list)
684
677
{
685
678
  TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
686
679
  const TableIdentifier::Key &key(identifier.getKey());
700
693
        continue;
701
694
      }
702
695
 
703
 
      if (table->in_use == session)
 
696
      if (table->in_use == this)
704
697
      {
705
698
        table->getMutableShare()->resetVersion();                  // Ensure no one can use this
706
699
        table->locked_by_name= true;
710
703
  }
711
704
 
712
705
  table::Placeholder *table= NULL;
713
 
  if (!(table= session->table_cache_insert_placeholder(identifier)))
 
706
  if (!(table= table_cache_insert_placeholder(identifier)))
714
707
  {
715
708
    return -1;
716
709
  }
718
711
  table_list->table= reinterpret_cast<Table *>(table);
719
712
 
720
713
  /* Return 1 if table is in use */
721
 
  return(test(table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG)));
 
714
  return(test(table::Cache::singleton().removeTable(this, identifier, RTFC_NO_FLAG)));
722
715
}
723
716
 
724
717
 
725
 
void unlock_table_name(TableList *table_list)
 
718
void TableList::unlock_table_name()
726
719
{
727
 
  if (table_list->table)
 
720
  if (table)
728
721
  {
729
 
    table::remove_table(static_cast<table::Concurrent *>(table_list->table));
730
 
    broadcast_refresh();
 
722
    table::remove_table(static_cast<table::Concurrent *>(table));
 
723
    locking::broadcast_refresh();
731
724
  }
732
725
}
733
726
 
752
745
}
753
746
 
754
747
 
755
 
static bool wait_for_locked_table_names(Session *session, TableList *table_list)
 
748
bool Session::wait_for_locked_table_names(TableList *table_list)
756
749
{
757
750
  bool result= false;
758
751
 
762
755
 
763
756
  while (locked_named_table(table_list))
764
757
  {
765
 
    if (session->killed)
 
758
    if (getKilled())
766
759
    {
767
760
      result=1;
768
761
      break;
769
762
    }
770
 
    session->wait_for_condition(LOCK_open, COND_refresh);
 
763
    wait_for_condition(LOCK_open, COND_refresh);
771
764
    LOCK_open.lock(); /* Wait for a table to unlock and then lock it */
772
765
  }
773
766
  return result;
788
781
    1   Fatal error (end of memory ?)
789
782
*/
790
783
 
791
 
static bool lock_table_names(Session *session, TableList *table_list)
 
784
bool Session::lock_table_names(TableList *table_list)
792
785
{
793
 
  bool got_all_locks=1;
 
786
  bool got_all_locks= true;
794
787
  TableList *lock_table;
795
788
 
796
789
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
797
790
  {
798
791
    int got_lock;
799
 
    if ((got_lock= lock_table_name(session, lock_table)) < 0)
800
 
      goto end;                                 // Fatal error
 
792
    if ((got_lock= lock_table_name(lock_table)) < 0)
 
793
    {
 
794
      table_list->unlock_table_names(table_list);
 
795
      return true; // Fatal error
 
796
    }
 
797
 
801
798
    if (got_lock)
802
 
      got_all_locks=0;                          // Someone is using table
 
799
      got_all_locks= false;                             // Someone is using table
803
800
  }
804
801
 
805
802
  /* If some table was in use, wait until we got the lock */
806
 
  if (!got_all_locks && wait_for_locked_table_names(session, table_list))
807
 
    goto end;
 
803
  if (not got_all_locks && wait_for_locked_table_names(table_list))
 
804
  {
 
805
    table_list->unlock_table_names(table_list);
 
806
 
 
807
    return true;
 
808
  }
 
809
 
808
810
  return false;
809
 
 
810
 
end:
811
 
  unlock_table_names(table_list, lock_table);
812
 
 
813
 
  return true;
814
811
}
815
812
 
816
813
 
817
814
/**
818
815
  Unlock all tables in list with a name lock.
819
816
 
820
 
  @param session        Thread handle.
821
817
  @param table_list Names of tables to lock.
822
818
 
823
819
  @note
833
829
  @retval FALSE Name lock successfully acquired.
834
830
*/
835
831
 
836
 
bool lock_table_names_exclusively(Session *session, TableList *table_list)
 
832
bool Session::lock_table_names_exclusively(TableList *table_list)
837
833
{
838
 
  if (lock_table_names(session, table_list))
 
834
  if (lock_table_names(table_list))
839
835
    return true;
840
836
 
841
837
  /*
872
868
    1   Fatal error (end of memory ?)
873
869
*/
874
870
 
875
 
void unlock_table_names(TableList *table_list, TableList *last_table)
 
871
void TableList::unlock_table_names(TableList *last_table)
876
872
{
877
 
  for (TableList *table= table_list;
878
 
       table != last_table;
879
 
       table= table->next_local)
880
 
    unlock_table_name(table);
881
 
  broadcast_refresh();
 
873
  for (TableList *table_iter= this;
 
874
       table_iter != last_table;
 
875
       table_iter= table_iter->next_local)
 
876
  {
 
877
    table_iter->unlock_table_name();
 
878
  }
 
879
 
 
880
  locking::broadcast_refresh();
882
881
}
883
882
 
884
883
 
946
945
  - call to wait_if_global_read_lock(). When this returns 0, no global read
947
946
  lock is owned; if argument abort_on_refresh was 0, none can be obtained.
948
947
  - job
949
 
  - if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
 
948
  - if abort_on_refresh was 0, call to session->startWaitingGlobalReadLock() to
950
949
  allow other threads to get the global read lock. I.e. removal of the
951
950
  protection.
952
951
  (Note: it's a bit like an implementation of rwlock).
967
966
  currently opened and being updated to close (so it's possible that there is
968
967
  a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
969
968
  READ LOCK is, too).
970
 
  3) make_global_read_lock_block_commit().
 
969
  3) session::makeGlobalReadLockBlockCommit().
971
970
  If we have merged 1) and 3) into 1), we would have had this deadlock:
972
971
  imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
973
972
  table t.
991
990
static volatile uint32_t protect_against_global_read_lock=0;
992
991
static volatile uint32_t waiting_for_read_lock=0;
993
992
 
994
 
#define GOT_GLOBAL_READ_LOCK               1
995
 
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
996
 
 
997
 
bool lock_global_read_lock(Session *session)
 
993
bool Session::lockGlobalReadLock()
998
994
{
999
 
  if (!session->global_read_lock)
 
995
  if (isGlobalReadLock() == Session::NONE)
1000
996
  {
1001
997
    const char *old_message;
1002
998
    LOCK_global_read_lock.lock();
1003
 
    old_message=session->enter_cond(COND_global_read_lock, LOCK_global_read_lock,
1004
 
                                    "Waiting to get readlock");
 
999
    old_message= enter_cond(COND_global_read_lock, LOCK_global_read_lock,
 
1000
                            "Waiting to get readlock");
1005
1001
 
1006
1002
    waiting_for_read_lock++;
1007
1003
    boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
1008
 
    while (protect_against_global_read_lock && !session->killed)
 
1004
    while (protect_against_global_read_lock && not getKilled())
1009
1005
      COND_global_read_lock.wait(scopedLock);
1010
1006
    waiting_for_read_lock--;
1011
1007
    scopedLock.release();
1012
 
    if (session->killed)
 
1008
    if (getKilled())
1013
1009
    {
1014
 
      session->exit_cond(old_message);
 
1010
      exit_cond(old_message);
1015
1011
      return true;
1016
1012
    }
1017
 
    session->global_read_lock= GOT_GLOBAL_READ_LOCK;
 
1013
    setGlobalReadLock(Session::GOT_GLOBAL_READ_LOCK);
1018
1014
    global_read_lock++;
1019
 
    session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1015
    exit_cond(old_message); // this unlocks LOCK_global_read_lock
1020
1016
  }
 
1017
 
1021
1018
  /*
1022
1019
    We DON'T set global_read_lock_blocks_commit now, it will be set after
1023
1020
    tables are flushed (as the present function serves for FLUSH TABLES WITH
1030
1027
}
1031
1028
 
1032
1029
 
1033
 
void unlock_global_read_lock(Session *session)
 
1030
void Session::unlockGlobalReadLock(void)
1034
1031
{
1035
1032
  uint32_t tmp;
1036
1033
 
1037
1034
  {
1038
1035
    boost_unique_lock_t scopedLock(LOCK_global_read_lock);
1039
1036
    tmp= --global_read_lock;
1040
 
    if (session->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
 
1037
    if (isGlobalReadLock() == Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1041
1038
      --global_read_lock_blocks_commit;
1042
1039
  }
1043
1040
  /* Send the signal outside the mutex to avoid a context switch */
1044
 
  if (!tmp)
 
1041
  if (not tmp)
1045
1042
  {
1046
1043
    COND_global_read_lock.notify_all();
1047
1044
  }
1048
 
  session->global_read_lock= 0;
 
1045
  setGlobalReadLock(Session::NONE);
1049
1046
}
1050
1047
 
1051
1048
static inline bool must_wait(bool is_not_commit)
1055
1052
          global_read_lock_blocks_commit));
1056
1053
}
1057
1054
 
1058
 
bool wait_if_global_read_lock(Session *session, bool abort_on_refresh,
1059
 
                              bool is_not_commit)
 
1055
bool Session::wait_if_global_read_lock(bool abort_on_refresh, bool is_not_commit)
1060
1056
{
1061
1057
  const char *old_message= NULL;
1062
1058
  bool result= 0, need_exit_cond;
1071
1067
  LOCK_global_read_lock.lock();
1072
1068
  if ((need_exit_cond= must_wait(is_not_commit)))
1073
1069
  {
1074
 
    if (session->global_read_lock)              // This thread had the read locks
 
1070
    if (isGlobalReadLock())             // This thread had the read locks
1075
1071
    {
1076
1072
      if (is_not_commit)
1077
1073
        my_message(ER_CANT_UPDATE_WITH_READLOCK,
1084
1080
      */
1085
1081
      return is_not_commit;
1086
1082
    }
1087
 
    old_message=session->enter_cond(COND_global_read_lock, LOCK_global_read_lock,
1088
 
                                    "Waiting for release of readlock");
1089
 
    while (must_wait(is_not_commit) && ! session->killed &&
1090
 
           (!abort_on_refresh || session->version == refresh_version))
 
1083
    old_message= enter_cond(COND_global_read_lock, LOCK_global_read_lock,
 
1084
                            "Waiting for release of readlock");
 
1085
 
 
1086
    while (must_wait(is_not_commit) && not getKilled() &&
 
1087
           (!abort_on_refresh || version == refresh_version))
1091
1088
    {
1092
1089
      boost_unique_lock_t scoped(LOCK_global_read_lock, boost::adopt_lock_t());
1093
1090
      COND_global_read_lock.wait(scoped);
1094
1091
      scoped.release();
1095
1092
    }
1096
 
    if (session->killed)
 
1093
    if (getKilled())
1097
1094
      result=1;
1098
1095
  }
1099
 
  if (!abort_on_refresh && !result)
 
1096
  if (not abort_on_refresh && not result)
1100
1097
    protect_against_global_read_lock++;
 
1098
 
1101
1099
  /*
1102
1100
    The following is only true in case of a global read locks (which is rare)
1103
1101
    and if old_message is set
1104
1102
  */
1105
1103
  if (unlikely(need_exit_cond))
1106
 
    session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1104
  {
 
1105
    exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1106
  }
1107
1107
  else
 
1108
  {
1108
1109
    LOCK_global_read_lock.unlock();
 
1110
  }
 
1111
 
1109
1112
  return result;
1110
1113
}
1111
1114
 
1112
1115
 
1113
 
void start_waiting_global_read_lock(Session *session)
 
1116
void Session::startWaitingGlobalReadLock()
1114
1117
{
1115
1118
  bool tmp;
1116
 
  if (unlikely(session->global_read_lock))
 
1119
  if (unlikely(isGlobalReadLock()))
1117
1120
    return;
 
1121
 
1118
1122
  LOCK_global_read_lock.lock();
1119
1123
  tmp= (!--protect_against_global_read_lock &&
1120
1124
        (waiting_for_read_lock || global_read_lock_blocks_commit));
1121
1125
  LOCK_global_read_lock.unlock();
 
1126
 
1122
1127
  if (tmp)
1123
1128
    COND_global_read_lock.notify_all();
1124
 
  return;
1125
1129
}
1126
1130
 
1127
1131
 
1128
 
bool make_global_read_lock_block_commit(Session *session)
 
1132
bool Session::makeGlobalReadLockBlockCommit()
1129
1133
{
1130
1134
  bool error;
1131
1135
  const char *old_message;
1132
1136
  /*
1133
1137
    If we didn't succeed lock_global_read_lock(), or if we already suceeded
1134
 
    make_global_read_lock_block_commit(), do nothing.
 
1138
    Session::makeGlobalReadLockBlockCommit(), do nothing.
1135
1139
  */
1136
 
  if (session->global_read_lock != GOT_GLOBAL_READ_LOCK)
 
1140
  if (isGlobalReadLock() != Session::GOT_GLOBAL_READ_LOCK)
1137
1141
    return false;
1138
1142
  LOCK_global_read_lock.lock();
1139
1143
  /* increment this BEFORE waiting on cond (otherwise race cond) */
1140
1144
  global_read_lock_blocks_commit++;
1141
 
  old_message= session->enter_cond(COND_global_read_lock, LOCK_global_read_lock,
1142
 
                                   "Waiting for all running commits to finish");
1143
 
  while (protect_against_global_read_lock && !session->killed)
 
1145
  old_message= enter_cond(COND_global_read_lock, LOCK_global_read_lock,
 
1146
                          "Waiting for all running commits to finish");
 
1147
  while (protect_against_global_read_lock && not getKilled())
1144
1148
  {
1145
1149
    boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
1146
1150
    COND_global_read_lock.wait(scopedLock);
1147
1151
    scopedLock.release();
1148
1152
  }
1149
 
  if ((error= test(session->killed)))
 
1153
  if ((error= test(getKilled())))
 
1154
  {
1150
1155
    global_read_lock_blocks_commit--; // undo what we did
 
1156
  }
1151
1157
  else
1152
 
    session->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1153
 
  session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1158
  {
 
1159
    setGlobalReadLock(Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT);
 
1160
  }
 
1161
 
 
1162
  exit_cond(old_message); // this unlocks LOCK_global_read_lock
 
1163
 
1154
1164
  return error;
1155
1165
}
1156
1166
 
1174
1184
    handling, it is not necessary to also signal COND_refresh.
1175
1185
*/
1176
1186
 
 
1187
namespace locking {
 
1188
 
1177
1189
void broadcast_refresh(void)
1178
1190
{
1179
1191
  COND_refresh.notify_all();
1180
1192
  COND_global_read_lock.notify_all();
1181
1193
}
1182
1194
 
 
1195
}
 
1196
 
1183
1197
 
1184
1198
/**
1185
1199
  @} (end of group Locking)