1
/* Copyright (C) 2000-2006 MySQL AB
2
Copyright (C) 2011 Brian Aker
3
Copyright (C) 2000-2006 MySQL AB
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
20
Locking functions for mysql.
22
@note this is out of date, just for historical reference
24
Locking functions for drizzled.
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
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.
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.
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>
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 };
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)
168
174
DrizzleLock *sql_lock;
169
175
Table *write_lock_used;
170
176
vector<plugin::StorageEngine *> involved_engines;
177
if (! (sql_lock= get_lock_data(tables, count, true,
180
if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
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)))
185
186
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
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;
212
215
for (size_t x= 1; x <= num_tables; x++, tables++)
214
217
engine= (*tables)->cursor->getEngine();
215
219
if (involved_slots.count(engine->getId()) > 0)
216
220
continue; /* already added to involved engines */
217
222
involved_engines.push_back(engine);
218
223
involved_slots.insert(engine->getId());
241
246
memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
242
247
sql_lock->getLocks(),
243
248
sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
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(),
250
if (rc > 1) /* a timeout or a deadlock */
257
if (rc) /* a timeout or a deadlock */
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));
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
314
266
set_proc_info(0);
667
621
int Session::lock_table_name(TableList *table_list)
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());
673
627
/* Only insert the table if we haven't insert it already */