~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/locking/global.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

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
84
#include <drizzled/my_hash.h>
79
85
#include <drizzled/thr_lock.h>
80
86
#include <drizzled/session.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/refresh_version.h>
 
93
#include <drizzled/plugin/storage_engine.h>
86
94
 
87
95
#include <set>
88
96
#include <vector>
122
130
                                              lockTables() should
123
131
                                              notify upper level and rely
124
132
                                              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
133
 
128
134
  RETURN
129
135
    A lock structure pointer on success.
131
137
*/
132
138
 
133
139
/* 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 };
 
140
static drizzled::error_t thr_lock_errno_to_mysql[]=
 
141
{ EE_OK, EE_ERROR_FIRST, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
136
142
 
137
143
 
138
144
/**
163
169
  *mysql_lock= 0;
164
170
}
165
171
 
166
 
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
 
172
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags)
167
173
{
168
174
  DrizzleLock *sql_lock;
169
175
  Table *write_lock_used;
170
176
  vector<plugin::StorageEngine *> involved_engines;
171
 
  int rc;
172
 
 
173
 
  *need_reopen= false;
174
 
 
175
 
  for (;;)
 
177
 
 
178
  do
176
179
  {
177
 
    if (! (sql_lock= get_lock_data(tables, count, true,
178
 
                                   &write_lock_used)))
 
180
    if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
179
181
      break;
180
182
 
181
 
    if (global_read_lock && write_lock_used &&
182
 
        ! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK))
 
183
    if (global_read_lock && write_lock_used and (not (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK)))
183
184
    {
184
185
      /*
185
186
        Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
191
192
        reset_lock_data_and_free(&sql_lock);
192
193
        break;
193
194
      }
 
195
 
194
196
      if (version != refresh_version)
195
197
      {
196
198
        /* Clear the lock type of all lock data to avoid reusage. */
197
199
        reset_lock_data_and_free(&sql_lock);
198
 
        goto retry;
 
200
        break;
199
201
      }
200
202
    }
201
203
    
208
210
    {
209
211
      size_t num_tables= sql_lock->sizeTable();
210
212
      plugin::StorageEngine *engine;
211
 
      set<size_t> involved_slots;
 
213
      std::set<size_t> involved_slots;
 
214
 
212
215
      for (size_t x= 1; x <= num_tables; x++, tables++)
213
216
      {
214
217
        engine= (*tables)->cursor->getEngine();
 
218
 
215
219
        if (involved_slots.count(engine->getId()) > 0)
216
220
          continue; /* already added to involved engines */
 
221
 
217
222
        involved_engines.push_back(engine);
218
223
        involved_slots.insert(engine->getId());
219
224
      }
241
246
    memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
242
247
           sql_lock->getLocks(),
243
248
           sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
 
249
 
244
250
    /* Lock on the copied half of the lock data array. */
 
251
    drizzled::error_t rc;
245
252
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this,
246
253
                                                     sql_lock->getLocks() +
247
254
                                                     sql_lock->sizeLock(),
248
255
                                                     sql_lock->sizeLock(),
249
256
                                                     this->lock_id)];
250
 
    if (rc > 1)                                 /* a timeout or a deadlock */
 
257
    if (rc)                                 /* a timeout or a deadlock */
251
258
    {
252
259
      if (sql_lock->sizeTable())
253
260
        unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
254
261
      reset_lock_data_and_free(&sql_lock);
255
262
      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
 
  }
 
263
    }
 
264
  } while(0);
313
265
 
314
266
  set_proc_info(0);
315
267
  if (getKilled())
321
273
      sql_lock= NULL;
322
274
    }
323
275
  }
 
276
 
324
277
  set_time_after_lock();
 
278
 
325
279
  return (sql_lock);
326
280
}
327
281
 
666
620
 
667
621
int Session::lock_table_name(TableList *table_list)
668
622
{
669
 
  TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
670
 
  const TableIdentifier::Key &key(identifier.getKey());
 
623
  identifier::Table identifier(table_list->getSchemaName(), table_list->getTableName());
 
624
  const identifier::Table::Key &key(identifier.getKey());
671
625
 
672
626
  {
673
627
    /* Only insert the table if we haven't insert it already */
874
828
 
875
829
static void print_lock_error(int error, const char *table)
876
830
{
877
 
  int textno;
 
831
  drizzled::error_t textno;
878
832
 
879
833
  switch (error) {
880
834
  case HA_ERR_LOCK_WAIT_TIMEOUT:
1087
1041
    if (getKilled())
1088
1042
      result=1;
1089
1043
  }
 
1044
 
1090
1045
  if (not abort_on_refresh && not result)
1091
1046
    protect_against_global_read_lock++;
1092
1047