2
Copyright (C) 2011 Brian Aker
3
Copyright (C) 2000-2006 MySQL AB
1
/* Copyright (C) 2000-2006 MySQL AB
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
22
@note this is out of date, just for historical reference
24
Locking functions for drizzled.
20
Locking functions for mysql.
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
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.
40
36
- When statement is done, we call unlockTables().
77
73
we are forced to use mysql_lock_merge.
79
75
#include "config.h"
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"
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 };
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)
174
168
DrizzleLock *sql_lock;
175
169
Table *write_lock_used;
176
170
vector<plugin::StorageEngine *> involved_engines;
180
if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
177
if (! (sql_lock= get_lock_data(tables, count, true,
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))
186
185
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
211
209
size_t num_tables= sql_lock->sizeTable();
212
210
plugin::StorageEngine *engine;
213
std::set<size_t> involved_slots;
211
set<size_t> involved_slots;
215
212
for (size_t x= 1; x <= num_tables; x++, tables++)
217
214
engine= (*tables)->cursor->getEngine();
219
215
if (involved_slots.count(engine->getId()) > 0)
220
216
continue; /* already added to involved engines */
222
217
involved_engines.push_back(engine);
223
218
involved_slots.insert(engine->getId());
246
241
memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
247
242
sql_lock->getLocks(),
248
243
sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
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(),
257
if (rc) /* a timeout or a deadlock */
250
if (rc > 1) /* a timeout or a deadlock */
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));
258
else if (rc == 1) /* aborted */
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
264
else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
267
Thread was killed or lock aborted. Let upper level close all
268
used tables and retry or give error.
272
else if (not open_tables)
274
// Only using temporary tables, no need to unlock
275
some_tables_deleted= false;
280
/* going to retry, unlock all tables */
281
if (sql_lock->sizeLock())
282
sql_lock->unlock(sql_lock->sizeLock());
284
if (sql_lock->sizeTable())
285
unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
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.
292
reset_lock_data_and_free(&sql_lock);
295
* Notify all involved engines that the
296
* SQL statement has ended
298
for_each(involved_engines.begin(),
299
involved_engines.end(),
300
bind2nd(mem_fun(&plugin::StorageEngine::endStatement), this));
302
if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
308
if (wait_for_tables(this))
310
break; // Couldn't open tables
266
314
set_proc_info(0);
621
667
int Session::lock_table_name(TableList *table_list)
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());
627
673
/* Only insert the table if we haven't insert it already */