~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

Added code necessary for building plugins dynamically.
Merged in changes from lifeless to allow autoreconf to work.
Touching plugin.ini files now triggers a rebuid - so config/autorun.sh is no
longer required to be run after touching those.
Removed the duplicate plugin names - also removed the issue that getting them
different would silently fail weirdly later.

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>
53
55
{
54
56
 
55
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,
59
64
                                     size_t savepoint_offset_arg,
60
65
                                     bool support_2pc)
61
 
    : Plugin(name_arg),
 
66
    : Plugin(name_arg, "StorageEngine"),
62
67
      two_phase_commit(support_2pc),
63
68
      enabled(true),
64
69
      flags(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++)
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);
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 session->getDefaultStorageEngine();
 
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
 
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;
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
 
  NameMap<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
 
  Cursor **file;
594
 
  int *dt_error;
595
 
public:
596
 
  DeleteTableStorageEngine(Session *session_arg, const char *path_arg,
597
 
                           Cursor **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
 
    Cursor *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
 
  Cursor *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
708
      we use an internal error Cursor to intercept it and store the text
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
 
    ext= fn_rext(file->name);
783
 
 
784
 
    if (ext != NULL)
785
 
    {
786
 
      if (my_strcasecmp(system_charset_info, ext, ".dfe") ||
787
 
          is_prefix(file->name, TMP_FILE_PREFIX))
788
 
        continue;
789
 
      *ext=0;
790
 
    }
791
 
 
792
 
    file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
793
 
 
794
 
    uname[file_name_len]= '\0';
795
 
 
796
 
    if (wild && wild_compare(uname, wild, 0))
797
 
      continue;
798
 
 
799
 
    if (name)
800
 
      name->assign(uname);
801
 
 
802
 
    return 0;
803
 
  }
804
 
}
805
 
 
806
 
 
807
 
plugin::TableNameIterator::TableNameIterator(const string &db)
808
 
  : current_implementation(NULL), database(db)
809
 
{
810
 
  engine_iter= all_engines.begin();
811
 
  default_implementation= new DFETableNameIterator(database);
812
 
}
813
 
 
814
 
plugin::TableNameIterator::~TableNameIterator()
815
 
{
816
 
  delete current_implementation;
817
 
  if (current_implementation != default_implementation)
818
 
  {
819
 
    delete default_implementation;
820
 
  }
821
 
}
822
 
 
823
 
int plugin::TableNameIterator::next(string *name)
824
 
{
825
 
  int err= 0;
826
 
 
827
 
next:
828
 
  if (current_implementation == NULL)
829
 
  {
830
 
    while(current_implementation == NULL &&
831
 
          (engine_iter != all_engines.end()))
832
 
    {
833
 
      plugin::StorageEngine *engine= *engine_iter;
834
 
      current_implementation= engine->tableNameIterator(database);
835
 
      engine_iter++;
836
 
    }
837
 
 
838
 
    if (current_implementation == NULL &&
839
 
        (engine_iter == all_engines.end()))
840
 
    {
841
 
      current_implementation= default_implementation;
842
 
    }
843
 
  }
844
 
 
845
 
  err= current_implementation->next(name);
846
 
 
847
 
  if (err == -1)
848
 
  {
849
 
    if (current_implementation != default_implementation)
850
 
    {
851
 
      delete current_implementation;
852
 
      current_implementation= NULL;
853
 
      goto next;
854
 
    }
855
 
  }
856
 
 
857
 
  return err;
858
 
}
859
 
 
860
 
 
861
 
/**
862
 
  Return the default storage engine plugin::StorageEngine for thread
863
 
 
864
 
  defaultStorageEngine(session)
865
 
  @param session         current thread
866
 
 
867
 
  @return
868
 
    pointer to plugin::StorageEngine
869
 
*/
870
 
plugin::StorageEngine *plugin::StorageEngine::defaultStorageEngine(Session *session)
871
 
{
872
 
  if (session->variables.storage_engine)
873
 
    return session->variables.storage_engine;
874
 
  return global_system_variables.storage_engine;
875
 
}
876
 
 
877
746
/**
878
747
  Initiates table-file and calls appropriate database-creator.
879
748
 
882
751
  @retval
883
752
   1  error
884
753
*/
885
 
int plugin::StorageEngine::createTable(Session *session, const char *path,
 
754
int plugin::StorageEngine::createTable(Session& session, const char *path,
886
755
                                       const char *db, const char *table_name,
887
 
                                       HA_CREATE_INFO *create_info,
 
756
                                       HA_CREATE_INFO& create_info,
888
757
                                       bool update_create_info,
889
 
                                       message::Table *table_proto)
 
758
                                       drizzled::message::Table& table_proto, bool proto_used)
890
759
{
891
760
  int error= 1;
892
761
  Table table;
893
762
  TableShare share(db, 0, table_name, path);
894
763
  message::Table tmp_proto;
895
764
 
896
 
  if (table_proto)
 
765
  if (proto_used)
897
766
  {
898
 
    if (parse_table_proto(session, *table_proto, &share))
 
767
    if (parse_table_proto(session, table_proto, &share))
899
768
      goto err;
900
769
  }
901
770
  else
902
771
  {
903
 
    table_proto= &tmp_proto;
904
772
    if (open_table_def(session, &share))
905
773
      goto err;
906
774
  }
907
775
 
908
 
  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,
909
777
                            &table, OTM_CREATE))
910
778
    goto err;
911
779
 
912
780
  if (update_create_info)
913
 
    table.updateCreateInfo(create_info, table_proto);
914
 
 
915
 
  error= share.storage_engine->doCreateTable(session, path, &table,
916
 
                                           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
 
917
795
  table.closefrm(false);
918
796
  if (error)
919
797
  {
937
815
  return file;
938
816
}
939
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
}
 
897
 
940
898
 
941
899
} /* namespace drizzled */