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().
76
72
Change to use malloc() ONLY when using LOCK TABLES command or when
77
73
we are forced to use mysql_lock_merge.
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
void DrizzleLock::reset(void)
168
for (std::vector<THR_LOCK_DATA *>::iterator iter= locks.begin(); iter != locks.end(); iter++)
170
(*iter)->type= TL_UNLOCK;
175
DrizzleLock *Session::lockTables(Table **tables, uint32_t count, uint32_t flags, bool *need_reopen)
174
177
DrizzleLock *sql_lock;
175
178
Table *write_lock_used;
176
179
vector<plugin::StorageEngine *> involved_engines;
180
if (! (sql_lock= get_lock_data(tables, count, true, &write_lock_used)))
186
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)))
190
if (global_read_lock && write_lock_used &&
191
! (flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK))
186
194
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
211
218
size_t num_tables= sql_lock->sizeTable();
212
219
plugin::StorageEngine *engine;
213
std::set<size_t> involved_slots;
220
set<size_t> involved_slots;
215
221
for (size_t x= 1; x <= num_tables; x++, tables++)
217
223
engine= (*tables)->cursor->getEngine();
219
224
if (involved_slots.count(engine->getId()) > 0)
220
225
continue; /* already added to involved engines */
222
226
involved_engines.push_back(engine);
223
227
involved_slots.insert(engine->getId());
246
250
memcpy(sql_lock->getLocks() + sql_lock->sizeLock(),
247
251
sql_lock->getLocks(),
248
252
sql_lock->sizeLock() * sizeof(*sql_lock->getLocks()));
250
253
/* Lock on the copied half of the lock data array. */
251
drizzled::error_t rc;
252
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(*this,
253
sql_lock->getLocks() +
254
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->getLocks() +
254
255
sql_lock->sizeLock(),
255
256
sql_lock->sizeLock(),
257
if (rc) /* a timeout or a deadlock */
258
if (rc > 1) /* a timeout or a deadlock */
259
260
if (sql_lock->sizeTable())
260
261
unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
261
262
reset_lock_data_and_free(&sql_lock);
262
263
my_error(rc, MYF(0));
266
else if (rc == 1) /* aborted */
268
some_tables_deleted= true; // Try again
269
sql_lock->setLock(0); // Locks are already freed
270
// Fall through: unlock, reset lock data, free and retry
272
else if (not some_tables_deleted || (flags & DRIZZLE_LOCK_IGNORE_FLUSH))
275
Thread was killed or lock aborted. Let upper level close all
276
used tables and retry or give error.
280
else if (not open_tables)
282
// Only using temporary tables, no need to unlock
283
some_tables_deleted= false;
288
/* going to retry, unlock all tables */
289
if (sql_lock->sizeLock())
290
sql_lock->unlock(sql_lock->sizeLock());
292
if (sql_lock->sizeTable())
293
unlock_external(sql_lock->getTable(), sql_lock->sizeTable());
296
If thr_multi_lock fails it resets lock type for tables, which
297
were locked before (and including) one that caused error. Lock
298
type for other tables preserved.
300
reset_lock_data_and_free(&sql_lock);
303
* Notify all involved engines that the
304
* SQL statement has ended
306
for_each(involved_engines.begin(),
307
involved_engines.end(),
308
bind2nd(mem_fun(&plugin::StorageEngine::endStatement), this));
310
if (flags & DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN)
316
if (wait_for_tables(this))
318
break; // Couldn't open tables
266
322
set_proc_info(0);
621
675
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());
677
TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
678
const TableIdentifier::Key &key(identifier.getKey());
627
681
/* Only insert the table if we haven't insert it already */