~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/locking/global.cc

  • Committer: Monty Taylor
  • Date: 2010-12-26 01:32:11 UTC
  • mto: This revision was merged to the branch mainline in revision 2038.
  • Revision ID: mordred@inaugust.com-20101226013211-c1tx52h7evovmijg
fixed dict and eval.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
    Copyright (C) 2011 Brian Aker
3
 
    Copyright (C) 2000-2006 MySQL AB
 
1
/* Copyright (C) 2000-2006 MySQL AB
4
2
 
5
3
   This program is free software; you can redistribute it and/or modify
6
4
   it under the terms of the GNU General Public License as published by
19
17
/**
20
18
  @file
21
19
 
22
 
  @note this is out of date, just for historical reference 
23
 
 
24
 
  Locking functions for drizzled.
 
20
  Locking functions for mysql.
25
21
 
26
22
  Because of the new concurrent inserts, we must first get external locks
27
23
  before getting internal locks.  If we do it in the other order, the status
34
30
  - For each SQL statement lockTables() is called for all involved
35
31
    tables.
36
32
    - lockTables() will call
37
 
      cursor->external_lock(session,locktype) for each table.
 
33
      table_handler->external_lock(session,locktype) for each table.
38
34
      This is followed by a call to thr_multi_lock() for all tables.
39
35
 
40
36
  - When statement is done, we call unlockTables().
77
73
  we are forced to use mysql_lock_merge.
78
74
*/
79
75
#include "config.h"
80
 
 
81
76
#include <fcntl.h>
82
 
 
83
77
#include <drizzled/error.h>
84
78
#include <drizzled/my_hash.h>
85
79
#include <drizzled/thr_lock.h>
86
80
#include <drizzled/session.h>
87
81
#include <drizzled/sql_base.h>
88
82
#include <drizzled/lock.h>
89
 
#include <drizzled/pthread_globals.h>
90
 
#include <drizzled/internal/my_sys.h>
91
 
#include <drizzled/pthread_globals.h>
92
 
#include <drizzled/refresh_version.h>
93
 
#include <drizzled/plugin/storage_engine.h>
 
83
#include "drizzled/pthread_globals.h"
 
84
#include "drizzled/internal/my_sys.h"
 
85
#include "drizzled/pthread_globals.h"
94
86
 
95
87
#include <set>
96
88
#include <vector>
130
122
                                              lockTables() should
131
123
                                              notify upper level and rely
132
124
                                              on caller doing this.
 
125
    need_reopen                 Out parameter, TRUE if some tables were altered
 
126
                                or deleted and should be reopened by caller.
133
127
 
134
128
  RETURN
135
129
    A lock structure pointer on success.
137
131
*/
138
132
 
139
133
/* Map the return value of thr_lock to an error from errmsg.txt */
140
 
static drizzled::error_t thr_lock_errno_to_mysql[]=
141
 
{ EE_OK, EE_ERROR_FIRST, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
 
134
static int thr_lock_errno_to_mysql[]=
 
135
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
142
136
 
143
137
 
144
138
/**
169
163
  *mysql_lock= 0;
170
164
}
171
165
 
172
 
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags)
 
166
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
173
167
{
174
168
  DrizzleLock *sql_lock;
175
169
  Table *write_lock_used;
176
170
  vector<plugin::StorageEngine *> involved_engines;
177
 
 
178
 
  do
 
171
  int rc;
 
172
 
 
173
  *need_reopen= false;
 
174
 
 
175
  for (;;)
179
176
  {
180
 
    if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
 
177
    if (! (sql_lock= get_lock_data(tables, count, true,
 
178
                                   &write_lock_used)))
181
179
      break;
182
180
 
183
 
    if (global_read_lock && write_lock_used and (not (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK)))
 
181
    if (global_read_lock && write_lock_used &&
 
182
        ! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK))
184
183
    {
185
184
      /*
186
185
        Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
192
191
        reset_lock_data_and_free(&sql_lock);
193
192
        break;
194
193
      }
195
 
 
196
194
      if (version != refresh_version)
197
195
      {
198
196
        /* Clear the lock type of all lock data to avoid reusage. */
199
197
        reset_lock_data_and_free(&sql_lock);
200
 
        break;
 
198
        goto retry;
201
199
      }
202
200
    }
203
201
    
210
208
    {
211
209
      size_t num_tables= sql_lock->sizeTable();
212
210
      plugin::StorageEngine *engine;
213
 
      std::set<size_t> involved_slots;
214
 
 
 
211
      set<size_t> involved_slots;
215
212
      for (size_t x= 1; x <= num_tables; x++, tables++)
216
213
      {
217
214
        engine= (*tables)->cursor->getEngine();
218
 
 
219
215
        if (involved_slots.count(engine->getId()) > 0)
220
216
          continue; /* already added to involved engines */
221
 
 
222
217
        involved_engines.push_back(engine);
223
218
        involved_slots.insert(engine->getId());
224
219
      }
246
241
    memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
247
242
           sql_lock->getLocks(),
248
243
           sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
249
 
 
250
244
    /* Lock on the copied half of the lock data array. */
251
 
    drizzled::error_t rc;
252
245
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this,
253
246
                                                     sql_lock->getLocks() +
254
247
                                                     sql_lock->sizeLock(),
255
248
                                                     sql_lock->sizeLock(),
256
249
                                                     this->lock_id)];
257
 
    if (rc)                                 /* a timeout or a deadlock */
 
250
    if (rc > 1)                                 /* a timeout or a deadlock */
258
251
    {
259
252
      if (sql_lock->sizeTable())
260
253
        unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
261
254
      reset_lock_data_and_free(&sql_lock);
262
255
      my_error(rc, MYF(0));
263
 
    }
264
 
  } while(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
  }
265
313
 
266
314
  set_proc_info(0);
267
315
  if (getKilled())
273
321
      sql_lock= NULL;
274
322
    }
275
323
  }
276
 
 
277
324
  set_time_after_lock();
278
 
 
279
325
  return (sql_lock);
280
326
}
281
327
 
620
666
 
621
667
int Session::lock_table_name(TableList *table_list)
622
668
{
623
 
  identifier::Table identifier(table_list->getSchemaName(), table_list->getTableName());
624
 
  const identifier::Table::Key &key(identifier.getKey());
 
669
  TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
 
670
  const TableIdentifier::Key &key(identifier.getKey());
625
671
 
626
672
  {
627
673
    /* Only insert the table if we haven't insert it already */
828
874
 
829
875
static void print_lock_error(int error, const char *table)
830
876
{
831
 
  drizzled::error_t textno;
 
877
  int textno;
832
878
 
833
879
  switch (error) {
834
880
  case HA_ERR_LOCK_WAIT_TIMEOUT:
1041
1087
    if (getKilled())
1042
1088
      result=1;
1043
1089
  }
1044
 
 
1045
1090
  if (not abort_on_refresh && not result)
1046
1091
    protect_against_global_read_lock++;
1047
1092