65
typedef hash_map<std::string, plugin::StorageEngine *> EngineMap;
66
typedef std::vector<plugin::StorageEngine *> EngineVector;
68
65
static EngineVector vector_of_engines;
69
static EngineVector vector_of_transactional_engines;
71
const std::string plugin::UNKNOWN_STRING("UNKNOWN");
72
const std::string plugin::DEFAULT_DEFINITION_FILE_EXT(".dfe");
67
const std::string UNKNOWN_STRING("UNKNOWN");
68
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
74
70
static std::set<std::string> set_of_table_definition_ext;
76
plugin::StorageEngine::StorageEngine(const string name_arg,
77
const bitset<HTON_BIT_SIZE> &flags_arg,
72
StorageEngine::StorageEngine(const string name_arg,
73
const bitset<HTON_BIT_SIZE> &flags_arg)
79
74
: Plugin(name_arg, "StorageEngine"),
80
two_phase_commit(support_2pc),
91
83
pthread_mutex_init(&proto_cache_mutex, NULL);
95
plugin::StorageEngine::~StorageEngine()
86
StorageEngine::~StorageEngine()
97
88
pthread_mutex_destroy(&proto_cache_mutex);
100
void plugin::StorageEngine::setTransactionReadWrite(Session& session)
91
void StorageEngine::setTransactionReadWrite(Session& session)
102
Ha_trx_info *ha_info= session.getEngineInfo(this);
105
When a storage engine method is called, the transaction must
106
have been started, unless it's a DDL call, for which the
107
storage engine starts the transaction internally, and commits
108
it internally, without registering in the ha_list.
109
Unfortunately here we can't know know for sure if the engine
110
has registered the transaction or not, so we must check.
112
if (ha_info->is_started())
115
* table_share can be NULL in plugin::StorageEngine::dropTable().
117
ha_info->set_trx_read_write();
93
TransactionContext &statement_ctx= session.transaction.stmt;
94
statement_ctx.markModifiedNonTransData();
123
int plugin::StorageEngine::doRenameTable(Session *,
97
int StorageEngine::doRenameTable(Session *,
309
279
don't bother to rollback here, it's done already
311
void plugin::StorageEngine::closeConnection(Session* session)
281
void StorageEngine::closeConnection(Session* session)
313
283
for_each(vector_of_engines.begin(), vector_of_engines.end(),
314
284
StorageEngineCloseConnection(session));
317
void plugin::StorageEngine::dropDatabase(char* path)
287
void StorageEngine::dropDatabase(char* path)
319
289
for_each(vector_of_engines.begin(), vector_of_engines.end(),
320
bind2nd(mem_fun(&plugin::StorageEngine::drop_database),path));
323
int plugin::StorageEngine::commitOrRollbackByXID(XID *xid, bool commit)
328
transform(vector_of_engines.begin(), vector_of_engines.end(), results.begin(),
329
bind2nd(mem_fun(&plugin::StorageEngine::commit_by_xid),xid));
331
transform(vector_of_engines.begin(), vector_of_engines.end(), results.begin(),
332
bind2nd(mem_fun(&plugin::StorageEngine::rollback_by_xid),xid));
334
if (find_if(results.begin(), results.end(), bind2nd(equal_to<int>(),0))
342
This function should be called when MySQL sends rows of a SELECT result set
343
or the EOF mark to the client. It releases a possible adaptive hash index
344
S-latch held by session in InnoDB and also releases a possible InnoDB query
345
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
346
keep them over several calls of the InnoDB Cursor interface when a join
347
is executed. But when we let the control to pass to the client they have
348
to be released because if the application program uses mysql_use_result(),
349
it may deadlock on the S-latch if the application on another connection
350
performs another SQL query. In MySQL-4.1 this is even more important because
351
there a connection can have several SELECT queries open at the same time.
353
@param session the thread handle of the current connection
358
int plugin::StorageEngine::releaseTemporaryLatches(Session *session)
360
for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
361
bind2nd(mem_fun(&plugin::StorageEngine::release_temporary_latches),session));
365
bool plugin::StorageEngine::flushLogs(plugin::StorageEngine *engine)
290
bind2nd(mem_fun(&StorageEngine::drop_database),path));
293
bool StorageEngine::flushLogs(StorageEngine *engine)
367
295
if (engine == NULL)
369
297
if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
370
mem_fun(&plugin::StorageEngine::flush_logs))
298
mem_fun(&StorageEngine::flush_logs))
371
299
!= vector_of_engines.begin())
384
recover() step of xa.
387
there are three modes of operation:
388
- automatic recover after a crash
389
in this case commit_list != 0, tc_heuristic_recover==0
390
all xids from commit_list are committed, others are rolled back
391
- manual (heuristic) recover
392
in this case commit_list==0, tc_heuristic_recover != 0
393
DBA has explicitly specified that all prepared transactions should
394
be committed (or rolled back).
395
- no recovery (MySQL did not detect a crash)
396
in this case commit_list==0, tc_heuristic_recover == 0
397
there should be no prepared transactions in this case.
399
class XARecover : unary_function<plugin::StorageEngine *, void>
401
int trans_len, found_foreign_xids, found_my_xids;
407
XARecover(XID *trans_list_arg, int trans_len_arg,
408
HASH *commit_list_arg, bool dry_run_arg)
409
: trans_len(trans_len_arg), found_foreign_xids(0), found_my_xids(0),
411
trans_list(trans_list_arg), commit_list(commit_list_arg),
417
return found_foreign_xids;
422
return found_my_xids;
425
result_type operator() (argument_type engine)
430
if (engine->is_enabled())
432
while ((got= engine->recover(trans_list, trans_len)) > 0 )
434
errmsg_printf(ERRMSG_LVL_INFO,
435
_("Found %d prepared transaction(s) in %s"),
436
got, engine->getName().c_str());
437
for (int i=0; i < got; i ++)
439
my_xid x=trans_list[i].get_my_xid();
440
if (!x) // not "mine" - that is generated by external TM
442
xid_cache_insert(trans_list+i, XA_PREPARED);
443
found_foreign_xids++;
453
hash_search(commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
454
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
456
engine->commit_by_xid(trans_list+i);
460
engine->rollback_by_xid(trans_list+i);
470
int plugin::StorageEngine::recover(HASH *commit_list)
472
XID *trans_list= NULL;
475
bool dry_run= (commit_list==0 && tc_heuristic_recover==0);
477
/* commit_list and tc_heuristic_recover cannot be set both */
478
assert(commit_list==0 || tc_heuristic_recover==0);
480
/* if either is set, total_ha_2pc must be set too */
481
if (total_ha_2pc <= 1)
485
#ifndef WILL_BE_DELETED_LATER
488
for now, only InnoDB supports 2pc. It means we can always safely
489
rollback all pending transactions, without risking inconsistent data
492
assert(total_ha_2pc == 2); // only InnoDB and binlog
493
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
496
for (trans_len= MAX_XID_LIST_SIZE ;
497
trans_list==0 && trans_len > MIN_XID_LIST_SIZE; trans_len/=2)
499
trans_list=(XID *)malloc(trans_len*sizeof(XID));
503
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), trans_len*sizeof(XID));
508
errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
511
XARecover recover_func(trans_list, trans_len, commit_list, dry_run);
512
for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
516
if (recover_func.getForeignXIDs())
517
errmsg_printf(ERRMSG_LVL_WARN,
518
_("Found %d prepared XA transactions"),
519
recover_func.getForeignXIDs());
520
if (dry_run && recover_func.getMyXIDs())
522
errmsg_printf(ERRMSG_LVL_ERROR,
523
_("Found %d prepared transactions! It means that drizzled "
524
"was not shut down properly last time and critical "
525
"recovery information (last binlog or %s file) was "
526
"manually deleted after a crash. You have to start "
527
"drizzled with the --tc-heuristic-recover switch to "
528
"commit or rollback pending transactions."),
529
recover_func.getMyXIDs(), opt_tc_log_file);
533
errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
537
int plugin::StorageEngine::startConsistentSnapshot(Session *session)
539
for_each(vector_of_engines.begin(), vector_of_engines.end(),
540
bind2nd(mem_fun(&plugin::StorageEngine::start_consistent_snapshot),
545
class StorageEngineGetTableDefinition: public unary_function<plugin::StorageEngine *,bool>
311
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
547
313
Session& session;
548
314
const char* path;