47
47
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
49
/* number of entries in handlertons[] */
49
/* number of entries in storage_engines[] */
50
50
uint32_t total_ha= 0;
51
/* number of storage engines (from handlertons[]) that support 2pc */
51
/* number of storage engines (from storage_engines[]) that support 2pc */
52
52
uint32_t total_ha_2pc= 0;
53
53
/* size of savepoint storage area (see ha_init) */
54
54
uint32_t savepoint_alloc_size= 0;
187
static bool dropdb_handlerton(Session *,
187
static bool dropdb_storage_engine(Session *,
191
handlerton *hton= plugin_data(plugin, handlerton *);
192
if (hton->state == SHOW_OPTION_YES && hton->drop_database)
193
hton->drop_database(hton, (char *)path);
191
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
192
if (engine->state == SHOW_OPTION_YES)
193
engine->drop_database((char *)path);
198
198
void ha_drop_database(char* path)
200
plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
200
plugin_foreach(NULL, dropdb_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
204
static bool closecon_handlerton(Session *session, plugin_ref plugin,
204
static bool closecon_storage_engine(Session *session, plugin_ref plugin,
207
handlerton *hton= plugin_data(plugin, handlerton *);
207
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
209
209
there's no need to rollback here as all transactions must
210
210
be rolled back already
212
if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
213
session_get_ha_data(session, hton))
214
hton->close_connection(hton, session);
212
if (engine->state == SHOW_OPTION_YES &&
213
session_get_ha_data(session, engine))
214
engine->close_connection(session);
223
223
void ha_close_connection(Session* session)
225
plugin_foreach(session, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
225
plugin_foreach(session, closecon_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
228
228
/* ========================================================================
405
405
in each engine independently. The two-phase commit protocol
407
407
- all participating engines support two-phase commit (provide
408
handlerton::prepare PSEA API call) and
408
StorageEngine::prepare PSEA API call) and
409
409
- transactions in at least two engines modify data (i.e. are
470
470
At the end of a statement, server call
471
471
ha_autocommit_or_rollback() is invoked. This call in turn
472
invokes handlerton::prepare() for every involved engine.
473
Prepare is followed by a call to handlerton::commit_one_phase()
474
If a one-phase commit will suffice, handlerton::prepare() is not
475
invoked and the server only calls handlerton::commit_one_phase().
472
invokes StorageEngine::prepare() for every involved engine.
473
Prepare is followed by a call to StorageEngine::commit_one_phase()
474
If a one-phase commit will suffice, StorageEngine::prepare() is not
475
invoked and the server only calls StorageEngine::commit_one_phase().
476
476
At statement commit, the statement-related read-write engine
477
477
flag is propagated to the corresponding flag in the normal
478
478
transaction. When the commit is complete, the list of registered
545
545
trans= &session->transaction.stmt;
547
ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
547
ha_info= session->ha_data[engine->slot].ha_info + static_cast<unsigned>(all);
549
549
if (ha_info->is_started())
550
550
return; /* already registered, return */
552
ha_info->register_ha(trans, ht_arg);
552
ha_info->register_ha(trans, engine);
554
trans->no_2pc|=(ht_arg->prepare==0);
554
trans->no_2pc|= not engine->has_2pc();
555
555
if (session->transaction.xid_state.xid.is_null())
556
556
session->transaction.xid_state.xid.set(session->query_id);
574
574
for (; ha_info; ha_info= ha_info->next())
577
handlerton *ht= ha_info->ht();
577
StorageEngine *engine= ha_info->engine();
578
578
status_var_increment(session->status_var.ha_prepare_count);
579
if ((err= engine->prepare(session, all)))
581
if ((err= ht->prepare(ht, session, all)))
583
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
584
ha_rollback_trans(session, all);
581
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
582
ha_rollback_trans(session, all);
591
588
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
592
589
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
593
ha_resolve_storage_engine_name(ht));
590
ha_resolve_storage_engine_name(engine));
630
Ha_trx_info *ha_info_all= &session->ha_data[ha_info->ht()->slot].ha_info[1];
627
Ha_trx_info *ha_info_all= &session->ha_data[ha_info->engine()->slot].ha_info[1];
631
628
assert(ha_info != ha_info_all);
633
630
Merge read-only/read-write information about statement
704
701
for (; ha_info && !error; ha_info= ha_info->next())
707
handlerton *ht= ha_info->ht();
704
StorageEngine *engine= ha_info->engine();
709
706
Do not call two-phase commit if this particular
710
707
transaction is read-only. This allows for simpler
716
713
Sic: we know that prepare() is not NULL since otherwise
717
714
trans->no_2pc would have been set.
719
if ((err= ht->prepare(ht, session, all)))
716
if ((err= engine->prepare(session, all)))
721
718
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
753
750
for (; ha_info; ha_info= ha_info_next)
756
handlerton *ht= ha_info->ht();
757
if ((err= ht->commit(ht, session, all)))
753
StorageEngine *engine= ha_info->engine();
754
if ((err= engine->commit(session, all)))
759
756
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
796
793
for (; ha_info; ha_info= ha_info_next)
799
handlerton *ht= ha_info->ht();
800
if ((err= ht->rollback(ht, session, all)))
796
StorageEngine *engine= ha_info->engine();
797
if ((err= engine->rollback(session, all)))
801
798
{ // cannot happen
802
799
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
876
static bool xacommit_handlerton(Session *,
873
static bool xacommit_storage_engine(Session *,
880
handlerton *hton= plugin_data(plugin, handlerton *);
881
if (hton->state == SHOW_OPTION_YES && hton->recover)
877
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
878
if (engine->state == SHOW_OPTION_YES)
883
hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
884
((struct xahton_st *)arg)->result= 0;
880
engine->commit_by_xid(((struct xaengine_st *)arg)->xid);
881
((struct xaengine_st *)arg)->result= 0;
889
static bool xarollback_handlerton(Session *,
886
static bool xarollback_storage_engine(Session *,
890
887
plugin_ref plugin,
893
handlerton *hton= plugin_data(plugin, handlerton *);
894
if (hton->state == SHOW_OPTION_YES && hton->recover)
890
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
891
if (engine->state == SHOW_OPTION_YES)
896
hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
897
((struct xahton_st *)arg)->result= 0;
893
engine->rollback_by_xid(((struct xaengine_st *)arg)->xid);
894
((struct xaengine_st *)arg)->result= 0;
903
900
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
905
struct xahton_st xaop;
902
struct xaengine_st xaop;
909
plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
906
plugin_foreach(NULL, commit ? xacommit_storage_engine : xarollback_storage_engine,
910
907
DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
912
909
return xaop.result;
939
static bool xarecover_handlerton(Session *,
936
static bool xarecover_storage_engine(Session *,
943
handlerton *hton= plugin_data(plugin, handlerton *);
940
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
944
941
struct xarecover_st *info= (struct xarecover_st *) arg;
947
if (hton->state == SHOW_OPTION_YES && hton->recover)
944
if (engine->state == SHOW_OPTION_YES)
949
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
946
while ((got= engine->recover(info->list, info->len)) > 0 )
951
948
errmsg_printf(ERRMSG_LVL_INFO, _("Found %d prepared transaction(s) in %s"),
952
got, ha_resolve_storage_engine_name(hton));
949
got, ha_resolve_storage_engine_name(engine));
953
950
for (int i=0; i < got; i ++)
955
952
my_xid x=info->list[i].get_my_xid();
969
966
hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
970
967
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
972
hton->commit_by_xid(hton, info->list+i);
969
engine->commit_by_xid(info->list+i);
976
hton->rollback_by_xid(hton, info->list+i);
973
engine->rollback_by_xid(info->list+i);
979
976
if (got < info->len)
1030
plugin_foreach(NULL, xarecover_handlerton,
1027
plugin_foreach(NULL, xarecover_storage_engine,
1031
1028
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1033
1030
free((unsigned char*)info.list);
1120
1117
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1123
handlerton *hton= plugin_data(plugin, handlerton *);
1120
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1125
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1126
hton->release_temporary_latches(hton, session);
1122
if (engine->state == SHOW_OPTION_YES)
1123
engine->release_temporary_latches(session);
1151
1148
for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
1154
handlerton *ht= ha_info->ht();
1156
assert(ht->savepoint_set != 0);
1157
if ((err= ht->savepoint_rollback(ht, session,
1158
(unsigned char *)(sv+1)+ht->savepoint_offset)))
1151
StorageEngine *engine= ha_info->engine();
1153
if ((err= engine->savepoint_rollback(session,
1154
(unsigned char *)(sv+1)+engine->savepoint_offset)))
1159
1155
{ // cannot happen
1160
1156
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1163
1159
status_var_increment(session->status_var.ha_savepoint_rollback_count);
1164
trans->no_2pc|= ht->prepare == 0;
1160
trans->no_2pc|= not engine->has_2pc();
1167
1163
rolling back the transaction in all storage engines that were not part of
1171
1167
ha_info= ha_info_next)
1174
handlerton *ht= ha_info->ht();
1175
if ((err= ht->rollback(ht, session, !(0))))
1170
StorageEngine *engine= ha_info->engine();
1171
if ((err= engine->rollback(session, !(0))))
1176
1172
{ // cannot happen
1177
1173
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1199
1195
for (; ha_info; ha_info= ha_info->next())
1202
handlerton *ht= ha_info->ht();
1204
if (! ht->savepoint_set)
1198
StorageEngine *engine= ha_info->engine();
1200
/* if (! engine->savepoint_set)
1206
1202
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1210
if ((err= ht->savepoint_set(ht, session, (unsigned char *)(sv+1)+ht->savepoint_offset)))
1206
if ((err= engine->savepoint_set(session, (unsigned char *)(sv+1)+engine->savepoint_offset)))
1211
1207
{ // cannot happen
1212
1208
my_error(ER_GET_ERRNO, MYF(0), err);
1230
1226
for (; ha_info; ha_info= ha_info->next())
1233
handlerton *ht= ha_info->ht();
1229
StorageEngine *engine= ha_info->engine();
1234
1230
/* Savepoint life time is enclosed into transaction life time. */
1236
if (!ht->savepoint_release)
1238
if ((err= ht->savepoint_release(ht, session,
1239
(unsigned char *)(sv+1) + ht->savepoint_offset)))
1232
if ((err= engine->savepoint_release(session,
1233
(unsigned char *)(sv+1) + engine->savepoint_offset)))
1240
1234
{ // cannot happen
1241
1235
my_error(ER_GET_ERRNO, MYF(0), err);
1249
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1243
static bool snapshot_storage_engine(Session *session, plugin_ref plugin, void *arg)
1251
handlerton *hton= plugin_data(plugin, handlerton *);
1252
if (hton->state == SHOW_OPTION_YES &&
1253
hton->start_consistent_snapshot)
1245
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1246
if (engine->state == SHOW_OPTION_YES)
1255
hton->start_consistent_snapshot(hton, session);
1248
engine->start_consistent_snapshot(session);
1256
1249
*((bool *)arg)= false;
1263
1256
bool warn= true;
1265
plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1258
plugin_foreach(session, snapshot_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1268
1261
Same idea as when one wants to CREATE TABLE in one engine which does not
1279
static bool flush_handlerton(Session *,
1272
static bool flush_storage_engine(Session *,
1280
1273
plugin_ref plugin,
1283
handlerton *hton= plugin_data(plugin, handlerton *);
1284
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1285
hton->flush_logs(hton))
1276
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1277
if (engine->state == SHOW_OPTION_YES &&
1278
engine->flush_logs())
1291
bool ha_flush_logs(handlerton *db_type)
1284
bool ha_flush_logs(StorageEngine *engine)
1293
if (db_type == NULL)
1295
if (plugin_foreach(NULL, flush_handlerton,
1288
if (plugin_foreach(NULL, flush_storage_engine,
1296
1289
DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1301
if (db_type->state != SHOW_OPTION_YES ||
1302
(db_type->flush_logs && db_type->flush_logs(db_type)))
1294
if (engine->state != SHOW_OPTION_YES ||
1295
(engine->flush_logs()))
1358
struct handlerton_delete_table_args {
1351
struct storage_engine_delete_table_args {
1359
1352
Session *session;
1360
1353
const char *path;
1365
static bool deletetable_handlerton(Session *,
1358
static bool deletetable_storage_engine(Session *,
1369
struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
1362
struct storage_engine_delete_table_args *dtargs= (struct storage_engine_delete_table_args *) args;
1371
1364
Session *session= dtargs->session;
1372
1365
const char *path= dtargs->path;
1377
1370
if(dtargs->error!=ENOENT) /* already deleted table */
1380
handlerton *table_type= plugin_data(plugin, handlerton *);
1385
if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
1388
if ((file= table_type->create(table_type, NULL, session->mem_root)))
1373
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
1378
if(!(engine->state == SHOW_OPTION_YES))
1381
if ((file= engine->create(NULL, session->mem_root)))
1417
1410
TABLE_SHARE dummy_share;
1418
1411
Table dummy_table;
1420
struct handlerton_delete_table_args dtargs;
1413
struct storage_engine_delete_table_args dtargs;
1421
1414
dtargs.error= ENOENT;
1422
1415
dtargs.session= session;
1423
1416
dtargs.path= path;
1424
1417
dtargs.file= NULL;
1426
plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1419
plugin_foreach(NULL, deletetable_storage_engine, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1429
1422
memset(&dummy_table, 0, sizeof(dummy_table));
1576
1569
void **handler::ha_data(Session *session) const
1578
return session_ha_data(session, ht);
1571
return session_ha_data(session, engine);
1581
1574
Session *handler::ha_session(void) const
2294
2287
temporary= get_error_message(error, &str);
2295
2288
if (!str.is_empty())
2297
const char* engine= table_type();
2299
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
2301
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
2290
const char* engine_name= table_type();
2292
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
2295
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2304
my_error(ER_GET_ERRNO,errflag,error);
2299
my_error(ER_GET_ERRNO,errflag,error);
2479
2475
handler::mark_trx_read_write()
2481
Ha_trx_info *ha_info= &ha_session()->ha_data[ht->slot].ha_info[0];
2477
Ha_trx_info *ha_info= &ha_session()->ha_data[engine->slot].ha_info[0];
2483
2479
When a storage engine method is called, the transaction must
2484
2480
have been started, unless it's a DDL call, for which the
2993
struct st_table_exists_in_engine_args
2989
struct st_table_exists_in_storage_engine_args
2995
2991
const char *db;
2996
2992
const char *name;
2994
StorageEngine* engine;
3001
static bool table_exists_in_engine_handlerton(Session *session, plugin_ref plugin,
2997
static bool table_exists_in_storage_engine(Session *session, plugin_ref plugin,
3004
st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3005
handlerton *hton= plugin_data(plugin, handlerton *);
3000
st_table_exists_in_storage_engine_args *vargs= (st_table_exists_in_storage_engine_args *)arg;
3001
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
3007
3003
int err= HA_ERR_NO_SUCH_TABLE;
3009
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3010
err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
3005
if (engine->state == SHOW_OPTION_YES)
3006
err = engine->table_exists_in_engine(session, vargs->db, vargs->name);
3012
3008
vargs->err = err;
3013
3009
if (vargs->err == HA_ERR_TABLE_EXIST)
3011
vargs->engine= engine;
3022
3018
int ha_table_exists_in_engine(Session* session,
3023
3019
const char* db, const char* name,
3020
StorageEngine **engine)
3026
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
3027
plugin_foreach(session, table_exists_in_engine_handlerton,
3022
st_table_exists_in_storage_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
3023
plugin_foreach(session, table_exists_in_storage_engine,
3028
3024
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3030
3026
if(args.err==HA_ERR_NO_SUCH_TABLE)
3050
3046
strlen(table.engine().name().c_str()) };
3051
3047
plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
3053
args.hton= plugin_data(plugin,handlerton *);
3049
args.engine= plugin_data(plugin,StorageEngine *);
3055
*engine= args.engine;
3061
3057
return(args.err);
4091
4087
List<char> *found_exts= (List<char> *) arg;
4092
handlerton *hton= plugin_data(plugin, handlerton *);
4088
StorageEngine *engine= plugin_data(plugin, StorageEngine *);
4094
if (hton->state == SHOW_OPTION_YES && hton->create &&
4095
(file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
4090
if (engine->state == SHOW_OPTION_YES &&
4091
(file= engine->create((TABLE_SHARE*) 0, current_session->mem_root)))
4097
4093
List_iterator_fast<char> it(*found_exts);
4098
4094
const char **ext, *old_ext;
4160
bool ha_show_status(Session *session, handlerton *db_type, enum ha_stat_type stat)
4156
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
4162
4158
List<Item> field_list;
4163
4159
Protocol *protocol= session->protocol;
4171
4167
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
4174
result= db_type->show_status &&
4175
db_type->show_status(db_type, session, stat_print, stat) ? 1 : 0;
4170
result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4178
4173
session->my_eof();