~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

  • Committer: Eric Day
  • Date: 2009-10-31 21:53:33 UTC
  • mfrom: (1200 staging)
  • mto: This revision was merged to the branch mainline in revision 1202.
  • Revision ID: eday@oddments.org-20091031215333-j94bjoanwmi68p6f
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include CSTDINT_H
23
23
#include <string>
24
24
#include <vector>
 
25
#include <set>
25
26
#include <algorithm>
26
27
#include <functional>
27
28
 
30
31
 
31
32
#include "mysys/my_dir.h"
32
33
#include "mysys/hash.h"
 
34
#include "mysys/cached_directory.h"
33
35
 
34
36
#include <drizzled/definitions.h>
35
37
#include <drizzled/base.h>
36
 
#include <drizzled/handler.h>
 
38
#include <drizzled/cursor.h>
37
39
#include <drizzled/plugin/storage_engine.h>
38
40
#include <drizzled/session.h>
39
41
#include <drizzled/error.h>
40
42
#include <drizzled/gettext.h>
41
 
#include <drizzled/registry.h>
 
43
#include <drizzled/name_map.h>
42
44
#include <drizzled/unireg.h>
43
45
#include <drizzled/data_home.h>
44
46
#include "drizzled/errmsg_print.h"
45
 
#include <drizzled/plugin/registry.h>
 
47
#include "drizzled/name_map.h"
46
48
#include "drizzled/xid.h"
47
49
 
48
50
#include <drizzled/table_proto.h>
52
54
namespace drizzled
53
55
{
54
56
 
55
 
Registry<plugin::StorageEngine *> all_engines;
 
57
NameMap<plugin::StorageEngine *> all_engines;
 
58
static std::vector<plugin::StorageEngine *> vector_of_engines;
 
59
static std::vector<plugin::StorageEngine *> vector_of_transactional_engines;
 
60
static std::set<std::string> set_of_table_definition_ext;
56
61
 
57
62
plugin::StorageEngine::StorageEngine(const string name_arg,
58
63
                                     const bitset<HTON_BIT_SIZE> &flags_arg,
73
78
    if (two_phase_commit)
74
79
        total_ha_2pc++;
75
80
  }
 
81
  pthread_mutex_init(&proto_cache_mutex, NULL);
76
82
}
77
83
 
78
84
 
79
85
plugin::StorageEngine::~StorageEngine()
80
86
{
81
87
  savepoint_alloc_size-= orig_savepoint_offset;
 
88
  pthread_mutex_destroy(&proto_cache_mutex);
82
89
}
83
90
 
84
 
void plugin::StorageEngine::setTransactionReadWrite(Session* session)
 
91
void plugin::StorageEngine::setTransactionReadWrite(Session& session)
85
92
{
86
 
  Ha_trx_info *ha_info= &session->ha_data[getSlot()].ha_info[0];
 
93
  Ha_trx_info *ha_info= &session.ha_data[getSlot()].ha_info[0];
87
94
  /*
88
95
    When a storage engine method is called, the transaction must
89
96
    have been started, unless it's a DDL call, for which the
95
102
  if (ha_info->is_started())
96
103
  {
97
104
    /*
98
 
     * table_share can be NULL in plugin::StorageEngine::deleteTable().
 
105
     * table_share can be NULL in plugin::StorageEngine::dropTable().
99
106
     */
100
107
    ha_info->set_trx_read_write();
101
108
  }
103
110
 
104
111
 
105
112
 
106
 
int plugin::StorageEngine::renameTableImplementation(Session *,
107
 
                                                     const char *from,
108
 
                                                     const char *to)
 
113
int plugin::StorageEngine::doRenameTable(Session *,
 
114
                                         const char *from,
 
115
                                         const char *to)
109
116
{
110
117
  int error= 0;
111
118
  for (const char **ext= bas_ext(); *ext ; ext++)
127
134
  @param name           Base name of table
128
135
 
129
136
  @note
130
 
    We assume that the handler may return more extensions than
 
137
    We assume that the Cursor may return more extensions than
131
138
    was actually used for the file.
132
139
 
133
140
  @retval
136
143
  @retval
137
144
    !0  Error
138
145
*/
139
 
int plugin::StorageEngine::deleteTableImplementation(Session *,
140
 
                                                     const string table_path)
 
146
int plugin::StorageEngine::doDropTable(Session&,
 
147
                                       const string table_path)
141
148
{
142
149
  int error= 0;
143
150
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
144
151
  char buff[FN_REFLEN];
145
152
 
146
 
  for (const char **ext=bas_ext(); *ext ; ext++)
 
153
  for (const char **ext= bas_ext(); *ext ; ext++)
147
154
  {
148
155
    fn_format(buff, table_path.c_str(), "", *ext,
149
156
              MY_UNPACK_FILENAME|MY_APPEND_EXT);
165
172
  if (flags.test(HTON_BIT_FILE_BASED))
166
173
    return path;
167
174
 
168
 
  /* Ensure that table handler get path in lower case */
 
175
  /* Ensure that table Cursor get path in lower case */
169
176
  if (tmp_path != path)
170
177
    strcpy(tmp_path, path);
171
178
 
190
197
                  _("Couldn't add StorageEngine"));
191
198
    return true;
192
199
  }
 
200
 
 
201
  vector_of_engines.push_back(engine);
 
202
 
 
203
  if (engine->check_flag(HTON_BIT_DOES_TRANSACTIONS))
 
204
    vector_of_transactional_engines.push_back(engine);
 
205
 
 
206
  if (engine->getTableDefinitionExt().length())
 
207
  {
 
208
    assert(engine->getTableDefinitionExt().length() == MAX_STORAGE_ENGINE_FILE_EXT);
 
209
    set_of_table_definition_ext.insert(engine->getTableDefinitionExt());
 
210
  }
 
211
 
193
212
  return false;
194
213
}
195
214
 
196
215
void plugin::StorageEngine::removePlugin(plugin::StorageEngine *engine)
197
216
{
198
217
  all_engines.remove(engine);
199
 
}
200
 
 
201
 
plugin::StorageEngine *plugin::StorageEngine::findByName(Session *session,
 
218
  vector_of_engines.clear();
 
219
  vector_of_transactional_engines.clear();
 
220
}
 
221
 
 
222
plugin::StorageEngine *plugin::StorageEngine::findByName(string find_str)
 
223
{
 
224
  transform(find_str.begin(), find_str.end(),
 
225
            find_str.begin(), ::tolower);
 
226
 
 
227
  plugin::StorageEngine *engine= all_engines.find(find_str);
 
228
 
 
229
  if (engine && engine->is_user_selectable())
 
230
    return engine;
 
231
 
 
232
  return NULL;
 
233
}
 
234
 
 
235
plugin::StorageEngine *plugin::StorageEngine::findByName(Session& session,
202
236
                                                         string find_str)
203
237
{
204
238
  
205
239
  transform(find_str.begin(), find_str.end(),
206
240
            find_str.begin(), ::tolower);
207
 
  string default_str("default");
208
 
  if (find_str == default_str)
209
 
    return ha_default_storage_engine(session);
 
241
 
 
242
  if (find_str.compare("default") == 0)
 
243
    return session.getDefaultStorageEngine();
210
244
 
211
245
  plugin::StorageEngine *engine= all_engines.find(find_str);
212
246
 
240
274
*/
241
275
void plugin::StorageEngine::closeConnection(Session* session)
242
276
{
243
 
  for_each(all_engines.begin(), all_engines.end(),
 
277
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
244
278
           StorageEngineCloseConnection(session));
245
279
}
246
280
 
247
281
void plugin::StorageEngine::dropDatabase(char* path)
248
282
{
249
 
  for_each(all_engines.begin(), all_engines.end(),
 
283
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
250
284
           bind2nd(mem_fun(&plugin::StorageEngine::drop_database),path));
251
285
}
252
286
 
273
307
  or the EOF mark to the client. It releases a possible adaptive hash index
274
308
  S-latch held by session in InnoDB and also releases a possible InnoDB query
275
309
  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
276
 
  keep them over several calls of the InnoDB handler interface when a join
 
310
  keep them over several calls of the InnoDB Cursor interface when a join
277
311
  is executed. But when we let the control to pass to the client they have
278
312
  to be released because if the application program uses mysql_use_result(),
279
313
  it may deadlock on the S-latch if the application on another connection
287
321
*/
288
322
int plugin::StorageEngine::releaseTemporaryLatches(Session *session)
289
323
{
290
 
  for_each(all_engines.begin(), all_engines.end(),
 
324
  for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
291
325
           bind2nd(mem_fun(&plugin::StorageEngine::release_temporary_latches),session));
292
326
  return 0;
293
327
}
439
473
 
440
474
 
441
475
  XARecover recover_func(trans_list, trans_len, commit_list, dry_run);
442
 
  for_each(all_engines.begin(), all_engines.end(), recover_func);
 
476
  for_each(vector_of_transactional_engines.begin(), vector_of_transactional_engines.end(),
 
477
           recover_func);
443
478
  free(trans_list);
444
479
 
445
480
  if (recover_func.getForeignXIDs())
465
500
 
466
501
int plugin::StorageEngine::startConsistentSnapshot(Session *session)
467
502
{
468
 
  for_each(all_engines.begin(), all_engines.end(),
 
503
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
469
504
           bind2nd(mem_fun(&plugin::StorageEngine::start_consistent_snapshot),
470
505
                   session));
471
506
  return 0;
472
507
}
473
508
 
474
 
class StorageEngineGetTableProto: public unary_function<plugin::StorageEngine *,bool>
 
509
class StorageEngineGetTableDefinition: public unary_function<plugin::StorageEngine *,bool>
475
510
{
 
511
  Session& session;
476
512
  const char* path;
 
513
  const char *db;
 
514
  const char *table_name;
 
515
  const bool is_tmp;
477
516
  message::Table *table_proto;
478
517
  int *err;
 
518
 
479
519
public:
480
 
  StorageEngineGetTableProto(const char* path_arg,
481
 
                             message::Table *table_proto_arg,
482
 
                             int *err_arg)
483
 
  :path(path_arg), table_proto(table_proto_arg), err(err_arg) {}
 
520
  StorageEngineGetTableDefinition(Session& session_arg,
 
521
                                  const char* path_arg,
 
522
                                  const char *db_arg,
 
523
                                  const char *table_name_arg,
 
524
                                  const bool is_tmp_arg,
 
525
                                  message::Table *table_proto_arg,
 
526
                                  int *err_arg) :
 
527
    session(session_arg), 
 
528
    path(path_arg), 
 
529
    db(db_arg),
 
530
    table_name(table_name_arg),
 
531
    is_tmp(is_tmp_arg),
 
532
    table_proto(table_proto_arg), 
 
533
    err(err_arg) {}
484
534
 
485
535
  result_type operator() (argument_type engine)
486
536
  {
487
 
    int ret= engine->getTableProtoImplementation(path, table_proto);
 
537
    int ret= engine->doGetTableDefinition(session,
 
538
                                          path, 
 
539
                                          db,
 
540
                                          table_name,
 
541
                                          is_tmp,
 
542
                                          table_proto);
488
543
 
489
544
    if (ret != ENOENT)
490
545
      *err= ret;
516
571
}
517
572
 
518
573
/**
519
 
  Call this function in order to give the handler the possiblity
 
574
  Call this function in order to give the Cursor the possiblity
520
575
  to ask engine if there are any new tables that should be written to disk
521
576
  or any dropped tables that need to be removed from disk
522
577
*/
523
 
int plugin::StorageEngine::getTableProto(const char* path,
524
 
                                         message::Table *table_proto)
 
578
int plugin::StorageEngine::getTableDefinition(Session& session,
 
579
                                              const char* path,
 
580
                                              const char *,
 
581
                                              const char *,
 
582
                                              const bool,
 
583
                                              message::Table *table_proto)
525
584
{
526
585
  int err= ENOENT;
527
586
 
528
 
  ::drizzled::Registry<plugin::StorageEngine *>::iterator iter=
529
 
    find_if(all_engines.begin(), all_engines.end(),
530
 
            StorageEngineGetTableProto(path, table_proto, &err));
531
 
  if (iter == all_engines.end())
 
587
  vector<plugin::StorageEngine *>::iterator iter=
 
588
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
589
            StorageEngineGetTableDefinition(session, path, NULL, NULL, true, table_proto, &err));
 
590
 
 
591
  if (iter == vector_of_engines.end())
532
592
  {
533
593
    string proto_path(path);
534
594
    string file_ext(".dfe");
585
645
}
586
646
 
587
647
 
588
 
class DeleteTableStorageEngine
589
 
  : public unary_function<plugin::StorageEngine *, void>
590
 
{
591
 
  Session *session;
592
 
  const char *path;
593
 
  handler **file;
594
 
  int *dt_error;
595
 
public:
596
 
  DeleteTableStorageEngine(Session *session_arg, const char *path_arg,
597
 
                           handler **file_arg, int *error_arg)
598
 
    : session(session_arg), path(path_arg), file(file_arg), dt_error(error_arg) {}
599
 
 
600
 
  result_type operator() (argument_type engine)
601
 
  {
602
 
    char tmp_path[FN_REFLEN];
603
 
    handler *tmp_file;
604
 
 
605
 
    if(*dt_error!=ENOENT) /* already deleted table */
606
 
      return;
607
 
 
608
 
    if (!engine)
609
 
      return;
610
 
 
611
 
    if (!engine->is_enabled())
612
 
      return;
613
 
 
614
 
    if ((tmp_file= engine->create(NULL, session->mem_root)))
615
 
      tmp_file->init();
616
 
    else
617
 
      return;
618
 
 
619
 
    path= engine->checkLowercaseNames(path, tmp_path);
620
 
    const string table_path(path);
621
 
    int tmp_error= engine->doDeleteTable(session, table_path);
622
 
 
623
 
    if (tmp_error != ENOENT)
624
 
    {
625
 
      if (tmp_error == 0)
626
 
      {
627
 
        if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
628
 
          delete_table_proto_file(path);
629
 
        else
630
 
          tmp_error= delete_table_proto_file(path);
631
 
      }
632
 
 
633
 
      *dt_error= tmp_error;
634
 
      if(*file)
635
 
        delete *file;
636
 
      *file= tmp_file;
637
 
      return;
638
 
    }
639
 
    else
640
 
      delete tmp_file;
641
 
 
642
 
    return;
643
 
  }
644
 
};
645
 
 
646
 
 
647
648
/**
648
649
  This should return ENOENT if the file doesn't exists.
649
650
  The .frm file will be deleted only if we return 0 or ENOENT
650
651
*/
651
 
int plugin::StorageEngine::deleteTable(Session *session, const char *path,
652
 
                                       const char *db, const char *alias,
653
 
                                       bool generate_warning)
 
652
int plugin::StorageEngine::dropTable(Session& session, const char *path,
 
653
                                     const char *db, const char *alias,
 
654
                                     bool generate_warning)
654
655
{
655
 
  TableShare dummy_share;
656
 
  Table dummy_table;
657
 
  memset(&dummy_table, 0, sizeof(dummy_table));
658
 
  memset(&dummy_share, 0, sizeof(dummy_share));
659
 
 
660
 
  dummy_table.s= &dummy_share;
661
 
 
662
 
  int error= ENOENT;
663
 
  handler *file= NULL;
664
 
 
665
 
  for_each(all_engines.begin(), all_engines.end(),
666
 
           DeleteTableStorageEngine(session, path, &file, &error));
667
 
 
668
 
  if (error == ENOENT) /* proto may be left behind */
669
 
    error= delete_table_proto_file(path);
 
656
  int error= 0;
 
657
  int error_proto;
 
658
  message::Table src_proto;
 
659
  plugin::StorageEngine* engine;
 
660
 
 
661
  error_proto= plugin::StorageEngine::getTableDefinition(session,
 
662
                                                         path, 
 
663
                                                         db,
 
664
                                                         alias,
 
665
                                                         true,
 
666
                                                         &src_proto);
 
667
 
 
668
  engine= plugin::StorageEngine::findByName(session,
 
669
                                            src_proto.engine().name());
 
670
 
 
671
  if (engine)
 
672
  {
 
673
    engine->setTransactionReadWrite(session);
 
674
    error= engine->doDropTable(session, path);
 
675
  }
 
676
 
 
677
  if (error != ENOENT)
 
678
  {
 
679
    if (error == 0)
 
680
    {
 
681
      if (engine && engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
682
        delete_table_proto_file(path);
 
683
      else
 
684
        error= delete_table_proto_file(path);
 
685
    }
 
686
  }
 
687
 
 
688
  if (error_proto && error == 0)
 
689
    return 0;
670
690
 
671
691
  if (error && generate_warning)
672
692
  {
 
693
    TableShare dummy_share;
 
694
    Table dummy_table;
 
695
    Cursor *file= NULL;
 
696
 
 
697
    if (engine)
 
698
    {
 
699
      if ((file= engine->create(NULL, session.mem_root)))
 
700
        file->init();
 
701
    }
 
702
    memset(&dummy_table, 0, sizeof(dummy_table));
 
703
    memset(&dummy_share, 0, sizeof(dummy_share));
 
704
    dummy_table.s= &dummy_share;
 
705
 
673
706
    /*
674
707
      Because file->print_error() use my_error() to generate the error message
675
 
      we use an internal error handler to intercept it and store the text
 
708
      we use an internal error Cursor to intercept it and store the text
676
709
      in a temporary buffer. Later the message will be presented to user
677
710
      as a warning.
678
711
    */
687
720
    dummy_share.table_name.length= strlen(alias);
688
721
    dummy_table.alias= alias;
689
722
 
690
 
    if(file != NULL)
 
723
    if (file != NULL)
691
724
    {
692
725
      file->change_table_ptr(&dummy_table, &dummy_share);
693
726
 
694
 
      session->push_internal_handler(&ha_delete_table_error_handler);
 
727
      session.push_internal_handler(&ha_delete_table_error_handler);
695
728
      file->print_error(error, 0);
696
729
 
697
 
      session->pop_internal_handler();
 
730
      session.pop_internal_handler();
698
731
    }
699
732
    else
700
733
      error= -1; /* General form of fail. maybe bad FRM */
703
736
      XXX: should we convert *all* errors to warnings here?
704
737
      What if the error is fatal?
705
738
    */
706
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
 
739
    push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
707
740
                 ha_delete_table_error_handler.buff);
708
741
  }
709
742
 
710
 
  if(file)
711
 
    delete file;
712
 
 
713
743
  return error;
714
744
}
715
745
 
716
 
class DFETableNameIterator: public plugin::TableNameIteratorImplementation
717
 
{
718
 
private:
719
 
  MY_DIR *dirp;
720
 
  uint32_t current_entry;
721
 
 
722
 
public:
723
 
  DFETableNameIterator(const string &database)
724
 
  : plugin::TableNameIteratorImplementation(database),
725
 
    dirp(NULL),
726
 
    current_entry(-1)
727
 
    {};
728
 
 
729
 
  ~DFETableNameIterator();
730
 
 
731
 
  int next(string *name);
732
 
 
733
 
};
734
 
 
735
 
DFETableNameIterator::~DFETableNameIterator()
736
 
{
737
 
  if (dirp)
738
 
    my_dirend(dirp);
739
 
}
740
 
 
741
 
int DFETableNameIterator::next(string *name)
742
 
{
743
 
  char uname[NAME_LEN + 1];
744
 
  FILEINFO *file;
745
 
  char *ext;
746
 
  uint32_t file_name_len;
747
 
  const char *wild= NULL;
748
 
 
749
 
  if (dirp == NULL)
750
 
  {
751
 
    bool dir= false;
752
 
    char path[FN_REFLEN];
753
 
 
754
 
    build_table_filename(path, sizeof(path), db.c_str(), "", false);
755
 
 
756
 
    dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0));
757
 
 
758
 
    if (dirp == NULL)
759
 
    {
760
 
      if (my_errno == ENOENT)
761
 
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db.c_str());
762
 
      else
763
 
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
764
 
      return(ENOENT);
765
 
    }
766
 
    current_entry= -1;
767
 
  }
768
 
 
769
 
  while(true)
770
 
  {
771
 
    current_entry++;
772
 
 
773
 
    if (current_entry == dirp->number_off_files)
774
 
    {
775
 
      my_dirend(dirp);
776
 
      dirp= NULL;
777
 
      return -1;
778
 
    }
779
 
 
780
 
    file= dirp->dir_entry + current_entry;
781
 
 
782
 
    if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),".dfe") ||
783
 
        is_prefix(file->name, TMP_FILE_PREFIX))
784
 
      continue;
785
 
    *ext=0;
786
 
 
787
 
    file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
788
 
 
789
 
    uname[file_name_len]= '\0';
790
 
 
791
 
    if (wild && wild_compare(uname, wild, 0))
792
 
      continue;
793
 
 
794
 
    if (name)
795
 
      name->assign(uname);
796
 
 
797
 
    return 0;
798
 
  }
799
 
}
800
 
 
801
 
 
802
 
plugin::TableNameIterator::TableNameIterator(const string &db)
803
 
  : current_implementation(NULL), database(db)
804
 
{
805
 
  engine_iter= all_engines.begin();
806
 
  default_implementation= new DFETableNameIterator(database);
807
 
}
808
 
 
809
 
plugin::TableNameIterator::~TableNameIterator()
810
 
{
811
 
  delete current_implementation;
812
 
  if (current_implementation != default_implementation)
813
 
  {
814
 
    delete default_implementation;
815
 
  }
816
 
}
817
 
 
818
 
int plugin::TableNameIterator::next(string *name)
819
 
{
820
 
  int err= 0;
821
 
 
822
 
next:
823
 
  if (current_implementation == NULL)
824
 
  {
825
 
    while(current_implementation == NULL &&
826
 
          (engine_iter != all_engines.end()))
827
 
    {
828
 
      plugin::StorageEngine *engine= *engine_iter;
829
 
      current_implementation= engine->tableNameIterator(database);
830
 
      engine_iter++;
831
 
    }
832
 
 
833
 
    if (current_implementation == NULL &&
834
 
        (engine_iter == all_engines.end()))
835
 
    {
836
 
      current_implementation= default_implementation;
837
 
    }
838
 
  }
839
 
 
840
 
  err= current_implementation->next(name);
841
 
 
842
 
  if (err == -1)
843
 
  {
844
 
    if (current_implementation != default_implementation)
845
 
    {
846
 
      delete current_implementation;
847
 
      current_implementation= NULL;
848
 
      goto next;
849
 
    }
850
 
  }
851
 
 
852
 
  return err;
853
 
}
854
 
 
855
 
 
856
746
/**
857
747
  Initiates table-file and calls appropriate database-creator.
858
748
 
861
751
  @retval
862
752
   1  error
863
753
*/
864
 
int plugin::StorageEngine::createTable(Session *session, const char *path,
 
754
int plugin::StorageEngine::createTable(Session& session, const char *path,
865
755
                                       const char *db, const char *table_name,
866
 
                                       HA_CREATE_INFO *create_info,
 
756
                                       HA_CREATE_INFO& create_info,
867
757
                                       bool update_create_info,
868
 
                                       drizzled::message::Table *table_proto)
 
758
                                       drizzled::message::Table& table_proto, bool proto_used)
869
759
{
870
760
  int error= 1;
871
761
  Table table;
872
762
  TableShare share(db, 0, table_name, path);
873
 
  drizzled::message::Table tmp_proto;
 
763
  message::Table tmp_proto;
874
764
 
875
 
  if (table_proto)
 
765
  if (proto_used)
876
766
  {
877
 
    if (parse_table_proto(session, *table_proto, &share))
 
767
    if (parse_table_proto(session, table_proto, &share))
878
768
      goto err;
879
769
  }
880
770
  else
881
771
  {
882
 
    table_proto= &tmp_proto;
883
772
    if (open_table_def(session, &share))
884
773
      goto err;
885
774
  }
886
775
 
887
 
  if (open_table_from_share(session, &share, "", 0, (uint32_t) READ_ALL, 0,
 
776
  if (open_table_from_share(&session, &share, "", 0, (uint32_t) READ_ALL, 0,
888
777
                            &table, OTM_CREATE))
889
778
    goto err;
890
779
 
891
780
  if (update_create_info)
892
 
    table.updateCreateInfo(create_info, table_proto);
893
 
 
894
 
  error= share.storage_engine->doCreateTable(session, path, &table,
895
 
                                           create_info, table_proto);
 
781
    table.updateCreateInfo(&create_info, &table_proto);
 
782
 
 
783
  {
 
784
    char name_buff[FN_REFLEN];
 
785
    const char *table_name_arg;
 
786
 
 
787
    table_name_arg= share.storage_engine->checkLowercaseNames(path, name_buff);
 
788
 
 
789
    share.storage_engine->setTransactionReadWrite(session);
 
790
 
 
791
    error= share.storage_engine->doCreateTable(&session, table_name_arg, table,
 
792
                                               create_info, table_proto);
 
793
  }
 
794
 
896
795
  table.closefrm(false);
897
796
  if (error)
898
797
  {
905
804
  return(error != 0);
906
805
}
907
806
 
 
807
Cursor *plugin::StorageEngine::getCursor(TableShare *share, MEM_ROOT *alloc)
 
808
{
 
809
  Cursor *file;
 
810
 
 
811
  assert(enabled);
 
812
 
 
813
  if ((file= create(share, alloc)))
 
814
    file->init();
 
815
  return file;
 
816
}
 
817
 
 
818
/**
 
819
  TODO -> Remove this to force all engines to implement their own file. Solves the "we only looked at dfe" problem.
 
820
*/
 
821
void plugin::StorageEngine::doGetTableNames(CachedDirectory &directory, string&, set<string>& set_of_names)
 
822
{
 
823
  CachedDirectory::Entries entries= directory.getEntries();
 
824
 
 
825
  for (CachedDirectory::Entries::iterator entry_iter= entries.begin(); 
 
826
       entry_iter != entries.end(); ++entry_iter)
 
827
  {
 
828
    CachedDirectory::Entry *entry= *entry_iter;
 
829
    string *filename= &entry->filename;
 
830
 
 
831
    assert(filename->size());
 
832
 
 
833
    const char *ext= strchr(filename->c_str(), '.');
 
834
 
 
835
    if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_DEFINITION_FILE_EXT.c_str()) ||
 
836
        is_prefix(filename->c_str(), TMP_FILE_PREFIX))
 
837
    { }
 
838
    else
 
839
    {
 
840
      char uname[NAME_LEN + 1];
 
841
      uint32_t file_name_len;
 
842
 
 
843
      file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
 
844
      // TODO: Remove need for memory copy here
 
845
      uname[file_name_len - sizeof(".dfe") + 1]= '\0'; // Subtract ending, place NULL 
 
846
      set_of_names.insert(uname);
 
847
    }
 
848
  }
 
849
}
 
850
 
 
851
class AddTableName : 
 
852
  public unary_function<plugin::StorageEngine *, void>
 
853
{
 
854
  string db;
 
855
  CachedDirectory& directory;
 
856
  set<string>& set_of_names;
 
857
 
 
858
public:
 
859
 
 
860
  AddTableName(CachedDirectory& directory_arg, string& database_name, set<string>& of_names) :
 
861
    directory(directory_arg),
 
862
    set_of_names(of_names)
 
863
  {
 
864
    db= database_name;
 
865
  }
 
866
 
 
867
  result_type operator() (argument_type engine)
 
868
  {
 
869
    engine->doGetTableNames(directory, db, set_of_names);
 
870
  }
 
871
};
 
872
 
 
873
void plugin::StorageEngine::getTableNames(string& db, set<string>& set_of_names)
 
874
{
 
875
  char tmp_path[FN_REFLEN];
 
876
 
 
877
  build_table_filename(tmp_path, sizeof(tmp_path), db.c_str(), "", false);
 
878
 
 
879
  CachedDirectory directory(tmp_path, set_of_table_definition_ext);
 
880
 
 
881
  if (db.compare("information_schema"))
 
882
  {
 
883
    if (directory.fail())
 
884
    {
 
885
      my_errno= directory.getError();
 
886
      if (my_errno == ENOENT)
 
887
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db.c_str());
 
888
      else
 
889
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), my_errno);
 
890
      return;
 
891
    }
 
892
  }
 
893
 
 
894
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
895
           AddTableName(directory, db, set_of_names));
 
896
}
908
897
 
909
898
 
910
899
} /* namespace drizzled */
911
 
 
912
 
 
913
 
 
914
 
handler *get_new_handler(TableShare *share, MEM_ROOT *alloc,
915
 
                         drizzled::plugin::StorageEngine *engine)
916
 
{
917
 
  handler *file;
918
 
 
919
 
  if (engine && engine->is_enabled())
920
 
  {
921
 
    if ((file= engine->create(share, alloc)))
922
 
      file->init();
923
 
    return(file);
924
 
  }
925
 
  /*
926
 
    Try the default table type
927
 
    Here the call to current_session() is ok as we call this function a lot of
928
 
    times but we enter this branch very seldom.
929
 
  */
930
 
  return(get_new_handler(share, alloc, ha_default_storage_engine(current_session)));
931
 
}
932
 
 
933
 
 
934
 
/**
935
 
  Return the default storage engine plugin::StorageEngine for thread
936
 
 
937
 
  @param ha_default_storage_engine(session)
938
 
  @param session         current thread
939
 
 
940
 
  @return
941
 
    pointer to plugin::StorageEngine
942
 
*/
943
 
drizzled::plugin::StorageEngine *ha_default_storage_engine(Session *session)
944
 
{
945
 
  if (session->variables.storage_engine)
946
 
    return session->variables.storage_engine;
947
 
  return global_system_variables.storage_engine;
948
 
}