~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/lock.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-09-17 00:08:20 UTC
  • mto: (1126.9.3 captain-20090915-01)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: osullivan.padraig@gmail.com-20090917000820-urd6p46qngi1okjp
Updated calls to some dtrace probes to cast the parameter to const char *
appropriately. Also, removed the additional variable in places that I was
using.

Show diffs side-by-side

added added

removed removed

Lines of Context:
72
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
 
#include "config.h"
76
 
#include <fcntl.h>
 
75
#include <drizzled/server_includes.h>
77
76
#include <drizzled/error.h>
78
 
#include <drizzled/my_hash.h>
79
 
#include <drizzled/thr_lock.h>
 
77
#include <mysys/hash.h>
 
78
#include <mysys/thr_lock.h>
80
79
#include <drizzled/session.h>
81
80
#include <drizzled/sql_base.h>
82
81
#include <drizzled/lock.h>
83
 
#include "drizzled/pthread_globals.h"
84
 
#include "drizzled/internal/my_sys.h"
85
 
 
86
 
#include <set>
87
 
#include <vector>
88
 
#include <algorithm>
89
 
#include <functional>
90
 
 
91
 
using namespace std;
92
 
 
93
 
namespace drizzled
94
 
{
95
82
 
96
83
/**
97
84
  @defgroup Locking Locking
179
166
{
180
167
  DRIZZLE_LOCK *sql_lock;
181
168
  Table *write_lock_used;
182
 
  vector<plugin::StorageEngine *> involved_engines;
183
169
  int rc;
184
170
 
185
171
  *need_reopen= false;
210
196
        goto retry;
211
197
      }
212
198
    }
213
 
    
214
 
    session->set_proc_info("Notify start statement");
215
 
    /*
216
 
     * Here, we advise all storage engines involved in the
217
 
     * statement that we are starting a new statement
218
 
     */
219
 
    if (sql_lock->table_count)
220
 
    {
221
 
      size_t num_tables= sql_lock->table_count;
222
 
      plugin::StorageEngine *engine;
223
 
      set<size_t> involved_slots;
224
 
      for (size_t x= 1; x <= num_tables; x++, tables++)
225
 
      {
226
 
        engine= (*tables)->cursor->engine;
227
 
        if (involved_slots.count(engine->getId()) > 0)
228
 
          continue; /* already added to involved engines */
229
 
        involved_engines.push_back(engine);
230
 
        involved_slots.insert(engine->getId());
231
 
      }
232
 
 
233
 
      for_each(involved_engines.begin(),
234
 
               involved_engines.end(),
235
 
               bind2nd(mem_fun(&plugin::StorageEngine::startStatement), session));
236
 
    }
237
 
 
238
 
    session->set_proc_info("External lock");
239
 
    /*
240
 
     * Here, the call to lock_external() informs the
241
 
     * all engines for all tables used in this statement
242
 
     * of the type of lock that Drizzle intends to take on a 
243
 
     * specific table.
244
 
     */
 
199
 
 
200
    session->set_proc_info("System lock");
245
201
    if (sql_lock->table_count && lock_external(session, sql_lock->table,
246
202
                                               sql_lock->table_count))
247
203
    {
301
257
      type for other tables preserved.
302
258
    */
303
259
    reset_lock_data_and_free(&sql_lock);
304
 
 
305
 
    /*
306
 
     * Notify all involved engines that the
307
 
     * SQL statement has ended
308
 
     */
309
 
    for_each(involved_engines.begin(),
310
 
             involved_engines.end(),
311
 
             bind2nd(mem_fun(&plugin::StorageEngine::endStatement), session));
312
260
retry:
313
261
    if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
314
262
    {
328
276
      sql_lock= NULL;
329
277
    }
330
278
  }
 
279
 
331
280
  session->set_time_after_lock();
332
281
  return (sql_lock);
333
282
}
346
295
         (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
347
296
      lock_type=F_RDLCK;
348
297
 
349
 
    if ((error=(*tables)->cursor->ha_external_lock(session,lock_type)))
 
298
    if ((error=(*tables)->file->ha_external_lock(session,lock_type)))
350
299
    {
351
 
      print_lock_error(error, (*tables)->cursor->engine->getName().c_str());
 
300
      print_lock_error(error, (*tables)->file->engine->getName().c_str());
352
301
      while (--i)
353
302
      {
354
303
        tables--;
355
 
        (*tables)->cursor->ha_external_lock(session, F_UNLCK);
 
304
        (*tables)->file->ha_external_lock(session, F_UNLCK);
356
305
        (*tables)->current_lock=F_UNLCK;
357
306
      }
358
307
      return error;
528
477
  return result;
529
478
}
530
479
 
 
480
 
 
481
/**
 
482
  Find duplicate lock in tables.
 
483
 
 
484
  Temporary tables are ignored here like they are ignored in
 
485
  get_lock_data(). If we allow two opens on temporary tables later,
 
486
  both functions should be checked.
 
487
 
 
488
  @param session                 The current thread.
 
489
  @param needle              The table to check for duplicate lock.
 
490
  @param haystack            The list of tables to search for the dup lock.
 
491
 
 
492
  @note
 
493
    This is mainly meant for MERGE tables in INSERT ... SELECT
 
494
    situations. The 'real', underlying tables can be found only after
 
495
    the MERGE tables are opened. This function assumes that the tables are
 
496
    already locked.
 
497
 
 
498
  @retval
 
499
    NULL    No duplicate lock found.
 
500
  @retval
 
501
    !NULL   First table from 'haystack' that matches a lock on 'needle'.
 
502
*/
 
503
 
 
504
TableList *mysql_lock_have_duplicate(Session *session, TableList *needle,
 
505
                                      TableList *haystack)
 
506
{
 
507
  DRIZZLE_LOCK            *mylock;
 
508
  Table                 **lock_tables;
 
509
  Table                 *table;
 
510
  Table                 *table2;
 
511
  THR_LOCK_DATA         **lock_locks;
 
512
  THR_LOCK_DATA         **table_lock_data;
 
513
  THR_LOCK_DATA         **end_data;
 
514
  THR_LOCK_DATA         **lock_data2;
 
515
  THR_LOCK_DATA         **end_data2;
 
516
 
 
517
  /*
 
518
    Table may not be defined for derived or view tables.
 
519
    Table may not be part of a lock for delayed operations.
 
520
  */
 
521
  if (! (table= needle->table) || ! table->lock_count)
 
522
    goto end;
 
523
 
 
524
  /* A temporary table does not have locks. */
 
525
  if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
 
526
    goto end;
 
527
 
 
528
  /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
 
529
  if (!(mylock= session->lock))
 
530
    goto end;
 
531
 
 
532
  /* If we have less than two tables, we cannot have duplicates. */
 
533
  if (mylock->table_count < 2)
 
534
    goto end;
 
535
 
 
536
  lock_locks=  mylock->locks;
 
537
  lock_tables= mylock->table;
 
538
 
 
539
  /* Prepare table related variables that don't change in loop. */
 
540
  assert((table->lock_position < mylock->table_count) &&
 
541
              (table == lock_tables[table->lock_position]));
 
542
  table_lock_data= lock_locks + table->lock_data_start;
 
543
  end_data= table_lock_data + table->lock_count;
 
544
 
 
545
  for (; haystack; haystack= haystack->next_global)
 
546
  {
 
547
    if (haystack->placeholder())
 
548
      continue;
 
549
    table2= haystack->table;
 
550
    if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
 
551
      continue;
 
552
 
 
553
    /* All tables in list must be in lock. */
 
554
    assert((table2->lock_position < mylock->table_count) &&
 
555
                (table2 == lock_tables[table2->lock_position]));
 
556
 
 
557
    for (lock_data2=  lock_locks + table2->lock_data_start,
 
558
           end_data2= lock_data2 + table2->lock_count;
 
559
         lock_data2 < end_data2;
 
560
         lock_data2++)
 
561
    {
 
562
      THR_LOCK_DATA **lock_data;
 
563
      THR_LOCK *lock2= (*lock_data2)->lock;
 
564
 
 
565
      for (lock_data= table_lock_data;
 
566
           lock_data < end_data;
 
567
           lock_data++)
 
568
      {
 
569
        if ((*lock_data)->lock == lock2)
 
570
          return haystack;
 
571
      }
 
572
    }
 
573
  }
 
574
 
 
575
 end:
 
576
  return NULL;
 
577
}
 
578
 
 
579
 
531
580
/** Unlock a set of external. */
532
581
 
533
582
static int unlock_external(Session *session, Table **table,uint32_t count)
540
589
    if ((*table)->current_lock != F_UNLCK)
541
590
    {
542
591
      (*table)->current_lock = F_UNLCK;
543
 
      if ((error=(*table)->cursor->ha_external_lock(session, F_UNLCK)))
 
592
      if ((error=(*table)->file->ha_external_lock(session, F_UNLCK)))
544
593
      {
545
594
        error_code=error;
546
 
        print_lock_error(error_code, (*table)->cursor->engine->getName().c_str());
 
595
        print_lock_error(error_code, (*table)->file->engine->getName().c_str());
547
596
      }
548
597
    }
549
598
    table++;
576
625
  {
577
626
    Table *t= table_ptr[i];
578
627
 
579
 
    if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)))
 
628
    if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
580
629
    {
581
630
      tables++;
582
631
      lock_count++;
603
652
    Table *table;
604
653
    enum thr_lock_type lock_type;
605
654
 
606
 
    if (table_ptr[i]->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK))
 
655
    if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
607
656
      continue;
608
 
 
609
 
    table= table_ptr[i];
610
657
    lock_type= table->reginfo.lock_type;
611
658
    assert (lock_type != TL_WRITE_DEFAULT);
612
659
    if (lock_type >= TL_WRITE_ALLOW_WRITE)
622
669
      }
623
670
    }
624
671
    locks_start= locks;
625
 
    locks= table->cursor->store_lock(session, locks,
 
672
    locks= table->file->store_lock(session, locks,
626
673
                                   should_lock == false ? TL_IGNORE : lock_type);
627
674
    if (should_lock)
628
675
    {
1048
1095
  session->global_read_lock= 0;
1049
1096
}
1050
1097
 
1051
 
static inline bool must_wait(bool is_not_commit)
1052
 
{
1053
 
  return (global_read_lock &&
1054
 
          (is_not_commit ||
1055
 
          global_read_lock_blocks_commit));
1056
 
}
 
1098
#define must_wait (global_read_lock &&                             \
 
1099
                   (is_not_commit ||                               \
 
1100
                    global_read_lock_blocks_commit))
1057
1101
 
1058
1102
bool wait_if_global_read_lock(Session *session, bool abort_on_refresh,
1059
1103
                              bool is_not_commit)
1069
1113
  safe_mutex_assert_not_owner(&LOCK_open);
1070
1114
 
1071
1115
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
1072
 
  if ((need_exit_cond= must_wait(is_not_commit)))
 
1116
  if ((need_exit_cond= must_wait))
1073
1117
  {
1074
1118
    if (session->global_read_lock)              // This thread had the read locks
1075
1119
    {
1086
1130
    }
1087
1131
    old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1088
1132
                                "Waiting for release of readlock");
1089
 
    while (must_wait(is_not_commit) && ! session->killed &&
 
1133
    while (must_wait && ! session->killed &&
1090
1134
           (!abort_on_refresh || session->version == refresh_version))
1091
1135
    {
1092
1136
      (void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1178
1222
/**
1179
1223
  @} (end of group Locking)
1180
1224
*/
1181
 
 
1182
 
} /* namespace drizzled */