~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/locking/global.cc

mergeĀ lp:~hingo/drizzle/drizzle-auth_ldap-fix-and-docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB
 
1
/* 
 
2
    Copyright (C) 2011 Brian Aker
 
3
    Copyright (C) 2000-2006 MySQL AB
2
4
 
3
5
   This program is free software; you can redistribute it and/or modify
4
6
   it under the terms of the GNU General Public License as published by
17
19
/**
18
20
  @file
19
21
 
20
 
  Locking functions for mysql.
 
22
  @note this is out of date, just for historical reference 
 
23
 
 
24
  Locking functions for drizzled.
21
25
 
22
26
  Because of the new concurrent inserts, we must first get external locks
23
27
  before getting internal locks.  If we do it in the other order, the status
30
34
  - For each SQL statement lockTables() is called for all involved
31
35
    tables.
32
36
    - lockTables() will call
33
 
      table_handler->external_lock(session,locktype) for each table.
 
37
      cursor->external_lock(session,locktype) for each table.
34
38
      This is followed by a call to thr_multi_lock() for all tables.
35
39
 
36
40
  - When statement is done, we call unlockTables().
72
76
  Change to use malloc() ONLY when using LOCK TABLES command or when
73
77
  we are forced to use mysql_lock_merge.
74
78
*/
75
 
#include "config.h"
 
79
#include <config.h>
 
80
 
76
81
#include <fcntl.h>
 
82
 
77
83
#include <drizzled/error.h>
78
 
#include <drizzled/my_hash.h>
79
84
#include <drizzled/thr_lock.h>
80
85
#include <drizzled/session.h>
 
86
#include <drizzled/session/times.h>
81
87
#include <drizzled/sql_base.h>
82
88
#include <drizzled/lock.h>
83
 
#include "drizzled/pthread_globals.h"
84
 
#include "drizzled/internal/my_sys.h"
85
 
#include "drizzled/pthread_globals.h"
 
89
#include <drizzled/pthread_globals.h>
 
90
#include <drizzled/internal/my_sys.h>
 
91
#include <drizzled/pthread_globals.h>
 
92
#include <drizzled/plugin/storage_engine.h>
 
93
#include <drizzled/util/test.h>
 
94
#include <drizzled/open_tables_state.h>
 
95
#include <drizzled/table/cache.h>
86
96
 
87
97
#include <set>
88
98
#include <vector>
122
132
                                              lockTables() should
123
133
                                              notify upper level and rely
124
134
                                              on caller doing this.
125
 
    need_reopen                 Out parameter, TRUE if some tables were altered
126
 
                                or deleted and should be reopened by caller.
127
135
 
128
136
  RETURN
129
137
    A lock structure pointer on success.
131
139
*/
132
140
 
133
141
/* Map the return value of thr_lock to an error from errmsg.txt */
134
 
static int thr_lock_errno_to_mysql[]=
135
 
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
 
142
static drizzled::error_t thr_lock_errno_to_mysql[]=
 
143
{ EE_OK, EE_ERROR_FIRST, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
136
144
 
137
145
 
138
146
/**
155
163
        lock request will set its lock type properly.
156
164
*/
157
165
 
158
 
static void reset_lock_data_and_free(DrizzleLock **mysql_lock)
 
166
static void reset_lock_data_and_free(DrizzleLock*& lock)
159
167
{
160
 
  DrizzleLock *sql_lock= *mysql_lock;
161
 
  sql_lock->reset();
162
 
  delete sql_lock;
163
 
  *mysql_lock= 0;
 
168
  lock->reset();
 
169
  delete lock;
 
170
  lock= NULL;
164
171
}
165
172
 
166
 
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
 
173
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags)
167
174
{
168
175
  DrizzleLock *sql_lock;
169
176
  Table *write_lock_used;
170
177
  vector<plugin::StorageEngine *> involved_engines;
171
 
  int rc;
172
 
 
173
 
  *need_reopen= false;
174
 
 
175
 
  for (;;)
 
178
 
 
179
  do
176
180
  {
177
 
    if (! (sql_lock= get_lock_data(tables, count, true,
178
 
                                   &write_lock_used)))
 
181
    if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
179
182
      break;
180
183
 
181
 
    if (global_read_lock && write_lock_used &&
182
 
        ! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK))
 
184
    if (global_read_lock && write_lock_used and (not (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK)))
183
185
    {
184
186
      /*
185
187
        Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
188
190
      if (wait_if_global_read_lock(1, 1))
189
191
      {
190
192
        /* Clear the lock type of all lock data to avoid reusage. */
191
 
        reset_lock_data_and_free(&sql_lock);
 
193
        reset_lock_data_and_free(sql_lock);
192
194
        break;
193
195
      }
194
 
      if (version != refresh_version)
 
196
 
 
197
      if (open_tables.version != g_refresh_version)
195
198
      {
196
199
        /* Clear the lock type of all lock data to avoid reusage. */
197
 
        reset_lock_data_and_free(&sql_lock);
198
 
        goto retry;
 
200
        reset_lock_data_and_free(sql_lock);
 
201
        break;
199
202
      }
200
203
    }
201
204
    
208
211
    {
209
212
      size_t num_tables= sql_lock->sizeTable();
210
213
      plugin::StorageEngine *engine;
211
 
      set<size_t> involved_slots;
 
214
      std::set<size_t> involved_slots;
 
215
 
212
216
      for (size_t x= 1; x <= num_tables; x++, tables++)
213
217
      {
214
218
        engine= (*tables)->cursor->getEngine();
 
219
 
215
220
        if (involved_slots.count(engine->getId()) > 0)
216
221
          continue; /* already added to involved engines */
 
222
 
217
223
        involved_engines.push_back(engine);
218
224
        involved_slots.insert(engine->getId());
219
225
      }
233
239
    if (sql_lock->sizeTable() && lock_external(sql_lock->getTable(), sql_lock->sizeTable()))
234
240
    {
235
241
      /* Clear the lock type of all lock data to avoid reusage. */
236
 
      reset_lock_data_and_free(&sql_lock);
 
242
      reset_lock_data_and_free(sql_lock);
237
243
      break;
238
244
    }
239
245
    set_proc_info("Table lock");
241
247
    memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
242
248
           sql_lock->getLocks(),
243
249
           sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
 
250
 
244
251
    /* Lock on the copied half of the lock data array. */
 
252
    drizzled::error_t rc;
245
253
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this,
246
254
                                                     sql_lock->getLocks() +
247
255
                                                     sql_lock->sizeLock(),
248
256
                                                     sql_lock->sizeLock(),
249
257
                                                     this->lock_id)];
250
 
    if (rc > 1)                                 /* a timeout or a deadlock */
 
258
    if (rc)                                 /* a timeout or a deadlock */
251
259
    {
252
260
      if (sql_lock->sizeTable())
253
261
        unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
254
 
      reset_lock_data_and_free(&sql_lock);
 
262
      reset_lock_data_and_free(sql_lock);
255
263
      my_error(rc, MYF(0));
256
 
      break;
257
 
    }
258
 
    else if (rc == 1)                           /* aborted */
259
 
    {
260
 
      some_tables_deleted= true;                // Try again
261
 
      sql_lock->setLock(0);                  // Locks are already freed
262
 
      // Fall through: unlock, reset lock data, free and retry
263
 
    }
264
 
    else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
265
 
    {
266
 
      /*
267
 
        Thread was killed or lock aborted. Let upper level close all
268
 
        used tables and retry or give error.
269
 
      */
270
 
      break;
271
 
    }
272
 
    else if (not open_tables)
273
 
    {
274
 
      // Only using temporary tables, no need to unlock
275
 
      some_tables_deleted= false;
276
 
      break;
277
 
    }
278
 
    set_proc_info(0);
279
 
 
280
 
    /* going to retry, unlock all tables */
281
 
    if (sql_lock->sizeLock())
282
 
        sql_lock->unlock(sql_lock->sizeLock());
283
 
 
284
 
    if (sql_lock->sizeTable())
285
 
      unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
286
 
 
287
 
    /*
288
 
      If thr_multi_lock fails it resets lock type for tables, which
289
 
      were locked before (and including) one that caused error. Lock
290
 
      type for other tables preserved.
291
 
    */
292
 
    reset_lock_data_and_free(&sql_lock);
293
 
 
294
 
    /*
295
 
     * Notify all involved engines that the
296
 
     * SQL statement has ended
297
 
     */
298
 
    for_each(involved_engines.begin(),
299
 
             involved_engines.end(),
300
 
             bind2nd(mem_fun(&plugin::StorageEngine::endStatement), this));
301
 
retry:
302
 
    if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
303
 
    {
304
 
      *need_reopen= true;
305
 
      break;
306
 
    }
307
 
 
308
 
    if (wait_for_tables(this))
309
 
    {
310
 
      break;                                    // Couldn't open tables
311
 
    }
312
 
  }
 
264
    }
 
265
  } while(0);
313
266
 
314
267
  set_proc_info(0);
315
268
  if (getKilled())
321
274
      sql_lock= NULL;
322
275
    }
323
276
  }
324
 
  set_time_after_lock();
325
 
  return (sql_lock);
 
277
 
 
278
  times.set_time_after_lock();
 
279
 
 
280
  return sql_lock;
326
281
}
327
282
 
328
283
 
334
289
    assert((*tables)->reginfo.lock_type >= TL_READ);
335
290
    lock_type=F_WRLCK;                          /* Lock exclusive */
336
291
    if ((*tables)->db_stat & HA_READ_ONLY ||
337
 
        ((*tables)->reginfo.lock_type >= TL_READ &&
338
 
         (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
 
292
      ((*tables)->reginfo.lock_type >= TL_READ &&
 
293
      (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
339
294
      lock_type=F_RDLCK;
340
295
 
341
296
    if ((error=(*tables)->cursor->ha_external_lock(this,lock_type)))
344
299
      while (--i)
345
300
      {
346
301
        tables--;
347
 
        (*tables)->cursor->ha_external_lock(this, F_UNLCK);
348
 
        (*tables)->current_lock=F_UNLCK;
 
302
        (*tables)->cursor->ha_external_lock(this, F_UNLCK);
 
303
        (*tables)->current_lock=F_UNLCK;
349
304
      }
350
305
      return error;
351
306
    }
500
455
 
501
456
bool Session::abortLockForThread(Table *table)
502
457
{
503
 
  DrizzleLock *locked;
504
 
  Table *write_lock_used;
505
458
  bool result= false;
506
 
 
507
 
  if ((locked= get_lock_data(&table, 1, false,
508
 
                             &write_lock_used)))
 
459
  Table* write_lock_used;
 
460
  if (DrizzleLock* locked= get_lock_data(&table, 1, false, &write_lock_used))
509
461
  {
510
462
    for (uint32_t i= 0; i < locked->sizeLock(); i++)
511
463
    {
521
473
 
522
474
int Session::unlock_external(Table **table, uint32_t count)
523
475
{
524
 
  int error,error_code;
 
476
  int error;
525
477
 
526
 
  error_code=0;
 
478
  int error_code=0;
527
479
  do
528
480
  {
529
481
    if ((*table)->current_lock != F_UNLCK)
587
539
  for (uint32_t i= 0; i < count ; i++)
588
540
  {
589
541
    Table *table;
590
 
    enum thr_lock_type lock_type;
 
542
    thr_lock_type lock_type;
591
543
 
592
544
    if (table_ptr[i]->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK))
593
545
      continue;
603
555
        my_error(ER_OPEN_AS_READONLY, MYF(0), table->getAlias());
604
556
        /* Clear the lock type of the lock data that are stored already. */
605
557
        sql_lock->setLock(locks - sql_lock->getLocks());
606
 
        reset_lock_data_and_free(&sql_lock);
 
558
        reset_lock_data_and_free(sql_lock);
607
559
        return NULL;
608
560
      }
609
561
    }
610
562
    locks_start= locks;
611
 
    locks= table->cursor->store_lock(this, locks, should_lock == false ? TL_IGNORE : lock_type);
 
563
    locks= table->cursor->store_lock(this, locks, should_lock ? lock_type : TL_IGNORE);
612
564
    if (should_lock)
613
565
    {
614
566
      table->lock_position=   (uint32_t) (to - table_buf);
645
597
  @param check_in_use           Do we need to check if table already in use by us
646
598
 
647
599
  @note
648
 
    One must have a lock on table::Cache::singleton().mutex()!
 
600
    One must have a lock on table::Cache::mutex()!
649
601
 
650
602
  @warning
651
603
    If you are going to update the table, you should use
666
618
 
667
619
int Session::lock_table_name(TableList *table_list)
668
620
{
669
 
  TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
670
 
  const TableIdentifier::Key &key(identifier.getKey());
671
 
 
 
621
  identifier::Table identifier(table_list->getSchemaName(), table_list->getTableName());
672
622
  {
673
623
    /* Only insert the table if we haven't insert it already */
674
 
    table::CacheRange ppp;
675
 
 
676
 
    ppp= table::getCache().equal_range(key);
677
 
 
678
 
    for (table::CacheMap::const_iterator iter= ppp.first;
679
 
         iter != ppp.second; ++iter)
 
624
    table::CacheRange ppp= table::getCache().equal_range(identifier.getKey());
 
625
    for (table::CacheMap::const_iterator iter= ppp.first; iter != ppp.second; ++iter)
680
626
    {
681
 
      Table *table= (*iter).second;
 
627
      Table *table= iter->second;
682
628
      if (table->reginfo.lock_type < TL_WRITE)
683
 
      {
684
629
        continue;
685
 
      }
686
 
 
687
630
      if (table->in_use == this)
688
631
      {
689
632
        table->getMutableShare()->resetVersion();                  // Ensure no one can use this
693
636
    }
694
637
  }
695
638
 
696
 
  table::Placeholder *table= NULL;
697
 
  if (!(table= table_cache_insert_placeholder(identifier)))
698
 
  {
699
 
    return -1;
700
 
  }
701
 
 
702
 
  table_list->table= reinterpret_cast<Table *>(table);
 
639
  table::Placeholder *table= &table_cache_insert_placeholder(identifier);
 
640
  table_list->table= reinterpret_cast<Table*>(table);
703
641
 
704
642
  /* Return 1 if table is in use */
705
 
  return(test(table::Cache::singleton().removeTable(this, identifier, RTFC_NO_FLAG)));
 
643
  return (test(table::Cache::removeTable(*this, identifier, RTFC_NO_FLAG)));
706
644
}
707
645
 
708
646
 
718
656
 
719
657
static bool locked_named_table(TableList *table_list)
720
658
{
721
 
  for (; table_list ; table_list=table_list->next_local)
 
659
  for (; table_list; table_list=table_list->next_local)
722
660
  {
723
661
    Table *table= table_list->table;
724
662
    if (table)
725
663
    {
726
664
      Table *save_next= table->getNext();
727
 
      bool result;
728
665
      table->setNext(NULL);
729
 
      result= table::Cache::singleton().areTablesUsed(table_list->table, 0);
 
666
      bool result= table::Cache::areTablesUsed(table_list->table, 0);
730
667
      table->setNext(save_next);
731
668
      if (result)
732
669
        return 1;
741
678
  bool result= false;
742
679
 
743
680
#if 0
744
 
  assert(ownership of table::Cache::singleton().mutex());
 
681
  assert(ownership of table::Cache::mutex());
745
682
#endif
746
683
 
747
684
  while (locked_named_table(table_list))
748
685
  {
749
686
    if (getKilled())
750
687
    {
751
 
      result=1;
 
688
      result= true;
752
689
      break;
753
690
    }
754
 
    wait_for_condition(table::Cache::singleton().mutex(), COND_refresh);
755
 
    table::Cache::singleton().mutex().lock(); /* Wait for a table to unlock and then lock it */
 
691
    wait_for_condition(table::Cache::mutex(), COND_refresh);
 
692
    table::Cache::mutex().lock(); /* Wait for a table to unlock and then lock it */
756
693
  }
757
694
  return result;
758
695
}
762
699
  Lock all tables in list with a name lock.
763
700
 
764
701
  REQUIREMENTS
765
 
  - One must have a lock on table::Cache::singleton().mutex() when calling this
 
702
  - One must have a lock on table::Cache::mutex() when calling this
766
703
 
767
704
  @param table_list             Names of tables to lock
768
705
 
775
712
bool Session::lock_table_names(TableList *table_list)
776
713
{
777
714
  bool got_all_locks= true;
778
 
  TableList *lock_table;
779
 
 
780
 
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
 
715
  for (TableList* lock_table= table_list; lock_table; lock_table= lock_table->next_local)
781
716
  {
782
 
    int got_lock;
783
 
    if ((got_lock= lock_table_name(lock_table)) < 0)
 
717
    int got_lock= lock_table_name(lock_table);
 
718
    if (got_lock < 0)
784
719
    {
785
720
      table_list->unlock_table_names(table_list);
786
721
      return true; // Fatal error
787
722
    }
788
 
 
789
723
    if (got_lock)
790
724
      got_all_locks= false;                             // Someone is using table
791
725
  }
794
728
  if (not got_all_locks && wait_for_locked_table_names(table_list))
795
729
  {
796
730
    table_list->unlock_table_names(table_list);
797
 
 
798
731
    return true;
799
732
  }
800
 
 
801
733
  return false;
802
734
}
803
735
 
808
740
  @param table_list Names of tables to lock.
809
741
 
810
742
  @note
811
 
    This function needs to be protected by table::Cache::singleton().mutex(). If we're
 
743
    This function needs to be protected by table::Cache::mutex(). If we're
812
744
    under LOCK TABLES, this function does not work as advertised. Namely,
813
745
    it does not exclude other threads from using this table and does not
814
746
    put an exclusive name lock on this table into the table cache.
847
779
                                (default 0, which will unlock all tables)
848
780
 
849
781
  @note
850
 
    One must have a lock on table::Cache::singleton().mutex() when calling this.
 
782
    One must have a lock on table::Cache::mutex() when calling this.
851
783
 
852
784
  @note
853
785
    This function will broadcast refresh signals to inform other threads
861
793
 
862
794
void TableList::unlock_table_names(TableList *last_table)
863
795
{
864
 
  for (TableList *table_iter= this;
865
 
       table_iter != last_table;
866
 
       table_iter= table_iter->next_local)
 
796
  for (TableList *table_iter= this; table_iter != last_table; table_iter= table_iter->next_local)
867
797
  {
868
798
    table_iter->unlock_table_name();
869
799
  }
870
 
 
871
800
  locking::broadcast_refresh();
872
801
}
873
802
 
874
803
 
875
804
static void print_lock_error(int error, const char *table)
876
805
{
877
 
  int textno;
878
 
 
879
 
  switch (error) {
 
806
  drizzled::error_t textno;
 
807
  switch (error) 
 
808
  {
880
809
  case HA_ERR_LOCK_WAIT_TIMEOUT:
881
810
    textno=ER_LOCK_WAIT_TIMEOUT;
882
811
    break;
922
851
 
923
852
  access to them is protected with a mutex LOCK_global_read_lock
924
853
 
925
 
  (XXX: one should never take table::Cache::singleton().mutex() if LOCK_global_read_lock is
 
854
  (XXX: one should never take table::Cache::mutex() if LOCK_global_read_lock is
926
855
  taken, otherwise a deadlock may occur. Other mutexes could be a
927
856
  problem too - grep the code for global_read_lock if you want to use
928
 
  any other mutex here) Also one must not hold table::Cache::singleton().mutex() when calling
 
857
  any other mutex here) Also one must not hold table::Cache::mutex() when calling
929
858
  wait_if_global_read_lock(). When the thread with the global read lock
930
 
  tries to close its tables, it needs to take table::Cache::singleton().mutex() in
 
859
  tries to close its tables, it needs to take table::Cache::mutex() in
931
860
  close_thread_table().
932
861
 
933
862
  How blocking of threads by global read lock is achieved: that's
991
920
                            "Waiting to get readlock");
992
921
 
993
922
    waiting_for_read_lock++;
994
 
    boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
 
923
    boost::mutex::scoped_lock scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
995
924
    while (protect_against_global_read_lock && not getKilled())
996
925
      COND_global_read_lock.wait(scopedLock);
997
926
    waiting_for_read_lock--;
1026
955
    return;
1027
956
 
1028
957
  {
1029
 
    boost_unique_lock_t scopedLock(LOCK_global_read_lock);
 
958
    boost::mutex::scoped_lock scopedLock(LOCK_global_read_lock);
1030
959
    tmp= --global_read_lock;
1031
960
    if (isGlobalReadLock() == Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1032
961
      --global_read_lock_blocks_commit;
1052
981
  bool result= 0, need_exit_cond;
1053
982
 
1054
983
  /*
1055
 
    Assert that we do not own table::Cache::singleton().mutex(). If we would own it, other
 
984
    Assert that we do not own table::Cache::mutex(). If we would own it, other
1056
985
    threads could not close their tables. This would make a pretty
1057
986
    deadlock.
1058
987
  */
1059
 
  safe_mutex_assert_not_owner(table::Cache::singleton().mutex().native_handle());
 
988
  safe_mutex_assert_not_owner(table::Cache::mutex().native_handle());
1060
989
 
1061
990
  LOCK_global_read_lock.lock();
1062
991
  if ((need_exit_cond= must_wait(is_not_commit)))
1078
1007
                            "Waiting for release of readlock");
1079
1008
 
1080
1009
    while (must_wait(is_not_commit) && not getKilled() &&
1081
 
           (!abort_on_refresh || version == refresh_version))
 
1010
           (!abort_on_refresh || open_tables.version == g_refresh_version))
1082
1011
    {
1083
 
      boost_unique_lock_t scoped(LOCK_global_read_lock, boost::adopt_lock_t());
 
1012
      boost::mutex::scoped_lock scoped(LOCK_global_read_lock, boost::adopt_lock_t());
1084
1013
      COND_global_read_lock.wait(scoped);
1085
1014
      scoped.release();
1086
1015
    }
1087
1016
    if (getKilled())
1088
1017
      result=1;
1089
1018
  }
 
1019
 
1090
1020
  if (not abort_on_refresh && not result)
1091
1021
    protect_against_global_read_lock++;
1092
1022
 
1109
1039
 
1110
1040
void Session::startWaitingGlobalReadLock()
1111
1041
{
1112
 
  bool tmp;
1113
1042
  if (unlikely(isGlobalReadLock()))
1114
1043
    return;
1115
1044
 
1116
1045
  LOCK_global_read_lock.lock();
1117
 
  tmp= (!--protect_against_global_read_lock &&
1118
 
        (waiting_for_read_lock || global_read_lock_blocks_commit));
 
1046
  bool tmp= (!--protect_against_global_read_lock && (waiting_for_read_lock || global_read_lock_blocks_commit));
1119
1047
  LOCK_global_read_lock.unlock();
1120
1048
 
1121
1049
  if (tmp)
1140
1068
                          "Waiting for all running commits to finish");
1141
1069
  while (protect_against_global_read_lock && not getKilled())
1142
1070
  {
1143
 
    boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
 
1071
    boost::mutex::scoped_lock scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
1144
1072
    COND_global_read_lock.wait(scopedLock);
1145
1073
    scopedLock.release();
1146
1074
  }
1165
1093
    Due to a bug in a threading library it could happen that a signal
1166
1094
    did not reach its target. A condition for this was that the same
1167
1095
    condition variable was used with different mutexes in
1168
 
    pthread_cond_wait(). Some time ago we changed table::Cache::singleton().mutex() to
 
1096
    pthread_cond_wait(). Some time ago we changed table::Cache::mutex() to
1169
1097
    LOCK_global_read_lock in global read lock handling. So COND_refresh
1170
 
    was used with table::Cache::singleton().mutex() and LOCK_global_read_lock.
 
1098
    was used with table::Cache::mutex() and LOCK_global_read_lock.
1171
1099
 
1172
1100
    We did now also change from COND_refresh to COND_global_read_lock
1173
1101
    in global read lock handling. But now it is necessary to signal
1178
1106
    handling, it is not necessary to also signal COND_refresh.
1179
1107
*/
1180
1108
 
1181
 
namespace locking {
1182
 
 
1183
 
void broadcast_refresh(void)
 
1109
void locking::broadcast_refresh()
1184
1110
{
1185
1111
  COND_refresh.notify_all();
1186
1112
  COND_global_read_lock.notify_all();
1187
1113
}
1188
1114
 
1189
 
}
1190
 
 
1191
 
 
1192
 
/**
1193
 
  @} (end of group Locking)
1194
 
*/
1195
 
 
1196
1115
} /* namespace drizzled */