~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

  • Committer: Stewart Smith
  • Date: 2010-03-15 04:42:26 UTC
  • mto: (1283.38.1)
  • mto: This revision was merged to the branch mainline in revision 1475.
  • Revision ID: stewart@flamingspork.com-20100315044226-q74o953r9h98brm4
basic embedded innodb DATA_DICTIONARY.INNODB_CONFIGURATION test

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <string>
26
26
#include <vector>
27
27
#include <set>
28
 
#include <fstream>
29
28
#include <algorithm>
30
29
#include <functional>
31
30
 
67
66
 
68
67
static EngineVector vector_of_engines;
69
68
static EngineVector vector_of_schema_engines;
70
 
static EngineVector vector_of_data_dictionary;
71
69
 
72
70
const std::string UNKNOWN_STRING("UNKNOWN");
73
71
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
75
73
static std::set<std::string> set_of_table_definition_ext;
76
74
 
77
75
StorageEngine::StorageEngine(const string name_arg,
78
 
                             const bitset<HTON_BIT_SIZE> &flags_arg) :
79
 
  Plugin(name_arg, "StorageEngine"),
80
 
  MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
81
 
  flags(flags_arg)
 
76
                             const bitset<HTON_BIT_SIZE> &flags_arg)
 
77
    : Plugin(name_arg, "StorageEngine"),
 
78
      MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
 
79
      flags(flags_arg)
82
80
{
 
81
  pthread_mutex_init(&proto_cache_mutex, NULL);
83
82
}
84
83
 
85
84
StorageEngine::~StorageEngine()
86
85
{
 
86
  pthread_mutex_destroy(&proto_cache_mutex);
87
87
}
88
88
 
89
89
void StorageEngine::setTransactionReadWrite(Session& session)
92
92
  statement_ctx.markModifiedNonTransData();
93
93
}
94
94
 
95
 
 
96
 
int StorageEngine::renameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
95
int StorageEngine::doRenameTable(Session *,
 
96
                                 const char *from,
 
97
                                 const char *to)
97
98
{
98
 
  setTransactionReadWrite(session);
99
 
 
100
 
  return doRenameTable(session, from, to);
 
99
  int error= 0;
 
100
  for (const char **ext= bas_ext(); *ext ; ext++)
 
101
  {
 
102
    if (rename_file_ext(from, to, *ext))
 
103
    {
 
104
      if ((error=errno) != ENOENT)
 
105
        break;
 
106
      error= 0;
 
107
    }
 
108
  }
 
109
  return error;
101
110
}
102
111
 
 
112
 
103
113
/**
104
114
  Delete all files with extension from bas_ext().
105
115
 
115
125
  @retval
116
126
    !0  Error
117
127
*/
118
 
int StorageEngine::doDropTable(Session&, TableIdentifier &identifier)
119
 
                               
 
128
int StorageEngine::doDropTable(Session&,
 
129
                               const string &table_path)
120
130
{
121
131
  int error= 0;
122
132
  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
124
134
 
125
135
  for (const char **ext= bas_ext(); *ext ; ext++)
126
136
  {
127
 
    internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
128
 
                        MY_UNPACK_FILENAME|MY_APPEND_EXT);
 
137
    internal::fn_format(buff, table_path.c_str(), "", *ext,
 
138
              MY_UNPACK_FILENAME|MY_APPEND_EXT);
129
139
    if (internal::my_delete_with_symlink(buff, MYF(0)))
130
140
    {
131
141
      if ((error= errno) != ENOENT)
132
 
        break;
 
142
        break;
133
143
    }
134
144
    else
135
 
    {
136
145
      enoent_or_zero= 0;                        // No error for ENOENT
137
 
    }
138
 
 
139
146
    error= enoent_or_zero;
140
147
  }
141
148
  return error;
142
149
}
143
150
 
 
151
const char *StorageEngine::checkLowercaseNames(const char *path,
 
152
                                                       char *tmp_path)
 
153
{
 
154
  if (flags.test(HTON_BIT_FILE_BASED))
 
155
    return path;
 
156
 
 
157
  /* Ensure that table Cursor get path in lower case */
 
158
  if (tmp_path != path)
 
159
    strcpy(tmp_path, path);
 
160
 
 
161
  /*
 
162
    we only should turn into lowercase database/table part
 
163
    so start the process after homedirectory
 
164
  */
 
165
  if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
 
166
    my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
 
167
  else
 
168
    my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
 
169
 
 
170
  return tmp_path;
 
171
}
 
172
 
 
173
 
144
174
bool StorageEngine::addPlugin(StorageEngine *engine)
145
175
{
146
176
 
155
185
  if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
156
186
    vector_of_schema_engines.push_back(engine);
157
187
 
158
 
  if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
159
 
    vector_of_data_dictionary.push_back(engine);
160
 
 
161
188
  return false;
162
189
}
163
190
 
167
194
  {
168
195
    vector_of_engines.clear();
169
196
    vector_of_schema_engines.clear();
170
 
    vector_of_data_dictionary.clear();
171
197
 
172
198
    shutdown_has_begun= true;
173
199
  }
176
202
class FindEngineByName
177
203
  : public unary_function<StorageEngine *, bool>
178
204
{
179
 
  const string &target;
180
 
 
 
205
  const string target;
181
206
public:
182
 
  explicit FindEngineByName(const string &target_arg) :
183
 
    target(target_arg)
184
 
  {
185
 
  }
 
207
  explicit FindEngineByName(const string target_arg)
 
208
    : target(target_arg)
 
209
  {}
186
210
  result_type operator() (argument_type engine)
187
211
  {
188
212
    string engine_name(engine->getName());
193
217
  }
194
218
};
195
219
 
196
 
StorageEngine *StorageEngine::findByName(const string &find_str)
 
220
StorageEngine *StorageEngine::findByName(string find_str)
197
221
{
198
 
  string search_string(find_str);
199
 
  transform(search_string.begin(), search_string.end(),
200
 
            search_string.begin(), ::tolower);
 
222
  transform(find_str.begin(), find_str.end(),
 
223
            find_str.begin(), ::tolower);
201
224
 
202
225
  
203
226
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
204
227
                                       vector_of_engines.end(),
205
 
                                       FindEngineByName(search_string));
 
228
                                       FindEngineByName(find_str));
206
229
  if (iter != vector_of_engines.end())
207
230
  {
208
231
    StorageEngine *engine= *iter;
213
236
  return NULL;
214
237
}
215
238
 
216
 
StorageEngine *StorageEngine::findByName(Session& session, const string &find_str)
 
239
StorageEngine *StorageEngine::findByName(Session& session,
 
240
                                                         string find_str)
217
241
{
218
 
  string search_string(find_str);
219
 
  transform(search_string.begin(), search_string.end(),
220
 
            search_string.begin(), ::tolower);
 
242
  
 
243
  transform(find_str.begin(), find_str.end(),
 
244
            find_str.begin(), ::tolower);
221
245
 
222
 
  if (search_string.compare("default") == 0)
 
246
  if (find_str.compare("default") == 0)
223
247
    return session.getDefaultStorageEngine();
224
248
 
225
249
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
226
250
                                       vector_of_engines.end(),
227
 
                                       FindEngineByName(search_string));
 
251
                                       FindEngineByName(find_str));
228
252
  if (iter != vector_of_engines.end())
229
253
  {
230
254
    StorageEngine *engine= *iter;
235
259
  return NULL;
236
260
}
237
261
 
238
 
class StorageEngineCloseConnection : public unary_function<StorageEngine *, void>
 
262
class StorageEngineCloseConnection
 
263
: public unary_function<StorageEngine *, void>
239
264
{
240
265
  Session *session;
241
266
public:
281
306
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
282
307
{
283
308
  Session& session;
284
 
  TableIdentifier &identifier;
285
 
  message::Table &table_message;
286
 
  int &err;
 
309
  const char* path;
 
310
  const char *db;
 
311
  const char *table_name;
 
312
  const bool is_tmp;
 
313
  message::Table *table_message;
 
314
  int *err;
287
315
 
288
316
public:
289
317
  StorageEngineGetTableDefinition(Session& session_arg,
290
 
                                  TableIdentifier &identifier_arg,
291
 
                                  message::Table &table_message_arg,
292
 
                                  int &err_arg) :
 
318
                                  const char* path_arg,
 
319
                                  const char *db_arg,
 
320
                                  const char *table_name_arg,
 
321
                                  const bool is_tmp_arg,
 
322
                                  message::Table *table_message_arg,
 
323
                                  int *err_arg) :
293
324
    session(session_arg), 
294
 
    identifier(identifier_arg),
 
325
    path(path_arg), 
 
326
    db(db_arg),
 
327
    table_name(table_name_arg),
 
328
    is_tmp(is_tmp_arg),
295
329
    table_message(table_message_arg), 
296
330
    err(err_arg) {}
297
331
 
298
332
  result_type operator() (argument_type engine)
299
333
  {
300
 
    int ret= engine->doGetTableDefinition(session, identifier, table_message);
 
334
    int ret= engine->doGetTableDefinition(session,
 
335
                                          path, 
 
336
                                          db,
 
337
                                          table_name,
 
338
                                          is_tmp,
 
339
                                          table_message);
301
340
 
302
341
    if (ret != ENOENT)
303
 
      err= ret;
304
 
 
305
 
    return err == EEXIST || err != ENOENT;
306
 
  }
307
 
};
308
 
 
309
 
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
310
 
{
311
 
  Session& session;
312
 
  TableIdentifier &identifier;
313
 
 
314
 
public:
315
 
  StorageEngineDoesTableExist(Session& session_arg, TableIdentifier &identifier_arg) :
316
 
    session(session_arg), 
317
 
    identifier(identifier_arg) 
318
 
  { }
319
 
 
320
 
  result_type operator() (argument_type engine)
321
 
  {
322
 
    return engine->doDoesTableExist(session, identifier);
 
342
      *err= ret;
 
343
 
 
344
    return *err == EEXIST || *err != ENOENT;
323
345
  }
324
346
};
325
347
 
326
348
/**
327
349
  Utility method which hides some of the details of getTableDefinition()
328
350
*/
329
 
bool plugin::StorageEngine::doesTableExist(Session &session,
 
351
bool plugin::StorageEngine::doesTableExist(Session& session,
330
352
                                           TableIdentifier &identifier,
331
353
                                           bool include_temporary_tables)
332
354
{
333
 
  if (include_temporary_tables)
334
 
  {
335
 
    if (session.doDoesTableExist(identifier))
336
 
      return true;
337
 
  }
338
 
 
339
 
  EngineVector::iterator iter=
340
 
    find_if(vector_of_data_dictionary.begin(), vector_of_data_dictionary.end(),
341
 
            StorageEngineDoesTableExist(session, identifier));
342
 
 
343
 
  if (iter == vector_of_data_dictionary.end())
344
 
  {
345
 
    return false;
346
 
  }
347
 
 
348
 
  return true;
349
 
}
350
 
 
351
 
bool plugin::StorageEngine::doDoesTableExist(Session&, TableIdentifier&)
352
 
{
353
 
  cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
354
 
  assert(0);
355
 
  return false;
 
355
  return (plugin::StorageEngine::getTableDefinition(session, identifier, NULL, include_temporary_tables) == EEXIST);
356
356
}
357
357
 
358
358
/**
362
362
*/
363
363
int StorageEngine::getTableDefinition(Session& session,
364
364
                                      TableIdentifier &identifier,
365
 
                                      message::Table &table_message,
 
365
                                      message::Table *table_message,
366
366
                                      bool include_temporary_tables)
367
367
{
 
368
  return getTableDefinition(session,
 
369
                            identifier.getPath(), identifier.getDBName(), identifier.getTableName(), identifier.isTmp(),
 
370
                            table_message, include_temporary_tables);
 
371
}
 
372
 
 
373
int StorageEngine::getTableDefinition(Session& session,
 
374
                                              const char* path,
 
375
                                              const char *schema_name,
 
376
                                              const char *table_name,
 
377
                                              const bool,
 
378
                                              message::Table *table_message,
 
379
                                              bool include_temporary_tables)
 
380
{
368
381
  int err= ENOENT;
369
382
 
370
383
  if (include_temporary_tables)
371
384
  {
372
 
    if (session.doGetTableDefinition(identifier, table_message) == EEXIST)
 
385
    if (session.doGetTableDefinition(path, schema_name, table_name, false, table_message) == EEXIST)
373
386
      return EEXIST;
374
387
  }
375
388
 
376
389
  EngineVector::iterator iter=
377
390
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
378
 
            StorageEngineGetTableDefinition(session, identifier, table_message, err));
 
391
            StorageEngineGetTableDefinition(session, path, NULL, NULL, true, table_message, &err));
379
392
 
380
393
  if (iter == vector_of_engines.end())
381
394
  {
433
446
 
434
447
  result_type operator() (argument_type engine)
435
448
  {
436
 
    bool success= engine->doDropTable(session, identifier);
 
449
    // @todo someday check that at least one engine said "true"
 
450
    std::string path(identifier.getPath());
 
451
    bool success= engine->doDropTable(session, path);
437
452
 
438
453
    if (success)
439
454
      success_count++;
450
465
  int error= 0;
451
466
  int error_proto;
452
467
  message::Table src_proto;
453
 
  StorageEngine *engine;
 
468
  StorageEngine* engine;
454
469
 
455
 
  error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
 
470
  error_proto= StorageEngine::getTableDefinition(session,
 
471
                                                 identifier,
 
472
                                                 &src_proto);
456
473
 
457
474
  if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
458
475
  {
459
 
    string error_message;
460
 
 
461
 
    error_message.append(identifier.getSQLPath());
462
 
    error_message.append(" : ");
463
 
    error_message.append(src_proto.InitializationErrorString());
464
 
 
465
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
466
 
 
 
476
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
 
477
             src_proto.InitializationErrorString().c_str());
467
478
    return ER_CORRUPT_TABLE_DEFINITION;
468
479
  }
469
480
 
471
482
 
472
483
  if (engine)
473
484
  {
474
 
    error= StorageEngine::dropTable(session, *engine, identifier);
 
485
    std::string path(identifier.getPath());
 
486
    engine->setTransactionReadWrite(session);
 
487
    error= engine->doDropTable(session, path);
 
488
 
 
489
    if (not error)
 
490
    {
 
491
      if (not engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
492
      {
 
493
        uint64_t counter; // @todo We need to refactor to check that.
 
494
 
 
495
        for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
496
                 DropTable(session, identifier, counter));
 
497
      }
 
498
    }
475
499
  }
476
500
 
477
501
  if (error_proto && error == 0)
480
504
  return error;
481
505
}
482
506
 
483
 
int StorageEngine::dropTable(Session& session,
484
 
                             StorageEngine &engine,
485
 
                             TableIdentifier &identifier)
486
 
{
487
 
  int error;
488
 
 
489
 
  engine.setTransactionReadWrite(session);
490
 
  error= engine.doDropTable(session, identifier);
491
 
 
492
 
  if (not error)
493
 
  {
494
 
    if (not engine.check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
495
 
    {
496
 
      uint64_t counter; // @todo We need to refactor to check that.
497
 
 
498
 
      for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
499
 
               DropTable(session, identifier, counter));
500
 
    }
501
 
  }
502
 
 
503
 
  return error;
504
 
}
505
 
 
506
507
/**
507
508
  Initiates table-file and calls appropriate database-creator.
508
509
 
510
511
   0  ok
511
512
  @retval
512
513
   1  error
 
514
 
 
515
   @todo refactor to remove goto
513
516
*/
514
 
int StorageEngine::createTable(Session &session,
 
517
int StorageEngine::createTable(Session& session,
515
518
                               TableIdentifier &identifier,
516
519
                               bool update_create_info,
517
520
                               message::Table& table_message)
518
521
{
519
522
  int error= 1;
520
523
  Table table;
521
 
  TableShare share(identifier.getDBName().c_str(), 0, identifier.getTableName().c_str(), identifier.getPath().c_str());
 
524
  TableShare share(identifier.getDBName(), 0, identifier.getTableName(), identifier.getPath());
522
525
  message::Table tmp_proto;
523
526
 
524
 
  if (parse_table_proto(session, table_message, &share) || open_table_from_share(&session, &share, "", 0, 0, &table))
525
 
  { 
526
 
    // @note Error occured, we should probably do a little more here.
527
 
  }
528
 
  else
529
 
  {
530
 
    if (update_create_info)
531
 
      table.updateCreateInfo(&table_message);
532
 
 
533
 
    /* Check for legal operations against the Engine using the proto (if used) */
534
 
    if (table_message.type() == message::Table::TEMPORARY &&
535
 
        share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
536
 
    {
537
 
      error= HA_ERR_UNSUPPORTED;
538
 
    }
539
 
    else if (table_message.type() != message::Table::TEMPORARY &&
540
 
             share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
541
 
    {
542
 
      error= HA_ERR_UNSUPPORTED;
543
 
    }
544
 
    else
545
 
    {
546
 
      bool do_create= true;
547
 
      if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
548
 
      {
549
 
        int protoerr= StorageEngine::writeDefinitionFromPath(identifier, table_message);
550
 
 
551
 
        if (protoerr)
552
 
        {
553
 
          error= protoerr;
554
 
          do_create= false;
555
 
        }
556
 
      }
557
 
 
558
 
      if (do_create)
559
 
      {
560
 
        share.storage_engine->setTransactionReadWrite(session);
561
 
 
562
 
        error= share.storage_engine->doCreateTable(&session,
563
 
                                                   table,
564
 
                                                   identifier,
565
 
                                                   table_message);
566
 
      }
567
 
    }
568
 
 
569
 
    if (error)
570
 
    {
571
 
      if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
572
 
        plugin::StorageEngine::deleteDefinitionFromPath(identifier);
573
 
 
574
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
575
 
    }
576
 
 
577
 
    table.closefrm(false);
578
 
  }
579
 
 
 
527
  if (parse_table_proto(session, table_message, &share))
 
528
    goto err;
 
529
 
 
530
  if (open_table_from_share(&session, &share, "", 0, 0,
 
531
                            &table))
 
532
    goto err;
 
533
 
 
534
  if (update_create_info)
 
535
    table.updateCreateInfo(&table_message);
 
536
 
 
537
  /* Check for legal operations against the Engine using the proto (if used) */
 
538
  if (table_message.type() == message::Table::TEMPORARY &&
 
539
      share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
 
540
  {
 
541
    error= HA_ERR_UNSUPPORTED;
 
542
    goto err2;
 
543
  }
 
544
  else if (table_message.type() != message::Table::TEMPORARY &&
 
545
           share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
 
546
  {
 
547
    error= HA_ERR_UNSUPPORTED;
 
548
    goto err2;
 
549
  }
 
550
 
 
551
  {
 
552
    char name_buff[FN_REFLEN];
 
553
    const char *table_name_arg;
 
554
 
 
555
    table_name_arg= share.storage_engine->checkLowercaseNames(identifier.getPath(), name_buff);
 
556
 
 
557
    if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
558
    {
 
559
      int protoerr= StorageEngine::writeDefinitionFromPath(identifier, table_message);
 
560
 
 
561
      if (protoerr)
 
562
      {
 
563
        error= protoerr;
 
564
        goto err2;
 
565
      }
 
566
    }
 
567
 
 
568
    share.storage_engine->setTransactionReadWrite(session);
 
569
 
 
570
    error= share.storage_engine->doCreateTable(&session,
 
571
                                               table_name_arg,
 
572
                                               table,
 
573
                                               table_message);
 
574
  }
 
575
 
 
576
err2:
 
577
  if (error)
 
578
  {
 
579
    if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
580
      plugin::StorageEngine::deleteDefinitionFromPath(identifier);
 
581
 
 
582
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
 
583
  }
 
584
 
 
585
  table.closefrm(false);
 
586
 
 
587
err:
580
588
  share.free_table_share();
581
589
  return(error != 0);
582
590
}
644
652
 
645
653
class StorageEngineGetSchemaDefinition: public unary_function<StorageEngine *, bool>
646
654
{
647
 
  std::string schema_name;
 
655
  const std::string &schema_name;
648
656
  message::Schema &schema_proto;
649
657
 
650
658
public:
651
 
  StorageEngineGetSchemaDefinition(const std::string schema_name_arg,
 
659
  StorageEngineGetSchemaDefinition(const std::string &schema_name_arg,
652
660
                                  message::Schema &schema_proto_arg) :
653
661
    schema_name(schema_name_arg),
654
662
    schema_proto(schema_proto_arg) 
655
 
  {
656
 
    transform(schema_name.begin(), schema_name.end(),
657
 
              schema_name.begin(), ::tolower);
658
 
  }
 
663
  { }
659
664
 
660
665
  result_type operator() (argument_type engine)
661
666
  {
666
671
/*
667
672
  Return value is "if parsed"
668
673
*/
669
 
bool StorageEngine::getSchemaDefinition(TableIdentifier &identifier, message::Schema &proto)
670
 
{
671
 
  return StorageEngine::getSchemaDefinition(identifier.getSchemaName(), proto);
672
 
}
673
 
 
674
674
bool StorageEngine::getSchemaDefinition(const std::string &schema_name, message::Schema &proto)
675
675
{
676
676
  proto.Clear();
694
694
  return StorageEngine::getSchemaDefinition(schema_name, proto);
695
695
}
696
696
 
697
 
bool StorageEngine::doesSchemaExist(TableIdentifier &identifier)
698
 
{
699
 
  message::Schema proto;
700
 
 
701
 
  return StorageEngine::getSchemaDefinition(identifier.getSchemaName(), proto);
702
 
}
703
 
 
704
697
 
705
698
const CHARSET_INFO *StorageEngine::getSchemaCollation(const std::string &schema_name)
706
699
{
828
821
 
829
822
void StorageEngine::getTableNames(const string &schema_name, TableNameList &set_of_names)
830
823
{
831
 
  string tmp_path;
 
824
  char tmp_path[FN_REFLEN];
832
825
 
833
 
  build_table_filename(tmp_path, schema_name.c_str(), "", false);
 
826
  build_table_filename(tmp_path, sizeof(tmp_path), schema_name.c_str(), "", false);
834
827
 
835
828
  CachedDirectory directory(tmp_path, set_of_table_definition_ext);
836
829
 
864
857
class DropTables: public unary_function<StorageEngine *, void>
865
858
{
866
859
  Session &session;
867
 
  TableIdentifierList &table_identifiers;
 
860
  TableNameList &set_of_names;
868
861
 
869
862
public:
870
863
 
871
 
  DropTables(Session &session_arg, TableIdentifierList &table_identifiers_arg) :
 
864
  DropTables(Session &session_arg, set<string>& of_names) :
872
865
    session(session_arg),
873
 
    table_identifiers(table_identifiers_arg)
 
866
    set_of_names(of_names)
874
867
  { }
875
868
 
876
869
  result_type operator() (argument_type engine)
877
870
  {
878
 
    for (TableIdentifierList::iterator iter= table_identifiers.begin();
879
 
         iter != table_identifiers.end();
 
871
 
 
872
    for (TableNameList::iterator iter= set_of_names.begin();
 
873
         iter != set_of_names.end();
880
874
         iter++)
881
875
    {
882
 
      int error= engine->doDropTable(session, const_cast<TableIdentifier&>(*iter));
 
876
      int error= engine->doDropTable(session, *iter);
883
877
 
884
878
      // On a return of zero we know we found and deleted the table. So we
885
879
      // remove it from our search.
886
880
      if (not error)
887
 
        table_identifiers.erase(iter);
 
881
        set_of_names.erase(iter);
888
882
    }
889
883
  }
890
884
};
897
891
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
898
892
{
899
893
  CachedDirectory dir(directory, set_of_table_definition_ext);
900
 
  TableIdentifierList table_identifiers;
 
894
  set<string> set_of_table_names;
901
895
 
902
896
  if (dir.fail())
903
897
  {
923
917
    path+= directory;
924
918
    path+= FN_LIBCHAR;
925
919
    path+= entry->filename;
926
 
    message::Table definition;
927
 
    if (StorageEngine::readTableFile(path, definition))
928
 
    {
929
 
      TableIdentifier identifier(definition.schema(), definition.name(), path);
930
 
      table_identifiers.push_back(identifier);
931
 
    }
 
920
    set_of_table_names.insert(path);
932
921
  }
933
922
 
934
923
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
935
 
           DropTables(session, table_identifiers));
 
924
           DropTables(session, set_of_table_names));
936
925
  
937
926
  /*
938
927
    Now we just clean up anything that might left over.
1123
1112
    break;
1124
1113
  case HA_ERR_NO_SUCH_TABLE:
1125
1114
    assert(table);
1126
 
    my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->getSchemaName(),
 
1115
    my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->db.str,
1127
1116
             table->s->table_name.str);
1128
1117
    return;
1129
1118
  case HA_ERR_RBR_LOGGING_FAILED:
1238
1227
 
1239
1228
int StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1240
1229
{
1241
 
  message::Table table_message;
1242
1230
  string src_path(src.getPath());
1243
1231
  string dest_path(dest.getPath());
1244
1232
 
1245
1233
  src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1246
1234
  dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1247
1235
 
1248
 
  bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1249
 
 
1250
 
  if (not was_read)
1251
 
  {
1252
 
    return ENOENT;
1253
 
  }
1254
 
 
1255
 
  dest.copyToTableMessage(table_message);
1256
 
 
1257
 
  int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1258
 
 
1259
 
  if (not error)
1260
 
  {
1261
 
    if (unlink(src_path.c_str()))
1262
 
      perror(src_path.c_str());
1263
 
  }
1264
 
 
1265
 
  return error;
 
1236
  return internal::my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1266
1237
}
1267
1238
 
1268
1239
int StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_message)
1269
1240
{
1270
 
  char definition_file_tmp[FN_REFLEN];
1271
1241
  string file_name(identifier.getPath());
1272
1242
 
1273
1243
  file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1274
1244
 
1275
 
  snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%s.%sXXXXXX", file_name.c_str(), DEFAULT_DEFINITION_FILE_EXT.c_str());
1276
 
 
1277
 
  int fd= mkstemp(definition_file_tmp);
 
1245
  int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, internal::my_umask);
1278
1246
 
1279
1247
  if (fd == -1)
1280
 
  {
1281
 
    perror(definition_file_tmp);
1282
1248
    return errno;
1283
 
  }
1284
1249
 
1285
1250
  google::protobuf::io::ZeroCopyOutputStream* output=
1286
1251
    new google::protobuf::io::FileOutputStream(fd);
1287
1252
 
1288
 
  if (not table_message.SerializeToZeroCopyStream(output))
 
1253
  if (table_message.SerializeToZeroCopyStream(output) == false)
1289
1254
  {
1290
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1291
 
             table_message.InitializationErrorString().c_str());
1292
1255
    delete output;
1293
 
 
1294
 
    if (close(fd) == -1)
1295
 
      perror(definition_file_tmp);
1296
 
 
1297
 
    if (unlink(definition_file_tmp) == -1)
1298
 
      perror(definition_file_tmp);
1299
 
 
1300
 
    return ER_CORRUPT_TABLE_DEFINITION;
 
1256
    close(fd);
 
1257
    return errno;
1301
1258
  }
1302
1259
 
1303
1260
  delete output;
1304
 
 
1305
 
  if (close(fd) == -1)
1306
 
  {
1307
 
    int error= errno;
1308
 
    perror(definition_file_tmp);
1309
 
 
1310
 
    if (unlink(definition_file_tmp))
1311
 
      perror(definition_file_tmp);
1312
 
 
1313
 
    return error;
1314
 
  }
1315
 
 
1316
 
  if (rename(definition_file_tmp, file_name.c_str()) == -1)
1317
 
  {
1318
 
    int error= errno;
1319
 
    perror(definition_file_tmp);
1320
 
 
1321
 
    if (unlink(definition_file_tmp))
1322
 
      perror(definition_file_tmp);
1323
 
 
1324
 
    return error;
1325
 
  }
1326
 
 
 
1261
  close(fd);
1327
1262
  return 0;
1328
1263
}
1329
1264
 
1360
1295
  return false;
1361
1296
}
1362
1297
 
1363
 
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1364
 
{
1365
 
  fstream input(path.c_str(), ios::in | ios::binary);
1366
 
 
1367
 
  if (input.good())
1368
 
  {
1369
 
    if (table_message.ParseFromIstream(&input))
1370
 
    {
1371
 
      return true;
1372
 
    }
1373
 
 
1374
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1375
 
             table_message.InitializationErrorString().c_str());
1376
 
  }
1377
 
  else
1378
 
  {
1379
 
    perror(path.c_str());
1380
 
  }
1381
 
 
1382
 
  return false;
1383
 
}
1384
 
 
1385
 
 
1386
 
 
1387
1298
} /* namespace plugin */
1388
1299
} /* namespace drizzled */