59
typedef hash_map<std::string, plugin::StorageEngine *> EngineMap;
60
typedef std::vector<plugin::StorageEngine *> EngineVector;
67
62
static EngineVector vector_of_engines;
68
static EngineVector vector_of_schema_engines;
63
static EngineVector vector_of_transactional_engines;
70
const std::string UNKNOWN_STRING("UNKNOWN");
71
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
65
const std::string plugin::UNKNOWN_STRING("UNKNOWN");
66
const std::string plugin::DEFAULT_DEFINITION_FILE_EXT(".dfe");
73
68
static std::set<std::string> set_of_table_definition_ext;
75
EngineVector &StorageEngine::getSchemaEngines()
77
return vector_of_schema_engines;
80
StorageEngine::StorageEngine(const string name_arg,
81
const bitset<HTON_BIT_SIZE> &flags_arg) :
82
Plugin(name_arg, "StorageEngine"),
83
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
88
StorageEngine::~StorageEngine()
92
void StorageEngine::setTransactionReadWrite(Session& session)
94
TransactionContext &statement_ctx= session.transaction.stmt;
95
statement_ctx.markModifiedNonTransData();
99
int StorageEngine::renameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
101
setTransactionReadWrite(session);
103
return doRenameTable(session, from, to);
70
plugin::StorageEngine::StorageEngine(const string name_arg,
71
const bitset<HTON_BIT_SIZE> &flags_arg,
72
size_t savepoint_offset_arg,
74
: Plugin(name_arg, "StorageEngine"),
75
two_phase_commit(support_2pc),
78
savepoint_offset(savepoint_alloc_size),
79
orig_savepoint_offset(savepoint_offset_arg),
84
savepoint_alloc_size+= orig_savepoint_offset;
89
pthread_mutex_init(&proto_cache_mutex, NULL);
93
plugin::StorageEngine::~StorageEngine()
95
savepoint_alloc_size-= orig_savepoint_offset;
96
pthread_mutex_destroy(&proto_cache_mutex);
99
void plugin::StorageEngine::setTransactionReadWrite(Session& session)
101
Ha_trx_info *ha_info= &session.ha_data[getSlot()].ha_info[0];
103
When a storage engine method is called, the transaction must
104
have been started, unless it's a DDL call, for which the
105
storage engine starts the transaction internally, and commits
106
it internally, without registering in the ha_list.
107
Unfortunately here we can't know know for sure if the engine
108
has registered the transaction or not, so we must check.
110
if (ha_info->is_started())
113
* table_share can be NULL in plugin::StorageEngine::dropTable().
115
ha_info->set_trx_read_write();
121
int plugin::StorageEngine::doRenameTable(Session *,
126
for (const char **ext= bas_ext(); *ext ; ext++)
128
if (rename_file_ext(from, to, *ext))
130
if ((error=my_errno) != ENOENT)
107
140
Delete all files with extension from bas_ext().
128
161
for (const char **ext= bas_ext(); *ext ; ext++)
130
internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
131
MY_UNPACK_FILENAME|MY_APPEND_EXT);
132
if (internal::my_delete_with_symlink(buff, MYF(0)))
163
fn_format(buff, table_path.c_str(), "", *ext,
164
MY_UNPACK_FILENAME|MY_APPEND_EXT);
165
if (my_delete_with_symlink(buff, MYF(0)))
134
if ((error= errno) != ENOENT)
167
if ((error= my_errno) != ENOENT)
139
171
enoent_or_zero= 0; // No error for ENOENT
142
172
error= enoent_or_zero;
147
bool StorageEngine::addPlugin(StorageEngine *engine)
177
const char *plugin::StorageEngine::checkLowercaseNames(const char *path,
180
if (flags.test(HTON_BIT_FILE_BASED))
183
/* Ensure that table Cursor get path in lower case */
184
if (tmp_path != path)
185
strcpy(tmp_path, path);
188
we only should turn into lowercase database/table part
189
so start the process after homedirectory
191
if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
192
my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
194
my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
200
bool plugin::StorageEngine::addPlugin(plugin::StorageEngine *engine)
150
203
vector_of_engines.push_back(engine);
205
if (engine->check_flag(HTON_BIT_DOES_TRANSACTIONS))
206
vector_of_transactional_engines.push_back(engine);
152
208
if (engine->getTableDefinitionFileExtension().length())
154
210
assert(engine->getTableDefinitionFileExtension().length() == DEFAULT_DEFINITION_FILE_EXT.length());
155
211
set_of_table_definition_ext.insert(engine->getTableDefinitionFileExtension());
158
if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
159
vector_of_schema_engines.push_back(engine);
164
void StorageEngine::removePlugin(StorageEngine *)
217
void plugin::StorageEngine::removePlugin(plugin::StorageEngine *)
166
219
if (shutdown_has_begun == false)
168
221
vector_of_engines.clear();
169
vector_of_schema_engines.clear();
222
vector_of_transactional_engines.clear();
171
224
shutdown_has_begun= true;
175
228
class FindEngineByName
176
: public unary_function<StorageEngine *, bool>
229
: public unary_function<plugin::StorageEngine *, bool>
178
const string ⌖
181
explicit FindEngineByName(const string &target_arg) :
233
explicit FindEngineByName(const string target_arg)
185
236
result_type operator() (argument_type engine)
187
238
string engine_name(engine->getName());
255
308
don't bother to rollback here, it's done already
257
void StorageEngine::closeConnection(Session* session)
310
void plugin::StorageEngine::closeConnection(Session* session)
259
312
for_each(vector_of_engines.begin(), vector_of_engines.end(),
260
313
StorageEngineCloseConnection(session));
263
bool StorageEngine::flushLogs(StorageEngine *engine)
316
void plugin::StorageEngine::dropDatabase(char* path)
318
for_each(vector_of_engines.begin(), vector_of_engines.end(),
319
bind2nd(mem_fun(&plugin::StorageEngine::drop_database),path));
322
int plugin::StorageEngine::commitOrRollbackByXID(XID *xid, bool commit)
327
transform(vector_of_engines.begin(), vector_of_engines.end(), results.begin(),
328
bind2nd(mem_fun(&plugin::StorageEngine::commit_by_xid),xid));
330
transform(vector_of_engines.begin(), vector_of_engines.end(), results.begin(),
331
bind2nd(mem_fun(&plugin::StorageEngine::rollback_by_xid),xid));
333
if (find_if(results.begin(), results.end(), bind2nd(equal_to<int>(),0))
341
This function should be called when MySQL sends rows of a SELECT result set
342
or the EOF mark to the client. It releases a possible adaptive hash index
343
S-latch held by session in InnoDB and also releases a possible InnoDB query
344
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
345
keep them over several calls of the InnoDB Cursor interface when a join
346
is executed. But when we let the control to pass to the client they have
347
to be released because if the application program uses mysql_use_result(),
348
it may deadlock on the S-latch if the application on another connection
349
performs another SQL query. In MySQL-4.1 this is even more important because
350
there a connection can have several SELECT queries open at the same time.
352
@param session the thread handle of the current connection
357
int plugin::StorageEngine::releaseTemporaryLatches(Session *session)
359
for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
360
bind2nd(mem_fun(&plugin::StorageEngine::release_temporary_latches),session));
364
bool plugin::StorageEngine::flushLogs(plugin::StorageEngine *engine)
265
366
if (engine == NULL)
267
368
if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
268
mem_fun(&StorageEngine::flush_logs))
269
!= vector_of_engines.begin())
369
mem_fun(&plugin::StorageEngine::flush_logs))
370
!= vector_of_engines.begin())
274
if (engine->flush_logs())
375
if ((!engine->is_enabled()) ||
376
(engine->flush_logs()))
280
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
383
recover() step of xa.
386
there are three modes of operation:
387
- automatic recover after a crash
388
in this case commit_list != 0, tc_heuristic_recover==0
389
all xids from commit_list are committed, others are rolled back
390
- manual (heuristic) recover
391
in this case commit_list==0, tc_heuristic_recover != 0
392
DBA has explicitly specified that all prepared transactions should
393
be committed (or rolled back).
394
- no recovery (MySQL did not detect a crash)
395
in this case commit_list==0, tc_heuristic_recover == 0
396
there should be no prepared transactions in this case.
398
class XARecover : unary_function<plugin::StorageEngine *, void>
400
int trans_len, found_foreign_xids, found_my_xids;
406
XARecover(XID *trans_list_arg, int trans_len_arg,
407
HASH *commit_list_arg, bool dry_run_arg)
408
: trans_len(trans_len_arg), found_foreign_xids(0), found_my_xids(0),
410
trans_list(trans_list_arg), commit_list(commit_list_arg),
416
return found_foreign_xids;
421
return found_my_xids;
424
result_type operator() (argument_type engine)
429
if (engine->is_enabled())
431
while ((got= engine->recover(trans_list, trans_len)) > 0 )
433
errmsg_printf(ERRMSG_LVL_INFO,
434
_("Found %d prepared transaction(s) in %s"),
435
got, engine->getName().c_str());
436
for (int i=0; i < got; i ++)
438
my_xid x=trans_list[i].get_my_xid();
439
if (!x) // not "mine" - that is generated by external TM
441
xid_cache_insert(trans_list+i, XA_PREPARED);
442
found_foreign_xids++;
452
hash_search(commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
453
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
455
engine->commit_by_xid(trans_list+i);
459
engine->rollback_by_xid(trans_list+i);
469
int plugin::StorageEngine::recover(HASH *commit_list)
471
XID *trans_list= NULL;
474
bool dry_run= (commit_list==0 && tc_heuristic_recover==0);
476
/* commit_list and tc_heuristic_recover cannot be set both */
477
assert(commit_list==0 || tc_heuristic_recover==0);
479
/* if either is set, total_ha_2pc must be set too */
480
if (total_ha_2pc <= 1)
484
#ifndef WILL_BE_DELETED_LATER
487
for now, only InnoDB supports 2pc. It means we can always safely
488
rollback all pending transactions, without risking inconsistent data
491
assert(total_ha_2pc == 2); // only InnoDB and binlog
492
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
495
for (trans_len= MAX_XID_LIST_SIZE ;
496
trans_list==0 && trans_len > MIN_XID_LIST_SIZE; trans_len/=2)
498
trans_list=(XID *)malloc(trans_len*sizeof(XID));
502
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), trans_len*sizeof(XID));
507
errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
510
XARecover recover_func(trans_list, trans_len, commit_list, dry_run);
511
for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
515
if (recover_func.getForeignXIDs())
516
errmsg_printf(ERRMSG_LVL_WARN,
517
_("Found %d prepared XA transactions"),
518
recover_func.getForeignXIDs());
519
if (dry_run && recover_func.getMyXIDs())
521
errmsg_printf(ERRMSG_LVL_ERROR,
522
_("Found %d prepared transactions! It means that drizzled "
523
"was not shut down properly last time and critical "
524
"recovery information (last binlog or %s file) was "
525
"manually deleted after a crash. You have to start "
526
"drizzled with the --tc-heuristic-recover switch to "
527
"commit or rollback pending transactions."),
528
recover_func.getMyXIDs(), opt_tc_log_file);
532
errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
536
int plugin::StorageEngine::startConsistentSnapshot(Session *session)
538
for_each(vector_of_engines.begin(), vector_of_engines.end(),
539
bind2nd(mem_fun(&plugin::StorageEngine::start_consistent_snapshot),
544
class StorageEngineGetTableDefinition: public unary_function<plugin::StorageEngine *,bool>
282
546
Session& session;
283
TableIdentifier &identifier;
284
message::Table &table_message;
549
const char *table_name;
551
message::Table *table_proto;
288
555
StorageEngineGetTableDefinition(Session& session_arg,
289
TableIdentifier &identifier_arg,
290
message::Table &table_message_arg,
556
const char* path_arg,
558
const char *table_name_arg,
559
const bool is_tmp_arg,
560
message::Table *table_proto_arg,
292
562
session(session_arg),
293
identifier(identifier_arg),
294
table_message(table_message_arg),
565
table_name(table_name_arg),
567
table_proto(table_proto_arg),
297
570
result_type operator() (argument_type engine)
299
int ret= engine->doGetTableDefinition(session, identifier, table_message);
572
int ret= engine->doGetTableDefinition(session,
301
579
if (ret != ENOENT)
304
return err == EEXIST || err != ENOENT;
308
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
311
TableIdentifier &identifier;
314
StorageEngineDoesTableExist(Session& session_arg, TableIdentifier &identifier_arg) :
315
session(session_arg),
316
identifier(identifier_arg)
319
result_type operator() (argument_type engine)
321
return engine->doDoesTableExist(session, identifier);
326
Utility method which hides some of the details of getTableDefinition()
328
bool plugin::StorageEngine::doesTableExist(Session &session,
329
TableIdentifier &identifier,
330
bool include_temporary_tables)
332
if (include_temporary_tables)
334
if (session.doDoesTableExist(identifier))
338
EngineVector::iterator iter=
339
find_if(vector_of_engines.begin(), vector_of_engines.end(),
340
StorageEngineDoesTableExist(session, identifier));
342
if (iter == vector_of_engines.end())
350
bool plugin::StorageEngine::doDoesTableExist(Session&, TableIdentifier&)
352
cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
582
return *err == EEXIST;
586
static int drizzle_read_table_proto(const char* path, message::Table* table)
588
int fd= open(path, O_RDONLY);
593
google::protobuf::io::ZeroCopyInputStream* input=
594
new google::protobuf::io::FileInputStream(fd);
596
if (table->ParseFromZeroCopyStream(input) == false)
418
returns ENOENT if the file doesn't exists.
693
This should return ENOENT if the file doesn't exists.
694
The .frm file will be deleted only if we return 0 or ENOENT
420
int StorageEngine::dropTable(Session& session,
421
TableIdentifier &identifier)
696
int plugin::StorageEngine::dropTable(Session& session,
697
TableIdentifier &identifier,
698
bool generate_warning)
425
702
message::Table src_proto;
426
StorageEngine *engine;
428
error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
430
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
432
string error_message;
434
error_message.append(identifier.getSQLPath());
435
error_message.append(" : ");
436
error_message.append(src_proto.InitializationErrorString());
438
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
440
return ER_CORRUPT_TABLE_DEFINITION;
443
engine= StorageEngine::findByName(session, src_proto.engine().name());
447
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), identifier.getSQLPath().c_str());
449
return ER_CORRUPT_TABLE_DEFINITION;
452
error= StorageEngine::dropTable(session, *engine, identifier);
703
plugin::StorageEngine* engine;
705
error_proto= plugin::StorageEngine::getTableDefinition(session,
709
engine= plugin::StorageEngine::findByName(session,
710
src_proto.engine().name());
714
engine->setTransactionReadWrite(session);
715
error= engine->doDropTable(session, identifier.getPath());
722
if (engine && engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
724
deleteDefinitionFromPath(identifier);
728
error= deleteDefinitionFromPath(identifier);
454
733
if (error_proto && error == 0)
460
int StorageEngine::dropTable(Session& session,
461
StorageEngine &engine,
462
TableIdentifier &identifier)
466
engine.setTransactionReadWrite(session);
467
error= engine.doDropTable(session, identifier);
736
if (error && generate_warning)
739
Because engine->print_error() use my_error() to generate the error message
740
we use an internal error Cursor to intercept it and store the text
741
in a temporary buffer. Later the message will be presented to user
744
Ha_delete_table_error_handler ha_delete_table_error_handler;
746
session.push_internal_handler(&ha_delete_table_error_handler);
747
engine->print_error(error, 0);
749
session.pop_internal_handler();
752
XXX: should we convert *all* errors to warnings here?
753
What if the error is fatal?
755
push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
756
ha_delete_table_error_handler.buff);
474
763
Initiates table-file and calls appropriate database-creator.
770
@todo refactor to remove goto
481
int StorageEngine::createTable(Session &session,
482
TableIdentifier &identifier,
483
bool update_create_info,
484
message::Table& table_message)
772
int plugin::StorageEngine::createTable(Session& session,
773
TableIdentifier &identifier,
774
bool update_create_info,
775
drizzled::message::Table& table_proto, bool proto_used)
488
TableShare share(identifier.getSchemaName().c_str(), 0, identifier.getTableName().c_str(), identifier.getPath().c_str());
779
TableShare share(identifier.getDBName(), 0, identifier.getTableName(), identifier.getPath());
489
780
message::Table tmp_proto;
491
if (parse_table_proto(session, table_message, &share) || open_table_from_share(&session, &share, "", 0, 0, &table))
493
// @note Error occured, we should probably do a little more here.
784
if (parse_table_proto(session, table_proto, &share))
497
if (update_create_info)
498
table.updateCreateInfo(&table_message);
500
/* Check for legal operations against the Engine using the proto (if used) */
501
if (table_message.type() == message::Table::TEMPORARY &&
789
if (open_table_def(session, &share))
793
if (open_table_from_share(&session, &share, "", 0, (uint32_t) READ_ALL, 0,
797
if (update_create_info)
798
table.updateCreateInfo(&table_proto);
800
/* Check for legal operations against the Engine using the proto (if used) */
803
if (table_proto.type() == message::Table::TEMPORARY &&
502
804
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
504
806
error= HA_ERR_UNSUPPORTED;
506
else if (table_message.type() != message::Table::TEMPORARY &&
809
else if (table_proto.type() != message::Table::TEMPORARY &&
507
810
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
509
812
error= HA_ERR_UNSUPPORTED;
513
share.storage_engine->setTransactionReadWrite(session);
515
error= share.storage_engine->doCreateTable(session,
523
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
526
table.closefrm(false);
817
if (! share.storage_engine->is_enabled())
819
error= HA_ERR_UNSUPPORTED;
825
char name_buff[FN_REFLEN];
826
const char *table_name_arg;
828
table_name_arg= share.storage_engine->checkLowercaseNames(identifier.getPath(), name_buff);
830
share.storage_engine->setTransactionReadWrite(session);
832
error= share.storage_engine->doCreateTable(&session,
839
table.closefrm(false);
843
char name_buff[FN_REFLEN];
844
sprintf(name_buff,"%s.%s", identifier.getDBName(), identifier.getTableName());
845
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
529
848
share.free_table_share();
530
849
return(error != 0);
533
Cursor *StorageEngine::getCursor(TableShare &share, memory::Root *alloc)
852
Cursor *plugin::StorageEngine::getCursor(TableShare &share, MEM_ROOT *alloc)
535
855
return create(share, alloc);
859
TODO -> Remove this to force all engines to implement their own file. Solves the "we only looked at dfe" problem.
861
void plugin::StorageEngine::doGetTableNames(CachedDirectory &directory, string&, set<string>& set_of_names)
863
CachedDirectory::Entries entries= directory.getEntries();
865
for (CachedDirectory::Entries::iterator entry_iter= entries.begin();
866
entry_iter != entries.end(); ++entry_iter)
868
CachedDirectory::Entry *entry= *entry_iter;
869
string *filename= &entry->filename;
871
assert(filename->size());
873
const char *ext= strchr(filename->c_str(), '.');
875
if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_DEFINITION_FILE_EXT.c_str()) ||
876
is_prefix(filename->c_str(), TMP_FILE_PREFIX))
880
char uname[NAME_LEN + 1];
881
uint32_t file_name_len;
883
file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
884
// TODO: Remove need for memory copy here
885
uname[file_name_len - sizeof(".dfe") + 1]= '\0'; // Subtract ending, place NULL
886
set_of_names.insert(uname);
538
891
class AddTableName :
539
public unary_function<StorageEngine *, void>
892
public unary_function<plugin::StorageEngine *, void>
541
CachedDirectory &directory;
542
SchemaIdentifier &identifier;
543
TableNameList &set_of_names;
895
CachedDirectory& directory;
896
set<string>& set_of_names;
547
AddTableName(CachedDirectory &directory_arg, SchemaIdentifier &identifier_arg, set<string>& of_names) :
900
AddTableName(CachedDirectory& directory_arg, string& database_name, set<string>& of_names) :
548
901
directory(directory_arg),
549
identifier(identifier_arg),
550
902
set_of_names(of_names)
554
result_type operator() (argument_type engine)
556
engine->doGetTableNames(directory, identifier, set_of_names);
560
class AddTableIdentifier :
561
public unary_function<StorageEngine *, void>
563
CachedDirectory &directory;
564
SchemaIdentifier &identifier;
565
TableIdentifiers &set_of_identifiers;
569
AddTableIdentifier(CachedDirectory &directory_arg, SchemaIdentifier &identifier_arg, TableIdentifiers &of_names) :
570
directory(directory_arg),
571
identifier(identifier_arg),
572
set_of_identifiers(of_names)
576
result_type operator() (argument_type engine)
578
engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
583
static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
584
static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
586
void StorageEngine::getTableNames(Session &session, SchemaIdentifier &schema_identifier, TableNameList &set_of_names)
588
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
590
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
592
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
596
if (directory.fail())
598
errno= directory.getError();
600
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_identifier.getSQLPath().c_str());
602
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
607
for_each(vector_of_engines.begin(), vector_of_engines.end(),
608
AddTableName(directory, schema_identifier, set_of_names));
610
session.doGetTableNames(directory, schema_identifier, set_of_names);
613
void StorageEngine::getTableIdentifiers(Session &session, SchemaIdentifier &schema_identifier, TableIdentifiers &set_of_identifiers)
615
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
617
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
619
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
623
if (directory.fail())
625
errno= directory.getError();
627
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_identifier.getSQLPath().c_str());
629
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
634
for_each(vector_of_engines.begin(), vector_of_engines.end(),
635
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
637
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
907
result_type operator() (argument_type engine)
909
engine->doGetTableNames(directory, db, set_of_names);
913
void plugin::StorageEngine::getTableNames(string& db, set<string>& set_of_names)
915
char tmp_path[FN_REFLEN];
917
build_table_filename(tmp_path, sizeof(tmp_path), db.c_str(), "", false);
919
CachedDirectory directory(tmp_path, set_of_table_definition_ext);
921
if (db.compare("information_schema"))
923
if (directory.fail())
925
my_errno= directory.getError();
926
if (my_errno == ENOENT)
927
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db.c_str());
929
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), my_errno);
934
for_each(vector_of_engines.begin(), vector_of_engines.end(),
935
AddTableName(directory, db, set_of_names));
640
938
/* This will later be converted to TableIdentifiers */
641
class DropTables: public unary_function<StorageEngine *, void>
939
class DropTables: public unary_function<plugin::StorageEngine *, void>
643
941
Session &session;
644
TableIdentifierList &table_identifiers;
942
set<string>& set_of_names;
648
DropTables(Session &session_arg, TableIdentifierList &table_identifiers_arg) :
946
DropTables(Session &session_arg, set<string>& of_names) :
649
947
session(session_arg),
650
table_identifiers(table_identifiers_arg)
948
set_of_names(of_names)
653
951
result_type operator() (argument_type engine)
655
for (TableIdentifierList::iterator iter= table_identifiers.begin();
656
iter != table_identifiers.end();
954
for (set<string>::iterator iter= set_of_names.begin();
955
iter != set_of_names.end();
659
int error= engine->doDropTable(session, const_cast<TableIdentifier&>(*iter));
958
int error= engine->doDropTable(session, *iter);
661
960
// On a return of zero we know we found and deleted the table. So we
662
961
// remove it from our search.
664
table_identifiers.erase(iter);
963
set_of_names.erase(iter);
1007
int StorageEngine::deleteDefinitionFromPath(TableIdentifier &identifier)
1301
int plugin::StorageEngine::deleteDefinitionFromPath(TableIdentifier &identifier)
1009
1303
string path(identifier.getPath());
1011
1305
path.append(DEFAULT_DEFINITION_FILE_EXT);
1013
return internal::my_delete(path.c_str(), MYF(0));
1307
return my_delete(path.c_str(), MYF(0));
1016
int StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1310
int plugin::StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1018
message::Table table_message;
1019
1312
string src_path(src.getPath());
1020
1313
string dest_path(dest.getPath());
1022
1315
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1023
1316
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1025
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1032
dest.copyToTableMessage(table_message);
1034
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1038
if (unlink(src_path.c_str()))
1039
perror(src_path.c_str());
1318
return my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1045
int StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_message)
1321
int plugin::StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_proto)
1047
char definition_file_tmp[FN_REFLEN];
1048
1323
string file_name(identifier.getPath());
1050
1325
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1052
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1054
int fd= mkstemp(definition_file_tmp);
1327
int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, my_umask);
1058
perror(definition_file_tmp);
1062
1332
google::protobuf::io::ZeroCopyOutputStream* output=
1063
1333
new google::protobuf::io::FileOutputStream(fd);
1065
if (not table_message.SerializeToZeroCopyStream(output))
1335
if (table_proto.SerializeToZeroCopyStream(output) == false)
1067
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1068
table_message.InitializationErrorString().c_str());
1071
if (close(fd) == -1)
1072
perror(definition_file_tmp);
1074
if (unlink(definition_file_tmp) == -1)
1075
perror(definition_file_tmp);
1077
return ER_CORRUPT_TABLE_DEFINITION;
1082
if (close(fd) == -1)
1085
perror(definition_file_tmp);
1087
if (unlink(definition_file_tmp))
1088
perror(definition_file_tmp);
1093
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1096
perror(definition_file_tmp);
1098
if (unlink(definition_file_tmp))
1099
perror(definition_file_tmp);
1107
class CanCreateTable: public unary_function<StorageEngine *, bool>
1109
TableIdentifier &identifier;
1112
CanCreateTable(TableIdentifier &identifier_arg) :
1113
identifier(identifier_arg)
1116
result_type operator() (argument_type engine)
1118
return not engine->doCanCreateTable(identifier);
1124
@note on success table can be created.
1126
bool StorageEngine::canCreateTable(drizzled::TableIdentifier &identifier)
1128
EngineVector::iterator iter=
1129
find_if(vector_of_engines.begin(), vector_of_engines.end(),
1130
CanCreateTable(identifier));
1132
if (iter == vector_of_engines.end())
1140
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1142
fstream input(path.c_str(), ios::in | ios::binary);
1146
if (table_message.ParseFromIstream(&input))
1151
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1152
table_message.InitializationErrorString().c_str());
1156
perror(path.c_str());
1164
} /* namespace plugin */
1165
1348
} /* namespace drizzled */