44
44
using namespace std;
45
45
using namespace drizzled;
47
static SchemaIdentifier TEMPORARY_IDENTIFIER("TEMPORARY");
47
49
#define MY_DB_OPT_FILE "db.opt"
48
50
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
51
53
drizzled::plugin::StorageEngine("schema",
52
54
HTON_ALTER_NOT_SUPPORTED |
53
HTON_HAS_DATA_DICTIONARY |
54
55
HTON_HAS_SCHEMA_DICTIONARY |
55
56
HTON_SKIP_STORE_LOCK |
56
57
HTON_TEMPORARY_NOT_SUPPORTED),
59
60
table_definition_ext= DEFAULT_FILE_EXTENSION;
60
61
pthread_rwlock_init(&schema_lock, NULL);
63
message::Schema schema_message;
65
schema_message.set_name("temporary_tables");
67
doCreateSchema(schema_message);
73
67
pthread_rwlock_destroy(&schema_lock);
76
int Schema::doGetTableDefinition(Session &,
77
drizzled::TableIdentifier &identifier,
78
message::Table &table_proto)
80
string proto_path(identifier.getPath());
81
proto_path.append(DEFAULT_FILE_EXTENSION);
83
if (access(proto_path.c_str(), F_OK))
88
if (readTableFile(proto_path, table_proto))
94
void Schema::doGetTableNames(CachedDirectory &directory, string&, set<string>& set_of_names)
96
CachedDirectory::Entries entries= directory.getEntries();
98
for (CachedDirectory::Entries::iterator entry_iter= entries.begin();
99
entry_iter != entries.end(); ++entry_iter)
101
CachedDirectory::Entry *entry= *entry_iter;
102
const string *filename= &entry->filename;
104
assert(filename->size());
106
const char *ext= strchr(filename->c_str(), '.');
108
if (ext == NULL || my_strcasecmp(system_charset_info, ext, DEFAULT_FILE_EXTENSION) ||
109
(filename->compare(0, strlen(TMP_FILE_PREFIX), TMP_FILE_PREFIX) == 0))
113
char uname[NAME_LEN + 1];
114
uint32_t file_name_len;
116
file_name_len= filename_to_tablename(filename->c_str(), uname, sizeof(uname));
117
// TODO: Remove need for memory copy here
118
uname[file_name_len - sizeof(DEFAULT_FILE_EXTENSION) + 1]= '\0'; // Subtract ending, place NULL
119
set_of_names.insert(uname);
124
70
void Schema::prime()
126
72
CachedDirectory directory(data_home, CachedDirectory::DIRECTORY);
137
83
if (readSchemaFile(entry->filename, schema_message))
85
SchemaIdentifier schema_identifier(schema_message.name());
139
87
pair<SchemaCache::iterator, bool> ret=
140
schema_cache.insert(make_pair(schema_message.name(), schema_message));
88
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
142
90
if (ret.second == false)
144
92
abort(); // If this has happened, something really bad is going down.
173
121
fileIter != files.end(); fileIter++)
175
123
CachedDirectory::Entry *entry= *fileIter;
176
set_of_names.insert(entry->filename);
124
set_of_names.push_back(entry->filename);
180
bool Schema::doGetSchemaDefinition(const std::string &schema_name, message::Schema &schema_message)
128
bool Schema::doGetSchemaDefinition(SchemaIdentifier &schema_identifier, message::Schema &schema_message)
182
130
if (not pthread_rwlock_rdlock(&schema_lock))
184
SchemaCache::iterator iter= schema_cache.find(schema_name);
132
SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
185
134
if (iter != schema_cache.end())
187
136
schema_message.CopyFrom(((*iter).second));
196
145
// Fail to disk based means
197
return readSchemaFile(schema_name, schema_message);
146
return readSchemaFile(schema_identifier.getPath(), schema_message);
200
149
bool Schema::doCreateSchema(const drizzled::message::Schema &schema_message)
203
drizzled::build_table_filename(path, schema_message.name().c_str(), "", false);
205
path.erase(path.length()-1);
207
if (mkdir(path.c_str(), 0777) == -1)
151
SchemaIdentifier schema_identifier(schema_message.name());
153
if (mkdir(schema_identifier.getPath().c_str(), 0777) == -1)
210
if (not writeSchemaFile(path.c_str(), schema_message))
156
if (not writeSchemaFile(schema_identifier, schema_message))
158
rmdir(schema_identifier.getPath().c_str());
217
163
if (not pthread_rwlock_wrlock(&schema_lock))
219
165
pair<SchemaCache::iterator, bool> ret=
220
schema_cache.insert(make_pair(schema_message.name(), schema_message));
166
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
223
169
if (ret.second == false)
233
bool Schema::doDropSchema(const std::string &schema_name)
179
bool Schema::doDropSchema(SchemaIdentifier &schema_identifier)
236
181
message::Schema schema_message;
238
drizzled::build_table_filename(path, schema_name.c_str(), "", false);
239
path.erase(path.length()-1);
241
string schema_file(path);
183
string schema_file(schema_identifier.getPath());
242
184
schema_file.append(1, FN_LIBCHAR);
243
185
schema_file.append(MY_DB_OPT_FILE);
245
if (not doGetSchemaDefinition(schema_name, schema_message))
187
if (not doGetSchemaDefinition(schema_identifier, schema_message))
248
190
// No db.opt file, no love from us.
261
if (rmdir(path.c_str()))
203
if (rmdir(schema_identifier.getPath().c_str()))
263
perror(path.c_str());
264
CachedDirectory dir(path);
205
perror(schema_identifier.getPath().c_str());
206
//@todo If this happens, we want a report of it. For the moment I dump
207
//to stderr so I can catch it in Hudson.
208
CachedDirectory dir(schema_identifier.getPath());
268
212
if (not pthread_rwlock_wrlock(&schema_lock))
270
schema_cache.erase(schema_message.name());
214
schema_cache.erase(schema_identifier.getPath());
271
215
pthread_rwlock_unlock(&schema_lock);
277
int Schema::doDropTable(Session&, TableIdentifier &identifier)
279
string path(identifier.getPath());
281
path.append(DEFAULT_FILE_EXTENSION);
283
return internal::my_delete(path.c_str(), MYF(0));
286
221
bool Schema::doAlterSchema(const drizzled::message::Schema &schema_message)
289
drizzled::build_table_filename(path, schema_message.name().c_str(), "", false);
290
path.erase(path.length()-1);
223
SchemaIdentifier schema_identifier(schema_message.name());
292
if (access(path.c_str(), F_OK))
225
if (access(schema_identifier.getPath().c_str(), F_OK))
295
if (writeSchemaFile(path.c_str(), schema_message))
228
if (writeSchemaFile(schema_identifier, schema_message))
297
230
if (not pthread_rwlock_wrlock(&schema_lock))
299
schema_cache.erase(schema_message.name());
232
schema_cache.erase(schema_identifier.getPath());
301
234
pair<SchemaCache::iterator, bool> ret=
302
schema_cache.insert(make_pair(schema_message.name(), schema_message));
235
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
304
237
if (ret.second == false)
323
256
@note we do the rename to make it crash safe.
325
bool Schema::writeSchemaFile(const char *path, const message::Schema &db)
258
bool Schema::writeSchemaFile(SchemaIdentifier &schema_identifier, const message::Schema &db)
327
260
char schema_file_tmp[FN_REFLEN];
328
string schema_file(path);
261
string schema_file(schema_identifier.getPath());
330
snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
332
264
schema_file.append(1, FN_LIBCHAR);
333
265
schema_file.append(MY_DB_OPT_FILE);
267
snprintf(schema_file_tmp, FN_REFLEN, "%sXXXXXX", schema_file.c_str());
335
269
int fd= mkstemp(schema_file_tmp);
339
273
perror(schema_file_tmp);
343
278
if (not db.SerializeToFileDescriptor(fd))
345
cerr << "Couldn't write " << path << "\n";
280
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
281
db.InitializationErrorString().c_str());
284
perror(schema_file_tmp);
286
if (unlink(schema_file_tmp))
287
perror(schema_file_tmp);
294
perror(schema_file_tmp);
296
if (unlink(schema_file_tmp))
297
perror(schema_file_tmp);
351
302
if (rename(schema_file_tmp, schema_file.c_str()) == -1)
304
if (unlink(schema_file_tmp))
305
perror(schema_file_tmp);
363
bool Schema::readTableFile(const std::string &path, message::Table &table_message)
365
fstream input(path.c_str(), ios::in | ios::binary);
369
if (table_message.ParseFromIstream(&input))
376
perror(path.c_str());
383
bool Schema::readSchemaFile(const std::string &schema_name, drizzled::message::Schema &schema_message)
314
bool Schema::readSchemaFile(const std::string &schema_file_name, drizzled::message::Schema &schema_message)
316
string db_opt_path(schema_file_name);
388
319
Pass an empty file name, and the database options file name as extension
389
320
to avoid table name to file name encoding.
391
build_table_filename(db_opt_path, schema_name.c_str(), "", false);
322
db_opt_path.append(1, FN_LIBCHAR);
392
323
db_opt_path.append(MY_DB_OPT_FILE);
394
325
fstream input(db_opt_path.c_str(), ios::in | ios::binary);
416
bool Schema::doCanCreateTable(const drizzled::TableIdentifier &identifier)
418
if (not strcasecmp(identifier.getSchemaName().c_str(), "temporary"))
426
bool Schema::doDoesTableExist(Session&, TableIdentifier &identifier)
428
string proto_path(identifier.getPath());
429
proto_path.append(DEFAULT_FILE_EXTENSION);
431
if (access(proto_path.c_str(), F_OK))
350
bool Schema::doCanCreateTable(drizzled::TableIdentifier &identifier)
352
if (static_cast<SchemaIdentifier&>(identifier) == TEMPORARY_IDENTIFIER)