47
47
#include "drizzled/xid.h"
48
48
#include "drizzled/sql_table.h"
49
49
#include "drizzled/global_charset_info.h"
50
#include "drizzled/charset.h"
51
50
#include "drizzled/internal/my_sys.h"
52
#include "drizzled/db.h"
54
53
#include <drizzled/table_proto.h>
55
#include <drizzled/plugin/event_observer.h>
57
#include <drizzled/table/shell.h>
59
#include "drizzled/message/cache.h"
61
#include <boost/algorithm/string/compare.hpp>
55
#include "drizzled/hash.h"
63
57
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
64
typedef hash_map<std::string, plugin::StorageEngine *> EngineMap;
65
typedef std::vector<plugin::StorageEngine *> EngineVector;
71
67
static EngineVector vector_of_engines;
72
static EngineVector vector_of_schema_engines;
68
static EngineVector vector_of_transactional_engines;
74
const std::string DEFAULT_STRING("default");
75
const std::string UNKNOWN_STRING("UNKNOWN");
76
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
70
const std::string plugin::UNKNOWN_STRING("UNKNOWN");
71
const std::string plugin::DEFAULT_DEFINITION_FILE_EXT(".dfe");
78
73
static std::set<std::string> set_of_table_definition_ext;
80
EngineVector &StorageEngine::getSchemaEngines()
82
return vector_of_schema_engines;
85
StorageEngine::StorageEngine(const std::string name_arg,
86
const std::bitset<HTON_BIT_SIZE> &flags_arg) :
87
Plugin(name_arg, "StorageEngine"),
88
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
93
StorageEngine::~StorageEngine()
97
void StorageEngine::setTransactionReadWrite(Session& session)
99
TransactionContext &statement_ctx= session.transaction.stmt;
100
statement_ctx.markModifiedNonTransData();
104
int StorageEngine::renameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
107
setTransactionReadWrite(session);
109
if (unlikely(plugin::EventObserver::beforeRenameTable(session, from, to)))
111
error= ER_EVENT_OBSERVER_PLUGIN;
115
error = doRenameTable(session, from, to);
116
if (unlikely(plugin::EventObserver::afterRenameTable(session, from, to, error)))
75
plugin::StorageEngine::StorageEngine(const string name_arg,
76
const bitset<HTON_BIT_SIZE> &flags_arg,
77
size_t savepoint_offset_arg,
79
: Plugin(name_arg, "StorageEngine"),
80
two_phase_commit(support_2pc),
83
savepoint_offset(savepoint_alloc_size),
84
orig_savepoint_offset(savepoint_offset_arg),
89
savepoint_alloc_size+= orig_savepoint_offset;
94
pthread_mutex_init(&proto_cache_mutex, NULL);
98
plugin::StorageEngine::~StorageEngine()
100
savepoint_alloc_size-= orig_savepoint_offset;
101
pthread_mutex_destroy(&proto_cache_mutex);
104
void plugin::StorageEngine::setTransactionReadWrite(Session& session)
106
Ha_trx_info *ha_info= session.getEngineInfo(this);
109
When a storage engine method is called, the transaction must
110
have been started, unless it's a DDL call, for which the
111
storage engine starts the transaction internally, and commits
112
it internally, without registering in the ha_list.
113
Unfortunately here we can't know know for sure if the engine
114
has registered the transaction or not, so we must check.
116
if (ha_info->is_started())
119
* table_share can be NULL in plugin::StorageEngine::dropTable().
121
ha_info->set_trx_read_write();
127
int plugin::StorageEngine::doRenameTable(Session *,
132
for (const char **ext= bas_ext(); *ext ; ext++)
134
if (rename_file_ext(from, to, *ext))
118
error= ER_EVENT_OBSERVER_PLUGIN;
136
if ((error=errno) != ENOENT)
126
146
Delete all files with extension from bas_ext().
147
167
for (const char **ext= bas_ext(); *ext ; ext++)
149
internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
150
MY_UNPACK_FILENAME|MY_APPEND_EXT);
151
if (internal::my_delete_with_symlink(buff, MYF(0)))
169
fn_format(buff, table_path.c_str(), "", *ext,
170
MY_UNPACK_FILENAME|MY_APPEND_EXT);
171
if (my_delete_with_symlink(buff, MYF(0)))
153
173
if ((error= errno) != ENOENT)
158
177
enoent_or_zero= 0; // No error for ENOENT
161
178
error= enoent_or_zero;
166
bool StorageEngine::addPlugin(StorageEngine *engine)
183
const char *plugin::StorageEngine::checkLowercaseNames(const char *path,
186
if (flags.test(HTON_BIT_FILE_BASED))
189
/* Ensure that table Cursor get path in lower case */
190
if (tmp_path != path)
191
strcpy(tmp_path, path);
194
we only should turn into lowercase database/table part
195
so start the process after homedirectory
197
if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
198
my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
200
my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
206
bool plugin::StorageEngine::addPlugin(plugin::StorageEngine *engine)
169
209
vector_of_engines.push_back(engine);
211
if (engine->check_flag(HTON_BIT_DOES_TRANSACTIONS))
212
vector_of_transactional_engines.push_back(engine);
171
214
if (engine->getTableDefinitionFileExtension().length())
173
216
assert(engine->getTableDefinitionFileExtension().length() == DEFAULT_DEFINITION_FILE_EXT.length());
174
217
set_of_table_definition_ext.insert(engine->getTableDefinitionFileExtension());
177
if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
178
vector_of_schema_engines.push_back(engine);
183
void StorageEngine::removePlugin(StorageEngine *)
223
void plugin::StorageEngine::removePlugin(plugin::StorageEngine *)
185
225
if (shutdown_has_begun == false)
187
227
vector_of_engines.clear();
188
vector_of_schema_engines.clear();
228
vector_of_transactional_engines.clear();
190
230
shutdown_has_begun= true;
194
234
class FindEngineByName
195
: public std::unary_function<StorageEngine *, bool>
235
: public unary_function<plugin::StorageEngine *, bool>
197
const std::string &predicate;
200
explicit FindEngineByName(const std::string &target_arg) :
201
predicate(target_arg)
239
explicit FindEngineByName(const string target_arg)
205
242
result_type operator() (argument_type engine)
207
return boost::iequals(engine->getName(), predicate);
244
string engine_name(engine->getName());
246
transform(engine_name.begin(), engine_name.end(),
247
engine_name.begin(), ::tolower);
248
return engine_name == target;
211
StorageEngine *StorageEngine::findByName(const std::string &predicate)
252
plugin::StorageEngine *plugin::StorageEngine::findByName(string find_str)
213
EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
214
vector_of_engines.end(),
215
FindEngineByName(predicate));
254
transform(find_str.begin(), find_str.end(),
255
find_str.begin(), ::tolower);
258
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
259
vector_of_engines.end(),
260
FindEngineByName(find_str));
216
261
if (iter != vector_of_engines.end())
218
263
StorageEngine *engine= *iter;
262
313
don't bother to rollback here, it's done already
264
void StorageEngine::closeConnection(Session* session)
266
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
267
StorageEngineCloseConnection(session));
270
bool StorageEngine::flushLogs(StorageEngine *engine)
315
void plugin::StorageEngine::closeConnection(Session* session)
317
for_each(vector_of_engines.begin(), vector_of_engines.end(),
318
StorageEngineCloseConnection(session));
321
void plugin::StorageEngine::dropDatabase(char* path)
323
for_each(vector_of_engines.begin(), vector_of_engines.end(),
324
bind2nd(mem_fun(&plugin::StorageEngine::drop_database),path));
327
int plugin::StorageEngine::commitOrRollbackByXID(XID *xid, bool commit)
332
transform(vector_of_engines.begin(), vector_of_engines.end(), results.begin(),
333
bind2nd(mem_fun(&plugin::StorageEngine::commit_by_xid),xid));
335
transform(vector_of_engines.begin(), vector_of_engines.end(), results.begin(),
336
bind2nd(mem_fun(&plugin::StorageEngine::rollback_by_xid),xid));
338
if (find_if(results.begin(), results.end(), bind2nd(equal_to<int>(),0))
346
This function should be called when MySQL sends rows of a SELECT result set
347
or the EOF mark to the client. It releases a possible adaptive hash index
348
S-latch held by session in InnoDB and also releases a possible InnoDB query
349
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
350
keep them over several calls of the InnoDB Cursor interface when a join
351
is executed. But when we let the control to pass to the client they have
352
to be released because if the application program uses mysql_use_result(),
353
it may deadlock on the S-latch if the application on another connection
354
performs another SQL query. In MySQL-4.1 this is even more important because
355
there a connection can have several SELECT queries open at the same time.
357
@param session the thread handle of the current connection
362
int plugin::StorageEngine::releaseTemporaryLatches(Session *session)
364
for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
365
bind2nd(mem_fun(&plugin::StorageEngine::release_temporary_latches),session));
369
bool plugin::StorageEngine::flushLogs(plugin::StorageEngine *engine)
272
371
if (engine == NULL)
274
if (std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
275
std::mem_fun(&StorageEngine::flush_logs))
276
!= vector_of_engines.begin())
373
if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
374
mem_fun(&plugin::StorageEngine::flush_logs))
375
!= vector_of_engines.begin())
281
if (engine->flush_logs())
380
if ((!engine->is_enabled()) ||
381
(engine->flush_logs()))
287
class StorageEngineGetTableDefinition: public std::unary_function<StorageEngine *,bool>
388
recover() step of xa.
391
there are three modes of operation:
392
- automatic recover after a crash
393
in this case commit_list != 0, tc_heuristic_recover==0
394
all xids from commit_list are committed, others are rolled back
395
- manual (heuristic) recover
396
in this case commit_list==0, tc_heuristic_recover != 0
397
DBA has explicitly specified that all prepared transactions should
398
be committed (or rolled back).
399
- no recovery (MySQL did not detect a crash)
400
in this case commit_list==0, tc_heuristic_recover == 0
401
there should be no prepared transactions in this case.
403
class XARecover : unary_function<plugin::StorageEngine *, void>
405
int trans_len, found_foreign_xids, found_my_xids;
411
XARecover(XID *trans_list_arg, int trans_len_arg,
412
HASH *commit_list_arg, bool dry_run_arg)
413
: trans_len(trans_len_arg), found_foreign_xids(0), found_my_xids(0),
415
trans_list(trans_list_arg), commit_list(commit_list_arg),
421
return found_foreign_xids;
426
return found_my_xids;
429
result_type operator() (argument_type engine)
434
if (engine->is_enabled())
436
while ((got= engine->recover(trans_list, trans_len)) > 0 )
438
errmsg_printf(ERRMSG_LVL_INFO,
439
_("Found %d prepared transaction(s) in %s"),
440
got, engine->getName().c_str());
441
for (int i=0; i < got; i ++)
443
my_xid x=trans_list[i].get_my_xid();
444
if (!x) // not "mine" - that is generated by external TM
446
xid_cache_insert(trans_list+i, XA_PREPARED);
447
found_foreign_xids++;
457
hash_search(commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
458
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
460
engine->commit_by_xid(trans_list+i);
464
engine->rollback_by_xid(trans_list+i);
474
int plugin::StorageEngine::recover(HASH *commit_list)
476
XID *trans_list= NULL;
479
bool dry_run= (commit_list==0 && tc_heuristic_recover==0);
481
/* commit_list and tc_heuristic_recover cannot be set both */
482
assert(commit_list==0 || tc_heuristic_recover==0);
484
/* if either is set, total_ha_2pc must be set too */
485
if (total_ha_2pc <= 1)
489
#ifndef WILL_BE_DELETED_LATER
492
for now, only InnoDB supports 2pc. It means we can always safely
493
rollback all pending transactions, without risking inconsistent data
496
assert(total_ha_2pc == 2); // only InnoDB and binlog
497
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
500
for (trans_len= MAX_XID_LIST_SIZE ;
501
trans_list==0 && trans_len > MIN_XID_LIST_SIZE; trans_len/=2)
503
trans_list=(XID *)malloc(trans_len*sizeof(XID));
507
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), trans_len*sizeof(XID));
512
errmsg_printf(ERRMSG_LVL_INFO, _("Starting crash recovery..."));
515
XARecover recover_func(trans_list, trans_len, commit_list, dry_run);
516
for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
520
if (recover_func.getForeignXIDs())
521
errmsg_printf(ERRMSG_LVL_WARN,
522
_("Found %d prepared XA transactions"),
523
recover_func.getForeignXIDs());
524
if (dry_run && recover_func.getMyXIDs())
526
errmsg_printf(ERRMSG_LVL_ERROR,
527
_("Found %d prepared transactions! It means that drizzled "
528
"was not shut down properly last time and critical "
529
"recovery information (last binlog or %s file) was "
530
"manually deleted after a crash. You have to start "
531
"drizzled with the --tc-heuristic-recover switch to "
532
"commit or rollback pending transactions."),
533
recover_func.getMyXIDs(), opt_tc_log_file);
537
errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
541
int plugin::StorageEngine::startConsistentSnapshot(Session *session)
543
for_each(vector_of_engines.begin(), vector_of_engines.end(),
544
bind2nd(mem_fun(&plugin::StorageEngine::start_consistent_snapshot),
549
class StorageEngineGetTableDefinition: public unary_function<plugin::StorageEngine *,bool>
289
551
Session& session;
290
const TableIdentifier &identifier;
291
message::Table &table_message;
554
const char *table_name;
556
message::Table *table_proto;
295
560
StorageEngineGetTableDefinition(Session& session_arg,
296
const TableIdentifier &identifier_arg,
297
message::Table &table_message_arg,
561
const char* path_arg,
563
const char *table_name_arg,
564
const bool is_tmp_arg,
565
message::Table *table_proto_arg,
299
567
session(session_arg),
300
identifier(identifier_arg),
301
table_message(table_message_arg),
570
table_name(table_name_arg),
572
table_proto(table_proto_arg),
304
575
result_type operator() (argument_type engine)
306
int ret= engine->doGetTableDefinition(session, identifier, table_message);
577
int ret= engine->doGetTableDefinition(session,
308
584
if (ret != ENOENT)
311
return err == EEXIST || err != ENOENT;
315
class StorageEngineDoesTableExist: public std::unary_function<StorageEngine *, bool>
318
const TableIdentifier &identifier;
321
StorageEngineDoesTableExist(Session& session_arg, const TableIdentifier &identifier_arg) :
322
session(session_arg),
323
identifier(identifier_arg)
326
result_type operator() (argument_type engine)
328
return engine->doDoesTableExist(session, identifier);
333
Utility method which hides some of the details of getTableDefinition()
335
bool plugin::StorageEngine::doesTableExist(Session &session,
336
const TableIdentifier &identifier,
337
bool include_temporary_tables)
339
if (include_temporary_tables)
341
if (session.doDoesTableExist(identifier))
345
EngineVector::iterator iter=
346
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
347
StorageEngineDoesTableExist(session, identifier));
349
if (iter == vector_of_engines.end())
357
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::TableIdentifier&)
359
std::cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
587
return *err == EEXIST;
591
static int drizzle_read_table_proto(const char* path, message::Table* table)
593
int fd= open(path, O_RDONLY);
598
google::protobuf::io::ZeroCopyInputStream* input=
599
new google::protobuf::io::FileInputStream(fd);
601
if (table->ParseFromZeroCopyStream(input) == false)
366
615
to ask engine if there are any new tables that should be written to disk
367
616
or any dropped tables that need to be removed from disk
369
int StorageEngine::getTableDefinition(Session& session,
370
const TableIdentifier &identifier,
371
message::table::shared_ptr &table_message,
372
bool include_temporary_tables)
618
int plugin::StorageEngine::getTableDefinition(Session& session,
619
TableIdentifier &identifier,
620
message::Table *table_proto)
622
return getTableDefinition(session,
623
identifier.getPath(), identifier.getDBName(), identifier.getTableName(), identifier.isTmp(),
627
int plugin::StorageEngine::getTableDefinition(Session& session,
632
message::Table *table_proto)
376
if (include_temporary_tables)
636
vector<plugin::StorageEngine *>::iterator iter=
637
find_if(vector_of_engines.begin(), vector_of_engines.end(),
638
StorageEngineGetTableDefinition(session, path, NULL, NULL, true, table_proto, &err));
640
if (iter == vector_of_engines.end())
378
Table *table= session.find_temporary_table(identifier);
642
string proto_path(path);
643
string file_ext(".dfe");
644
proto_path.append(file_ext);
646
int error= access(proto_path.c_str(), F_OK);
381
table_message.reset(new message::Table(*table->getShare()->getTableProto()));
655
int read_proto_err= drizzle_read_table_proto(proto_path.c_str(),
386
drizzled::message::table::shared_ptr table_ptr;
387
if ((table_ptr= drizzled::message::Cache::singleton().find(identifier)))
389
table_message= table_ptr;
392
message::Table message;
393
EngineVector::iterator iter=
394
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
395
StorageEngineGetTableDefinition(session, identifier, message, err));
397
if (iter == vector_of_engines.end())
401
table_message.reset(new message::Table(message));
403
drizzled::message::Cache::singleton().insert(identifier, table_message);
439
698
returns ENOENT if the file doesn't exists.
441
int StorageEngine::dropTable(Session& session,
442
const TableIdentifier &identifier)
700
int plugin::StorageEngine::dropTable(Session& session,
701
TableIdentifier &identifier,
702
bool generate_warning)
446
message::table::shared_ptr src_proto;
447
StorageEngine *engine;
449
error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
451
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
453
std::string error_message;
454
identifier.getSQLPath(error_message);
456
error_message.append(" : ");
457
error_message.append(src_proto->InitializationErrorString());
459
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
461
return ER_CORRUPT_TABLE_DEFINITION;
465
engine= StorageEngine::findByName(session, src_proto->engine().name());
467
engine= StorageEngine::findByName(session, "");
471
std::string error_message;
472
identifier.getSQLPath(error_message);
473
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
475
return ER_CORRUPT_TABLE_DEFINITION;
478
error= StorageEngine::dropTable(session, *engine, identifier);
706
message::Table src_proto;
707
plugin::StorageEngine* engine;
709
error_proto= plugin::StorageEngine::getTableDefinition(session,
713
engine= plugin::StorageEngine::findByName(session,
714
src_proto.engine().name());
718
engine->setTransactionReadWrite(session);
719
error= engine->doDropTable(session, identifier.getPath());
726
if (engine && engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
728
deleteDefinitionFromPath(identifier);
732
error= deleteDefinitionFromPath(identifier);
480
737
if (error_proto && error == 0)
486
int StorageEngine::dropTable(Session& session,
487
StorageEngine &engine,
488
const TableIdentifier &identifier)
492
engine.setTransactionReadWrite(session);
494
if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
496
error= ER_EVENT_OBSERVER_PLUGIN;
500
error= engine.doDropTable(session, identifier);
501
if (unlikely(plugin::EventObserver::afterDropTable(session, identifier, error)))
503
error= ER_EVENT_OBSERVER_PLUGIN;
507
drizzled::message::Cache::singleton().erase(identifier);
740
if (error && generate_warning)
743
Because engine->print_error() use my_error() to generate the error message
744
we use an internal error Cursor to intercept it and store the text
745
in a temporary buffer. Later the message will be presented to user
748
Ha_delete_table_error_handler ha_delete_table_error_handler;
750
session.push_internal_handler(&ha_delete_table_error_handler);
751
engine->print_error(error, 0);
753
session.pop_internal_handler();
756
XXX: should we convert *all* errors to warnings here?
757
What if the error is fatal?
759
push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
760
ha_delete_table_error_handler.buff);
514
767
Initiates table-file and calls appropriate database-creator.
774
@todo refactor to remove goto
521
int StorageEngine::createTable(Session &session,
522
const TableIdentifier &identifier,
523
message::Table& table_message)
776
int plugin::StorageEngine::createTable(Session& session,
777
TableIdentifier &identifier,
778
bool update_create_info,
779
drizzled::message::Table& table_proto, bool proto_used)
526
TableShare share(identifier);
527
table::Shell table(share);
783
TableShare share(identifier.getDBName(), 0, identifier.getTableName(), identifier.getPath());
528
784
message::Table tmp_proto;
530
if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
532
// @note Error occured, we should probably do a little more here.
788
if (parse_table_proto(session, table_proto, &share))
536
/* Check for legal operations against the Engine using the proto (if used) */
537
if (table_message.type() == message::Table::TEMPORARY &&
793
if (open_table_def(session, &share))
797
if (open_table_from_share(&session, &share, "", 0, 0,
801
if (update_create_info)
802
table.updateCreateInfo(&table_proto);
804
/* Check for legal operations against the Engine using the proto (if used) */
807
if (table_proto.type() == message::Table::TEMPORARY &&
538
808
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
540
810
error= HA_ERR_UNSUPPORTED;
542
else if (table_message.type() != message::Table::TEMPORARY &&
813
else if (table_proto.type() != message::Table::TEMPORARY &&
543
814
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
545
816
error= HA_ERR_UNSUPPORTED;
549
share.storage_engine->setTransactionReadWrite(session);
551
error= share.storage_engine->doCreateTable(session,
560
identifier.getSQLPath(path);
561
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), path.c_str(), error);
564
table.delete_table();
821
if (! share.storage_engine->is_enabled())
823
error= HA_ERR_UNSUPPORTED;
829
char name_buff[FN_REFLEN];
830
const char *table_name_arg;
832
table_name_arg= share.storage_engine->checkLowercaseNames(identifier.getPath(), name_buff);
834
share.storage_engine->setTransactionReadWrite(session);
836
error= share.storage_engine->doCreateTable(&session,
843
table.closefrm(false);
847
char name_buff[FN_REFLEN];
848
sprintf(name_buff,"%s.%s", identifier.getDBName(), identifier.getTableName());
849
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
852
share.free_table_share();
567
853
return(error != 0);
570
Cursor *StorageEngine::getCursor(Table &arg)
575
class AddTableIdentifier :
576
public std::unary_function<StorageEngine *, void>
578
CachedDirectory &directory;
579
const SchemaIdentifier &identifier;
580
TableIdentifier::vector &set_of_identifiers;
856
Cursor *plugin::StorageEngine::getCursor(TableShare &share, memory::Root *alloc)
859
return create(share, alloc);
863
TODO -> Remove this to force all engines to implement their own file. Solves the "we only looked at dfe" problem.
865
void plugin::StorageEngine::doGetTableNames(CachedDirectory &directory, string&, set<string>& set_of_names)
867
CachedDirectory::Entries entries= directory.getEntries();
869
for (CachedDirectory::Entries::iterator entry_iter= entries.begin();
870
entry_iter != entries.end(); ++entry_iter)
872
CachedDirectory::Entry *entry= *entry_iter;
873
const string *filename= &entry->filename;
875
assert(filename->size());
877
const char *ext= strchr(filename->c_str(), '.');
879
if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_DEFINITION_FILE_EXT.c_str()) ||
880
(filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
884
char uname[NAME_LEN + 1];
885
uint32_t file_name_len;
887
file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
888
// TODO: Remove need for memory copy here
889
uname[file_name_len - sizeof(".dfe") + 1]= '\0'; // Subtract ending, place NULL
890
set_of_names.insert(uname);
896
public unary_function<plugin::StorageEngine *, void>
899
CachedDirectory& directory;
900
set<string>& set_of_names;
584
AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifier::vector &of_names) :
904
AddTableName(CachedDirectory& directory_arg, string& database_name, set<string>& of_names) :
585
905
directory(directory_arg),
586
identifier(identifier_arg),
587
set_of_identifiers(of_names)
906
set_of_names(of_names)
591
911
result_type operator() (argument_type engine)
593
engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
913
engine->doGetTableNames(directory, db, set_of_names);
598
void StorageEngine::getIdentifiers(Session &session, const SchemaIdentifier &schema_identifier, TableIdentifier::vector &set_of_identifiers)
917
void plugin::StorageEngine::getTableNames(string& db, set<string>& set_of_names)
600
static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
601
static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
603
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
605
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
607
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
919
char tmp_path[FN_REFLEN];
921
build_table_filename(tmp_path, sizeof(tmp_path), db.c_str(), "", false);
923
CachedDirectory directory(tmp_path, set_of_table_definition_ext);
925
if (db.compare("information_schema"))
611
927
if (directory.fail())
613
929
errno= directory.getError();
614
930
if (errno == ENOENT)
617
schema_identifier.getSQLPath(path);
618
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), path.c_str());
931
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db.c_str());
622
933
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
629
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
630
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
632
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
938
for_each(vector_of_engines.begin(), vector_of_engines.end(),
939
AddTableName(directory, db, set_of_names));
635
class DropTable: public std::unary_function<TableIdentifier&, bool>
638
StorageEngine *engine;
642
DropTable(Session &session_arg, StorageEngine *engine_arg) :
643
session(session_arg),
647
result_type operator() (argument_type identifier)
649
return engine->doDropTable(session, identifier) == 0;
653
942
/* This will later be converted to TableIdentifiers */
654
class DropTables: public std::unary_function<StorageEngine *, void>
943
class DropTables: public unary_function<plugin::StorageEngine *, void>
656
945
Session &session;
657
TableIdentifier::vector &table_identifiers;
946
set<string>& set_of_names;
661
DropTables(Session &session_arg, TableIdentifier::vector &table_identifiers_arg) :
950
DropTables(Session &session_arg, set<string>& of_names) :
662
951
session(session_arg),
663
table_identifiers(table_identifiers_arg)
952
set_of_names(of_names)
666
955
result_type operator() (argument_type engine)
668
// True returning from DropTable means the table has been successfully
669
// deleted, so it should be removed from the list of tables to drop
670
table_identifiers.erase(std::remove_if(table_identifiers.begin(),
671
table_identifiers.end(),
672
DropTable(session, engine)),
673
table_identifiers.end());
958
for (set<string>::iterator iter= set_of_names.begin();
959
iter != set_of_names.end();
962
int error= engine->doDropTable(session, *iter);
964
// On a return of zero we know we found and deleted the table. So we
965
// remove it from our search.
967
set_of_names.erase(iter);
1008
int StorageEngine::deleteDefinitionFromPath(const TableIdentifier &identifier)
1305
int plugin::StorageEngine::deleteDefinitionFromPath(TableIdentifier &identifier)
1010
std::string path(identifier.getPath());
1307
string path(identifier.getPath());
1012
1309
path.append(DEFAULT_DEFINITION_FILE_EXT);
1014
return internal::my_delete(path.c_str(), MYF(0));
1311
return my_delete(path.c_str(), MYF(0));
1017
int StorageEngine::renameDefinitionFromPath(const TableIdentifier &dest, const TableIdentifier &src)
1314
int plugin::StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1019
message::Table table_message;
1020
std::string src_path(src.getPath());
1021
std::string dest_path(dest.getPath());
1316
string src_path(src.getPath());
1317
string dest_path(dest.getPath());
1023
1319
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1024
1320
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1026
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1033
dest.copyToTableMessage(table_message);
1035
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1039
if (unlink(src_path.c_str()))
1040
perror(src_path.c_str());
1322
return my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1046
int StorageEngine::writeDefinitionFromPath(const TableIdentifier &identifier, message::Table &table_message)
1325
int plugin::StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_proto)
1048
char definition_file_tmp[FN_REFLEN];
1049
std::string file_name(identifier.getPath());
1327
string file_name(identifier.getPath());
1051
1329
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1053
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1055
int fd= mkstemp(definition_file_tmp);
1331
int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, my_umask);
1059
perror(definition_file_tmp);
1063
1336
google::protobuf::io::ZeroCopyOutputStream* output=
1064
1337
new google::protobuf::io::FileOutputStream(fd);
1070
success= table_message.SerializeToZeroCopyStream(output);
1079
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1080
table_message.InitializationErrorString().c_str());
1339
if (table_proto.SerializeToZeroCopyStream(output) == false)
1083
if (close(fd) == -1)
1084
perror(definition_file_tmp);
1086
if (unlink(definition_file_tmp) == -1)
1087
perror(definition_file_tmp);
1089
return ER_CORRUPT_TABLE_DEFINITION;
1094
if (close(fd) == -1)
1097
perror(definition_file_tmp);
1099
if (unlink(definition_file_tmp))
1100
perror(definition_file_tmp);
1105
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1108
perror(definition_file_tmp);
1110
if (unlink(definition_file_tmp))
1111
perror(definition_file_tmp);
1119
class CanCreateTable: public std::unary_function<StorageEngine *, bool>
1121
const TableIdentifier &identifier;
1124
CanCreateTable(const TableIdentifier &identifier_arg) :
1125
identifier(identifier_arg)
1128
result_type operator() (argument_type engine)
1130
return not engine->doCanCreateTable(identifier);
1136
@note on success table can be created.
1138
bool StorageEngine::canCreateTable(const TableIdentifier &identifier)
1140
EngineVector::iterator iter=
1141
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1142
CanCreateTable(identifier));
1144
if (iter == vector_of_engines.end())
1152
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1154
std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
1159
if (table_message.ParseFromIstream(&input))
1166
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1167
table_message.InitializationErrorString().empty() ? "": table_message.InitializationErrorString().c_str());
1172
perror(path.c_str());
1180
} /* namespace plugin */
1181
1352
} /* namespace drizzled */