~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/locking/global.cc

  • Committer: Andrew Hutchings
  • Date: 2011-01-23 21:32:31 UTC
  • mto: (2108.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2109.
  • Revision ID: andrew@linuxjedi.co.uk-20110123213231-dp2r4enepa9k4g36
Convert all unit tests to boost::test
Add pandora support for boost::test
Remove pandora support for gtest

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