28
41
#include <drizzled/registry.h>
29
42
#include <drizzled/unireg.h>
30
43
#include <drizzled/data_home.h>
44
#include "drizzled/errmsg_print.h"
31
45
#include <drizzled/plugin/registry.h>
46
#include "drizzled/xid.h"
34
48
#include <drizzled/table_proto.h>
36
#include <google/protobuf/io/zero_copy_stream.h>
37
#include <google/protobuf/io/zero_copy_stream_impl.h>
39
#include <mysys/my_dir.h>
43
50
using namespace std;
44
using namespace drizzled;
46
drizzled::Registry<StorageEngine *> all_engines;
48
void add_storage_engine(StorageEngine *engine)
50
all_engines.add(engine);
53
void remove_storage_engine(StorageEngine *engine)
55
all_engines.remove(engine);
58
StorageEngine::StorageEngine(const std::string name_arg,
59
const std::bitset<HTON_BIT_SIZE> &flags_arg,
60
size_t savepoint_offset_arg,
56
Registry<plugin::StorageEngine *> all_engines;
58
plugin::StorageEngine::StorageEngine(const string name_arg,
59
const bitset<HTON_BIT_SIZE> &flags_arg,
60
size_t savepoint_offset_arg,
62
62
: name(name_arg), two_phase_commit(support_2pc), enabled(true),
64
64
savepoint_offset(savepoint_alloc_size),
94
94
if (ha_info->is_started())
97
table_share can be NULL in ha_delete_table(). See implementation
98
of standalone function ha_delete_table() in sql_base.cc.
97
* table_share can be NULL in plugin::StorageEngine::deleteTable().
100
99
ha_info->set_trx_read_write();
106
Return the default storage engine StorageEngine for thread
108
@param ha_default_storage_engine(session)
109
@param session current thread
112
pointer to StorageEngine
114
StorageEngine *ha_default_storage_engine(Session *session)
116
if (session->variables.storage_engine)
117
return session->variables.storage_engine;
118
return global_system_variables.storage_engine;
123
Return the storage engine StorageEngine for the supplied name
125
@param session current thread
126
@param name name of storage engine
129
pointer to storage engine plugin handle
131
StorageEngine *ha_resolve_by_name(Session *session, std::string find_str)
105
int plugin::StorageEngine::renameTableImplementation(Session *,
110
for (const char **ext= bas_ext(); *ext ; ext++)
112
if (rename_file_ext(from, to, *ext))
114
if ((error=my_errno) != ENOENT)
124
Delete all files with extension from bas_ext().
126
@param name Base name of table
129
We assume that the handler may return more extensions than
130
was actually used for the file.
133
0 If we successfully deleted at least one file from base_ext and
134
didn't get any other errors than ENOENT
138
int plugin::StorageEngine::deleteTableImplementation(Session *,
139
const string table_path)
142
int enoent_or_zero= ENOENT; // Error if no file was deleted
143
char buff[FN_REFLEN];
145
for (const char **ext=bas_ext(); *ext ; ext++)
147
fn_format(buff, table_path.c_str(), "", *ext,
148
MY_UNPACK_FILENAME|MY_APPEND_EXT);
149
if (my_delete_with_symlink(buff, MYF(0)))
151
if ((error= my_errno) != ENOENT)
155
enoent_or_zero= 0; // No error for ENOENT
156
error= enoent_or_zero;
161
const char *plugin::StorageEngine::checkLowercaseNames(const char *path,
164
if (flags.test(HTON_BIT_FILE_BASED))
167
/* Ensure that table handler get path in lower case */
168
if (tmp_path != path)
169
strcpy(tmp_path, path);
172
we only should turn into lowercase database/table part
173
so start the process after homedirectory
175
if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
176
my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
178
my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
184
bool plugin::StorageEngine::addPlugin(plugin::StorageEngine *engine)
186
if (all_engines.add(engine))
188
errmsg_printf(ERRMSG_LVL_ERROR,
189
_("Couldn't add StorageEngine"));
195
void plugin::StorageEngine::removePlugin(plugin::StorageEngine *engine)
197
all_engines.remove(engine);
200
plugin::StorageEngine *plugin::StorageEngine::findByName(Session *session,
133
204
transform(find_str.begin(), find_str.end(),
134
205
find_str.begin(), ::tolower);
135
206
string default_str("default");
136
207
if (find_str == default_str)
137
208
return ha_default_storage_engine(session);
139
StorageEngine *engine= all_engines.find(find_str);
210
plugin::StorageEngine *engine= all_engines.find(find_str);
141
212
if (engine && engine->is_user_selectable())
148
handler *get_new_handler(TableShare *share, MEM_ROOT *alloc,
149
StorageEngine *engine)
153
if (engine && engine->is_enabled())
155
if ((file= engine->create(share, alloc)))
160
Try the default table type
161
Here the call to current_session() is ok as we call this function a lot of
162
times but we enter this branch very seldom.
164
return(get_new_handler(share, alloc, ha_default_storage_engine(current_session)));
167
218
class StorageEngineCloseConnection
168
: public unary_function<StorageEngine *, void>
219
: public unary_function<plugin::StorageEngine *, void>
170
221
Session *session;
187
238
don't bother to rollback here, it's done already
189
void ha_close_connection(Session* session)
240
void plugin::StorageEngine::closeConnection(Session* session)
191
242
for_each(all_engines.begin(), all_engines.end(),
192
243
StorageEngineCloseConnection(session));
195
void ha_drop_database(char* path)
246
void plugin::StorageEngine::dropDatabase(char* path)
197
248
for_each(all_engines.begin(), all_engines.end(),
198
bind2nd(mem_fun(&StorageEngine::drop_database),path));
249
bind2nd(mem_fun(&plugin::StorageEngine::drop_database),path));
201
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
252
int plugin::StorageEngine::commitOrRollbackByXID(XID *xid, bool commit)
203
254
vector<int> results;
206
257
transform(all_engines.begin(), all_engines.end(), results.begin(),
207
bind2nd(mem_fun(&StorageEngine::commit_by_xid),xid));
258
bind2nd(mem_fun(&plugin::StorageEngine::commit_by_xid),xid));
209
260
transform(all_engines.begin(), all_engines.end(), results.begin(),
210
bind2nd(mem_fun(&StorageEngine::rollback_by_xid),xid));
261
bind2nd(mem_fun(&plugin::StorageEngine::rollback_by_xid),xid));
212
263
if (find_if(results.begin(), results.end(), bind2nd(equal_to<int>(),0))
213
264
== results.end())
237
int ha_release_temporary_latches(Session *session)
287
int plugin::StorageEngine::releaseTemporaryLatches(Session *session)
239
289
for_each(all_engines.begin(), all_engines.end(),
240
bind2nd(mem_fun(&StorageEngine::release_temporary_latches),session));
290
bind2nd(mem_fun(&plugin::StorageEngine::release_temporary_latches),session));
245
bool ha_flush_logs(StorageEngine *engine)
294
bool plugin::StorageEngine::flushLogs(plugin::StorageEngine *engine)
247
296
if (engine == NULL)
249
298
if (find_if(all_engines.begin(), all_engines.end(),
250
mem_fun(&StorageEngine::flush_logs))
299
mem_fun(&plugin::StorageEngine::flush_logs))
251
300
!= all_engines.begin())
417
int ha_start_consistent_snapshot(Session *session)
465
int plugin::StorageEngine::startConsistentSnapshot(Session *session)
419
467
for_each(all_engines.begin(), all_engines.end(),
420
bind2nd(mem_fun(&StorageEngine::start_consistent_snapshot),session));
468
bind2nd(mem_fun(&plugin::StorageEngine::start_consistent_snapshot),
473
class StorageEngineGetTableProto: public unary_function<plugin::StorageEngine *,bool>
476
message::Table *table_proto;
479
StorageEngineGetTableProto(const char* path_arg,
480
message::Table *table_proto_arg,
482
:path(path_arg), table_proto(table_proto_arg), err(err_arg) {}
484
result_type operator() (argument_type engine)
486
int ret= engine->getTableProtoImplementation(path, table_proto);
491
return *err == EEXIST;
424
495
static int drizzle_read_table_proto(const char* path, message::Table* table)
426
497
int fd= open(path, O_RDONLY);
446
class StorageEngineGetTableProto: public unary_function<StorageEngine *,bool>
449
message::Table *table_proto;
452
StorageEngineGetTableProto(const char* path_arg,
453
message::Table *table_proto_arg,
455
:path(path_arg), table_proto(table_proto_arg), err(err_arg) {}
457
result_type operator() (argument_type engine)
459
int ret= engine->getTableProtoImplementation(path, table_proto);
464
return *err == EEXIST;
469
518
Call this function in order to give the handler the possiblity
470
519
to ask engine if there are any new tables that should be written to disk
471
520
or any dropped tables that need to be removed from disk
473
int StorageEngine::getTableProto(const char* path,
474
message::Table *table_proto)
522
int plugin::StorageEngine::getTableProto(const char* path,
523
message::Table *table_proto)
478
drizzled::Registry<StorageEngine *>::iterator iter=
527
::drizzled::Registry<plugin::StorageEngine *>::iterator iter=
479
528
find_if(all_engines.begin(), all_engines.end(),
480
529
StorageEngineGetTableProto(path, table_proto, &err));
481
530
if (iter == all_engines.end())
508
int StorageEngine::renameTableImplementation(Session *, const char *from, const char *to)
511
for (const char **ext= bas_ext(); *ext ; ext++)
513
if (rename_file_ext(from, to, *ext))
515
if ((error=my_errno) != ENOENT)
525
Delete all files with extension from bas_ext().
527
@param name Base name of table
530
We assume that the handler may return more extensions than
531
was actually used for the file.
534
0 If we successfully deleted at least one file from base_ext and
535
didn't get any other errors than ENOENT
539
int StorageEngine::deleteTableImplementation(Session *, const std::string table_path)
542
int enoent_or_zero= ENOENT; // Error if no file was deleted
543
char buff[FN_REFLEN];
545
for (const char **ext=bas_ext(); *ext ; ext++)
547
fn_format(buff, table_path.c_str(), "", *ext,
548
MY_UNPACK_FILENAME|MY_APPEND_EXT);
549
if (my_delete_with_symlink(buff, MYF(0)))
551
if ((error= my_errno) != ENOENT)
555
enoent_or_zero= 0; // No error for ENOENT
556
error= enoent_or_zero;
562
557
An interceptor to hijack the text of the error message without
563
558
setting an error in the thread. We need the text to present it
720
Initiates table-file and calls appropriate database-creator.
727
int ha_create_table(Session *session, const char *path,
728
const char *db, const char *table_name,
729
HA_CREATE_INFO *create_info,
730
bool update_create_info,
731
message::Table *table_proto)
735
TableShare share(db, 0, table_name, path);
736
message::Table tmp_proto;
740
if (parse_table_proto(session, *table_proto, &share))
745
table_proto= &tmp_proto;
746
if (open_table_def(session, &share))
750
if (open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0,
754
if (update_create_info)
755
table.updateCreateInfo(create_info, table_proto);
757
error= share.storage_engine->createTable(session, path, &table,
758
create_info, table_proto);
759
table.closefrm(false);
762
char name_buff[FN_REFLEN];
763
sprintf(name_buff,"%s.%s",db,table_name);
764
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
767
share.free_table_share();
772
const string ha_resolve_storage_engine_name(const StorageEngine *engine)
774
return engine == NULL ? string("UNKNOWN") : engine->getName();
777
const char *StorageEngine::checkLowercaseNames(const char *path, char *tmp_path)
779
if (flags.test(HTON_BIT_FILE_BASED))
782
/* Ensure that table handler get path in lower case */
783
if (tmp_path != path)
784
strcpy(tmp_path, path);
787
we only should turn into lowercase database/table part
788
so start the process after homedirectory
790
if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
791
my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
793
my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
798
class DFETableNameIterator: public TableNameIteratorImplementation
715
class DFETableNameIterator: public plugin::TableNameIteratorImplementation
802
719
uint32_t current_entry;
805
DFETableNameIterator(const std::string &database)
806
: TableNameIteratorImplementation(database),
722
DFETableNameIterator(const string &database)
723
: plugin::TableNameIteratorImplementation(database),
808
725
current_entry(-1)
811
728
~DFETableNameIterator();
813
int next(std::string *name);
730
int next(string *name);
883
TableNameIterator::TableNameIterator(const std::string &db)
801
plugin::TableNameIterator::TableNameIterator(const string &db)
884
802
: current_implementation(NULL), database(db)
886
804
engine_iter= all_engines.begin();
887
805
default_implementation= new DFETableNameIterator(database);
890
TableNameIterator::~TableNameIterator()
808
plugin::TableNameIterator::~TableNameIterator()
892
810
delete current_implementation;
811
if (current_implementation != default_implementation)
813
delete default_implementation;
895
int TableNameIterator::next(std::string *name)
817
int plugin::TableNameIterator::next(string *name)
900
822
if (current_implementation == NULL)
902
while(current_implementation == NULL && engine_iter != all_engines.end())
824
while(current_implementation == NULL &&
825
(engine_iter != all_engines.end()))
904
StorageEngine *engine= *engine_iter;
827
plugin::StorageEngine *engine= *engine_iter;
905
828
current_implementation= engine->tableNameIterator(database);
909
if (current_implementation == NULL && engine_iter == all_engines.end())
832
if (current_implementation == NULL &&
833
(engine_iter == all_engines.end()))
911
835
current_implementation= default_implementation;
855
} /* namespace drizzled */
859
handler *get_new_handler(TableShare *share, MEM_ROOT *alloc,
860
drizzled::plugin::StorageEngine *engine)
864
if (engine && engine->is_enabled())
866
if ((file= engine->create(share, alloc)))
871
Try the default table type
872
Here the call to current_session() is ok as we call this function a lot of
873
times but we enter this branch very seldom.
875
return(get_new_handler(share, alloc, ha_default_storage_engine(current_session)));
880
Return the default storage engine plugin::StorageEngine for thread
882
@param ha_default_storage_engine(session)
883
@param session current thread
886
pointer to plugin::StorageEngine
888
drizzled::plugin::StorageEngine *ha_default_storage_engine(Session *session)
890
if (session->variables.storage_engine)
891
return session->variables.storage_engine;
892
return global_system_variables.storage_engine;
896
Initiates table-file and calls appropriate database-creator.
903
int ha_create_table(Session *session, const char *path,
904
const char *db, const char *table_name,
905
HA_CREATE_INFO *create_info,
906
bool update_create_info,
907
drizzled::message::Table *table_proto)
911
TableShare share(db, 0, table_name, path);
912
drizzled::message::Table tmp_proto;
916
if (parse_table_proto(session, *table_proto, &share))
921
table_proto= &tmp_proto;
922
if (open_table_def(session, &share))
926
if (open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0,
930
if (update_create_info)
931
table.updateCreateInfo(create_info, table_proto);
933
error= share.storage_engine->createTable(session, path, &table,
934
create_info, table_proto);
935
table.closefrm(false);
938
char name_buff[FN_REFLEN];
939
sprintf(name_buff,"%s.%s",db,table_name);
940
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
943
share.free_table_share();