~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

  • Committer: Diego Medina
  • Date: 2009-10-05 04:05:29 UTC
  • mfrom: (1161 staging)
  • mto: This revision was merged to the branch mainline in revision 1178.
  • Revision ID: diego.medina@sun.com-20091005040529-5g1qe9gxzslpgefd
resolved small merge issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
#include <drizzled/server_includes.h>
 
21
 
 
22
#include CSTDINT_H
 
23
#include <string>
 
24
#include <vector>
 
25
#include <algorithm>
 
26
#include <functional>
 
27
 
 
28
#include <google/protobuf/io/zero_copy_stream.h>
 
29
#include <google/protobuf/io/zero_copy_stream_impl.h>
 
30
 
 
31
#include "mysys/my_dir.h"
 
32
#include "mysys/hash.h"
 
33
 
21
34
#include <drizzled/definitions.h>
22
35
#include <drizzled/base.h>
23
36
#include <drizzled/handler.h>
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>
32
 
#include <string>
 
46
#include "drizzled/xid.h"
33
47
 
34
48
#include <drizzled/table_proto.h>
35
49
 
36
 
#include <google/protobuf/io/zero_copy_stream.h>
37
 
#include <google/protobuf/io/zero_copy_stream_impl.h>
38
 
 
39
 
#include <mysys/my_dir.h>
40
 
 
41
 
#include CSTDINT_H
42
 
 
43
50
using namespace std;
44
 
using namespace drizzled;
45
 
 
46
 
drizzled::Registry<StorageEngine *> all_engines;
47
 
 
48
 
void add_storage_engine(StorageEngine *engine)
49
 
{
50
 
  all_engines.add(engine);
51
 
}
52
 
 
53
 
void remove_storage_engine(StorageEngine *engine)
54
 
{
55
 
  all_engines.remove(engine);
56
 
}
57
 
 
58
 
StorageEngine::StorageEngine(const std::string name_arg,
59
 
                             const std::bitset<HTON_BIT_SIZE> &flags_arg,
60
 
                             size_t savepoint_offset_arg,
61
 
                             bool support_2pc)
 
51
 
 
52
 
 
53
namespace drizzled
 
54
{
 
55
 
 
56
Registry<plugin::StorageEngine *> all_engines;
 
57
 
 
58
plugin::StorageEngine::StorageEngine(const string name_arg,
 
59
                                     const bitset<HTON_BIT_SIZE> &flags_arg,
 
60
                                     size_t savepoint_offset_arg,
 
61
                                     bool support_2pc)
62
62
    : name(name_arg), two_phase_commit(support_2pc), enabled(true),
63
63
      flags(flags_arg),
64
64
      savepoint_offset(savepoint_alloc_size),
75
75
}
76
76
 
77
77
 
78
 
StorageEngine::~StorageEngine()
 
78
plugin::StorageEngine::~StorageEngine()
79
79
{
80
80
  savepoint_alloc_size-= orig_savepoint_offset;
81
81
}
82
82
 
83
 
void StorageEngine::setTransactionReadWrite(Session* session)
 
83
void plugin::StorageEngine::setTransactionReadWrite(Session* session)
84
84
{
85
85
  Ha_trx_info *ha_info= &session->ha_data[getSlot()].ha_info[0];
86
86
  /*
94
94
  if (ha_info->is_started())
95
95
  {
96
96
    /*
97
 
      table_share can be NULL in ha_delete_table(). See implementation
98
 
      of standalone function ha_delete_table() in sql_base.cc.
99
 
    */
 
97
     * table_share can be NULL in plugin::StorageEngine::deleteTable().
 
98
     */
100
99
    ha_info->set_trx_read_write();
101
100
  }
102
101
}
103
102
 
104
103
 
105
 
/**
106
 
  Return the default storage engine StorageEngine for thread
107
 
 
108
 
  @param ha_default_storage_engine(session)
109
 
  @param session         current thread
110
 
 
111
 
  @return
112
 
    pointer to StorageEngine
113
 
*/
114
 
StorageEngine *ha_default_storage_engine(Session *session)
115
 
{
116
 
  if (session->variables.storage_engine)
117
 
    return session->variables.storage_engine;
118
 
  return global_system_variables.storage_engine;
119
 
}
120
 
 
121
 
 
122
 
/**
123
 
  Return the storage engine StorageEngine for the supplied name
124
 
 
125
 
  @param session         current thread
126
 
  @param name        name of storage engine
127
 
 
128
 
  @return
129
 
    pointer to storage engine plugin handle
130
 
*/
131
 
StorageEngine *ha_resolve_by_name(Session *session, std::string find_str)
132
 
{
 
104
 
 
105
int plugin::StorageEngine::renameTableImplementation(Session *,
 
106
                                                     const char *from,
 
107
                                                     const char *to)
 
108
{
 
109
  int error= 0;
 
110
  for (const char **ext= bas_ext(); *ext ; ext++)
 
111
  {
 
112
    if (rename_file_ext(from, to, *ext))
 
113
    {
 
114
      if ((error=my_errno) != ENOENT)
 
115
        break;
 
116
      error= 0;
 
117
    }
 
118
  }
 
119
  return error;
 
120
}
 
121
 
 
122
 
 
123
/**
 
124
  Delete all files with extension from bas_ext().
 
125
 
 
126
  @param name           Base name of table
 
127
 
 
128
  @note
 
129
    We assume that the handler may return more extensions than
 
130
    was actually used for the file.
 
131
 
 
132
  @retval
 
133
    0   If we successfully deleted at least one file from base_ext and
 
134
    didn't get any other errors than ENOENT
 
135
  @retval
 
136
    !0  Error
 
137
*/
 
138
int plugin::StorageEngine::deleteTableImplementation(Session *,
 
139
                                                     const string table_path)
 
140
{
 
141
  int error= 0;
 
142
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
 
143
  char buff[FN_REFLEN];
 
144
 
 
145
  for (const char **ext=bas_ext(); *ext ; ext++)
 
146
  {
 
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)))
 
150
    {
 
151
      if ((error= my_errno) != ENOENT)
 
152
        break;
 
153
    }
 
154
    else
 
155
      enoent_or_zero= 0;                        // No error for ENOENT
 
156
    error= enoent_or_zero;
 
157
  }
 
158
  return error;
 
159
}
 
160
 
 
161
const char *plugin::StorageEngine::checkLowercaseNames(const char *path,
 
162
                                                       char *tmp_path)
 
163
{
 
164
  if (flags.test(HTON_BIT_FILE_BASED))
 
165
    return path;
 
166
 
 
167
  /* Ensure that table handler get path in lower case */
 
168
  if (tmp_path != path)
 
169
    strcpy(tmp_path, path);
 
170
 
 
171
  /*
 
172
    we only should turn into lowercase database/table part
 
173
    so start the process after homedirectory
 
174
  */
 
175
  if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
 
176
    my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
 
177
  else
 
178
    my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
 
179
 
 
180
  return tmp_path;
 
181
}
 
182
 
 
183
 
 
184
bool plugin::StorageEngine::addPlugin(plugin::StorageEngine *engine)
 
185
{
 
186
  if (all_engines.add(engine))
 
187
  {
 
188
    errmsg_printf(ERRMSG_LVL_ERROR,
 
189
                  _("Couldn't add StorageEngine"));
 
190
    return true;
 
191
  }
 
192
  return false;
 
193
}
 
194
 
 
195
void plugin::StorageEngine::removePlugin(plugin::StorageEngine *engine)
 
196
{
 
197
  all_engines.remove(engine);
 
198
}
 
199
 
 
200
plugin::StorageEngine *plugin::StorageEngine::findByName(Session *session,
 
201
                                                         string find_str)
 
202
{
 
203
  
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);
138
209
 
139
 
  StorageEngine *engine= all_engines.find(find_str);
 
210
  plugin::StorageEngine *engine= all_engines.find(find_str);
140
211
 
141
212
  if (engine && engine->is_user_selectable())
142
213
    return engine;
144
215
  return NULL;
145
216
}
146
217
 
147
 
 
148
 
handler *get_new_handler(TableShare *share, MEM_ROOT *alloc,
149
 
                         StorageEngine *engine)
150
 
{
151
 
  handler *file;
152
 
 
153
 
  if (engine && engine->is_enabled())
154
 
  {
155
 
    if ((file= engine->create(share, alloc)))
156
 
      file->init();
157
 
    return(file);
158
 
  }
159
 
  /*
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.
163
 
  */
164
 
  return(get_new_handler(share, alloc, ha_default_storage_engine(current_session)));
165
 
}
166
 
 
167
218
class StorageEngineCloseConnection
168
 
  : public unary_function<StorageEngine *, void>
 
219
  : public unary_function<plugin::StorageEngine *, void>
169
220
{
170
221
  Session *session;
171
222
public:
186
237
  @note
187
238
    don't bother to rollback here, it's done already
188
239
*/
189
 
void ha_close_connection(Session* session)
 
240
void plugin::StorageEngine::closeConnection(Session* session)
190
241
{
191
242
  for_each(all_engines.begin(), all_engines.end(),
192
243
           StorageEngineCloseConnection(session));
193
244
}
194
245
 
195
 
void ha_drop_database(char* path)
 
246
void plugin::StorageEngine::dropDatabase(char* path)
196
247
{
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));
199
250
}
200
251
 
201
 
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
 
252
int plugin::StorageEngine::commitOrRollbackByXID(XID *xid, bool commit)
202
253
{
203
254
  vector<int> results;
204
255
  
205
256
  if (commit)
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));
208
259
  else
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));
211
262
 
212
263
  if (find_if(results.begin(), results.end(), bind2nd(equal_to<int>(),0))
213
264
         == results.end())
215
266
  return 0;
216
267
}
217
268
 
218
 
 
219
269
/**
220
270
  @details
221
271
  This function should be called when MySQL sends rows of a SELECT result set
234
284
  @return
235
285
    always 0
236
286
*/
237
 
int ha_release_temporary_latches(Session *session)
 
287
int plugin::StorageEngine::releaseTemporaryLatches(Session *session)
238
288
{
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));
241
291
  return 0;
242
292
}
243
293
 
244
 
 
245
 
bool ha_flush_logs(StorageEngine *engine)
 
294
bool plugin::StorageEngine::flushLogs(plugin::StorageEngine *engine)
246
295
{
247
296
  if (engine == NULL)
248
297
  {
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())
252
301
      return true;
253
302
  }
276
325
    in this case commit_list==0, tc_heuristic_recover == 0
277
326
    there should be no prepared transactions in this case.
278
327
*/
279
 
class XARecover : unary_function<StorageEngine *, void>
 
328
class XARecover : unary_function<plugin::StorageEngine *, void>
280
329
{
281
330
  int trans_len, found_foreign_xids, found_my_xids;
282
331
  bool result;
345
394
      }
346
395
    }
347
396
  }
348
 
 
349
397
};
350
398
 
351
 
int ha_recover(HASH *commit_list)
 
399
int plugin::StorageEngine::recover(HASH *commit_list)
352
400
{
353
401
  XID *trans_list= NULL;
354
402
  int trans_len= 0;
414
462
  return(0);
415
463
}
416
464
 
417
 
int ha_start_consistent_snapshot(Session *session)
 
465
int plugin::StorageEngine::startConsistentSnapshot(Session *session)
418
466
{
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),
 
469
                   session));
421
470
  return 0;
422
471
}
423
472
 
 
473
class StorageEngineGetTableProto: public unary_function<plugin::StorageEngine *,bool>
 
474
{
 
475
  const char* path;
 
476
  message::Table *table_proto;
 
477
  int *err;
 
478
public:
 
479
  StorageEngineGetTableProto(const char* path_arg,
 
480
                             message::Table *table_proto_arg,
 
481
                             int *err_arg)
 
482
  :path(path_arg), table_proto(table_proto_arg), err(err_arg) {}
 
483
 
 
484
  result_type operator() (argument_type engine)
 
485
  {
 
486
    int ret= engine->getTableProtoImplementation(path, table_proto);
 
487
 
 
488
    if (ret != ENOENT)
 
489
      *err= ret;
 
490
 
 
491
    return *err == EEXIST;
 
492
  }
 
493
};
 
494
 
424
495
static int drizzle_read_table_proto(const char* path, message::Table* table)
425
496
{
426
497
  int fd= open(path, O_RDONLY);
443
514
  return 0;
444
515
}
445
516
 
446
 
class StorageEngineGetTableProto: public unary_function<StorageEngine *,bool>
447
 
{
448
 
  const char* path;
449
 
  message::Table *table_proto;
450
 
  int *err;
451
 
public:
452
 
  StorageEngineGetTableProto(const char* path_arg,
453
 
                             message::Table *table_proto_arg,
454
 
                             int *err_arg)
455
 
  :path(path_arg), table_proto(table_proto_arg), err(err_arg) {}
456
 
 
457
 
  result_type operator() (argument_type engine)
458
 
  {
459
 
    int ret= engine->getTableProtoImplementation(path, table_proto);
460
 
 
461
 
    if (ret != ENOENT)
462
 
      *err= ret;
463
 
 
464
 
    return *err == EEXIST;
465
 
  }
466
 
};
467
 
 
468
517
/**
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
472
521
*/
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)
475
524
{
476
525
  int err= ENOENT;
477
526
 
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())
504
553
  return err;
505
554
}
506
555
 
507
 
 
508
 
int StorageEngine::renameTableImplementation(Session *, const char *from, const char *to)
509
 
{
510
 
  int error= 0;
511
 
  for (const char **ext= bas_ext(); *ext ; ext++)
512
 
  {
513
 
    if (rename_file_ext(from, to, *ext))
514
 
    {
515
 
      if ((error=my_errno) != ENOENT)
516
 
        break;
517
 
      error= 0;
518
 
    }
519
 
  }
520
 
  return error;
521
 
}
522
 
 
523
 
 
524
 
/**
525
 
  Delete all files with extension from bas_ext().
526
 
 
527
 
  @param name           Base name of table
528
 
 
529
 
  @note
530
 
    We assume that the handler may return more extensions than
531
 
    was actually used for the file.
532
 
 
533
 
  @retval
534
 
    0   If we successfully deleted at least one file from base_ext and
535
 
    didn't get any other errors than ENOENT
536
 
  @retval
537
 
    !0  Error
538
 
*/
539
 
int StorageEngine::deleteTableImplementation(Session *, const std::string table_path)
540
 
{
541
 
  int error= 0;
542
 
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
543
 
  char buff[FN_REFLEN];
544
 
 
545
 
  for (const char **ext=bas_ext(); *ext ; ext++)
546
 
  {
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)))
550
 
    {
551
 
      if ((error= my_errno) != ENOENT)
552
 
        break;
553
 
    }
554
 
    else
555
 
      enoent_or_zero= 0;                        // No error for ENOENT
556
 
    error= enoent_or_zero;
557
 
  }
558
 
  return error;
559
 
}
560
 
 
561
556
/**
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
590
585
 
591
586
 
592
587
class DeleteTableStorageEngine
593
 
  : public unary_function<StorageEngine *, void>
 
588
  : public unary_function<plugin::StorageEngine *, void>
594
589
{
595
590
  Session *session;
596
591
  const char *path;
621
616
      return;
622
617
 
623
618
    path= engine->checkLowercaseNames(path, tmp_path);
624
 
    const std::string table_path(path);
 
619
    const string table_path(path);
625
620
    int tmp_error= engine->deleteTable(session, table_path);
626
621
 
627
622
    if (tmp_error != ENOENT)
647
642
  }
648
643
};
649
644
 
 
645
 
650
646
/**
651
647
  This should return ENOENT if the file doesn't exists.
652
648
  The .frm file will be deleted only if we return 0 or ENOENT
653
649
*/
654
 
int ha_delete_table(Session *session, const char *path,
655
 
                    const char *db, const char *alias, bool generate_warning)
 
650
int plugin::StorageEngine::deleteTable(Session *session, const char *path,
 
651
                                       const char *db, const char *alias,
 
652
                                       bool generate_warning)
656
653
{
657
654
  TableShare dummy_share;
658
655
  Table dummy_table;
689
686
    dummy_share.table_name.length= strlen(alias);
690
687
    dummy_table.alias= alias;
691
688
 
692
 
 
693
689
    if(file != NULL)
694
690
    {
695
691
      file->change_table_ptr(&dummy_table, &dummy_share);
716
712
  return error;
717
713
}
718
714
 
719
 
/**
720
 
  Initiates table-file and calls appropriate database-creator.
721
 
 
722
 
  @retval
723
 
   0  ok
724
 
  @retval
725
 
   1  error
726
 
*/
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)
732
 
{
733
 
  int error= 1;
734
 
  Table table;
735
 
  TableShare share(db, 0, table_name, path);
736
 
  message::Table tmp_proto;
737
 
 
738
 
  if (table_proto)
739
 
  {
740
 
    if (parse_table_proto(session, *table_proto, &share))
741
 
      goto err;
742
 
  }
743
 
  else
744
 
  {
745
 
    table_proto= &tmp_proto;
746
 
    if (open_table_def(session, &share))
747
 
      goto err;
748
 
  }
749
 
 
750
 
  if (open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0,
751
 
                            &table, OTM_CREATE))
752
 
    goto err;
753
 
 
754
 
  if (update_create_info)
755
 
    table.updateCreateInfo(create_info, table_proto);
756
 
 
757
 
  error= share.storage_engine->createTable(session, path, &table,
758
 
                                           create_info, table_proto);
759
 
  table.closefrm(false);
760
 
  if (error)
761
 
  {
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);
765
 
  }
766
 
err:
767
 
  share.free_table_share();
768
 
  return(error != 0);
769
 
}
770
 
 
771
 
 
772
 
const string ha_resolve_storage_engine_name(const StorageEngine *engine)
773
 
{
774
 
  return engine == NULL ? string("UNKNOWN") : engine->getName();
775
 
}
776
 
 
777
 
const char *StorageEngine::checkLowercaseNames(const char *path, char *tmp_path)
778
 
{
779
 
  if (flags.test(HTON_BIT_FILE_BASED))
780
 
    return path;
781
 
 
782
 
  /* Ensure that table handler get path in lower case */
783
 
  if (tmp_path != path)
784
 
    strcpy(tmp_path, path);
785
 
 
786
 
  /*
787
 
    we only should turn into lowercase database/table part
788
 
    so start the process after homedirectory
789
 
  */
790
 
  if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
791
 
    my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
792
 
  else
793
 
    my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
794
 
 
795
 
  return tmp_path;
796
 
}
797
 
 
798
 
class DFETableNameIterator: public TableNameIteratorImplementation
 
715
class DFETableNameIterator: public plugin::TableNameIteratorImplementation
799
716
{
800
717
private:
801
718
  MY_DIR *dirp;
802
719
  uint32_t current_entry;
803
720
 
804
721
public:
805
 
  DFETableNameIterator(const std::string &database)
806
 
  : TableNameIteratorImplementation(database),
 
722
  DFETableNameIterator(const string &database)
 
723
  : plugin::TableNameIteratorImplementation(database),
807
724
    dirp(NULL),
808
725
    current_entry(-1)
809
726
    {};
810
727
 
811
728
  ~DFETableNameIterator();
812
729
 
813
 
  int next(std::string *name);
 
730
  int next(string *name);
814
731
 
815
732
};
816
733
 
880
797
  }
881
798
}
882
799
 
883
 
TableNameIterator::TableNameIterator(const std::string &db)
 
800
 
 
801
plugin::TableNameIterator::TableNameIterator(const string &db)
884
802
  : current_implementation(NULL), database(db)
885
803
{
886
804
  engine_iter= all_engines.begin();
887
805
  default_implementation= new DFETableNameIterator(database);
888
806
}
889
807
 
890
 
TableNameIterator::~TableNameIterator()
 
808
plugin::TableNameIterator::~TableNameIterator()
891
809
{
892
810
  delete current_implementation;
 
811
  if (current_implementation != default_implementation)
 
812
  {
 
813
    delete default_implementation;
 
814
  }
893
815
}
894
816
 
895
 
int TableNameIterator::next(std::string *name)
 
817
int plugin::TableNameIterator::next(string *name)
896
818
{
897
819
  int err= 0;
898
820
 
899
821
next:
900
822
  if (current_implementation == NULL)
901
823
  {
902
 
    while(current_implementation == NULL && engine_iter != all_engines.end())
 
824
    while(current_implementation == NULL &&
 
825
          (engine_iter != all_engines.end()))
903
826
    {
904
 
      StorageEngine *engine= *engine_iter;
 
827
      plugin::StorageEngine *engine= *engine_iter;
905
828
      current_implementation= engine->tableNameIterator(database);
906
829
      engine_iter++;
907
830
    }
908
831
 
909
 
    if (current_implementation == NULL && engine_iter == all_engines.end())
 
832
    if (current_implementation == NULL &&
 
833
        (engine_iter == all_engines.end()))
910
834
    {
911
835
      current_implementation= default_implementation;
912
836
    }
927
851
  return err;
928
852
}
929
853
 
 
854
 
 
855
} /* namespace drizzled */
 
856
 
 
857
 
 
858
 
 
859
handler *get_new_handler(TableShare *share, MEM_ROOT *alloc,
 
860
                         drizzled::plugin::StorageEngine *engine)
 
861
{
 
862
  handler *file;
 
863
 
 
864
  if (engine && engine->is_enabled())
 
865
  {
 
866
    if ((file= engine->create(share, alloc)))
 
867
      file->init();
 
868
    return(file);
 
869
  }
 
870
  /*
 
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.
 
874
  */
 
875
  return(get_new_handler(share, alloc, ha_default_storage_engine(current_session)));
 
876
}
 
877
 
 
878
 
 
879
/**
 
880
  Return the default storage engine plugin::StorageEngine for thread
 
881
 
 
882
  @param ha_default_storage_engine(session)
 
883
  @param session         current thread
 
884
 
 
885
  @return
 
886
    pointer to plugin::StorageEngine
 
887
*/
 
888
drizzled::plugin::StorageEngine *ha_default_storage_engine(Session *session)
 
889
{
 
890
  if (session->variables.storage_engine)
 
891
    return session->variables.storage_engine;
 
892
  return global_system_variables.storage_engine;
 
893
}
 
894
 
 
895
/**
 
896
  Initiates table-file and calls appropriate database-creator.
 
897
 
 
898
  @retval
 
899
   0  ok
 
900
  @retval
 
901
   1  error
 
902
*/
 
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)
 
908
{
 
909
  int error= 1;
 
910
  Table table;
 
911
  TableShare share(db, 0, table_name, path);
 
912
  drizzled::message::Table tmp_proto;
 
913
 
 
914
  if (table_proto)
 
915
  {
 
916
    if (parse_table_proto(session, *table_proto, &share))
 
917
      goto err;
 
918
  }
 
919
  else
 
920
  {
 
921
    table_proto= &tmp_proto;
 
922
    if (open_table_def(session, &share))
 
923
      goto err;
 
924
  }
 
925
 
 
926
  if (open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0,
 
927
                            &table, OTM_CREATE))
 
928
    goto err;
 
929
 
 
930
  if (update_create_info)
 
931
    table.updateCreateInfo(create_info, table_proto);
 
932
 
 
933
  error= share.storage_engine->createTable(session, path, &table,
 
934
                                           create_info, table_proto);
 
935
  table.closefrm(false);
 
936
  if (error)
 
937
  {
 
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);
 
941
  }
 
942
err:
 
943
  share.free_table_share();
 
944
  return(error != 0);
 
945
}
 
946