44
44
using namespace std;
45
45
using namespace drizzled;
47
static SchemaIdentifier TEMPORARY_IDENTIFIER("TEMPORARY");
49
47
#define MY_DB_OPT_FILE "db.opt"
50
48
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
53
51
drizzled::plugin::StorageEngine("schema",
54
52
HTON_ALTER_NOT_SUPPORTED |
53
HTON_HAS_DATA_DICTIONARY |
55
54
HTON_HAS_SCHEMA_DICTIONARY |
56
55
HTON_SKIP_STORE_LOCK |
57
56
HTON_TEMPORARY_NOT_SUPPORTED),
60
59
table_definition_ext= DEFAULT_FILE_EXTENSION;
61
60
pthread_rwlock_init(&schema_lock, NULL);
63
message::Schema schema_message;
65
schema_message.set_name("temporary_tables");
67
doCreateSchema(schema_message);
67
73
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);
70
124
void Schema::prime()
72
126
CachedDirectory directory(drizzle_data_home, CachedDirectory::DIRECTORY);
83
137
if (readSchemaFile(entry->filename, schema_message))
85
SchemaIdentifier schema_identifier(schema_message.name());
87
139
pair<SchemaCache::iterator, bool> ret=
88
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
140
schema_cache.insert(make_pair(schema_message.name(), schema_message));
90
142
if (ret.second == false)
92
144
abort(); // If this has happened, something really bad is going down.
121
173
fileIter != files.end(); fileIter++)
123
175
CachedDirectory::Entry *entry= *fileIter;
124
set_of_names.push_back(entry->filename);
176
set_of_names.insert(entry->filename);
128
bool Schema::doGetSchemaDefinition(SchemaIdentifier &schema_identifier, message::Schema &schema_message)
180
bool Schema::doGetSchemaDefinition(const std::string &schema_name, message::Schema &schema_message)
130
182
if (not pthread_rwlock_rdlock(&schema_lock))
132
SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
184
SchemaCache::iterator iter= schema_cache.find(schema_name);
134
185
if (iter != schema_cache.end())
136
187
schema_message.CopyFrom(((*iter).second));
145
196
// Fail to disk based means
146
return readSchemaFile(schema_identifier.getPath(), schema_message);
197
return readSchemaFile(schema_name, schema_message);
149
200
bool Schema::doCreateSchema(const drizzled::message::Schema &schema_message)
151
SchemaIdentifier schema_identifier(schema_message.name());
153
if (mkdir(schema_identifier.getPath().c_str(), 0777) == -1)
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)
156
if (not writeSchemaFile(schema_identifier, schema_message))
210
if (not writeSchemaFile(path.c_str(), schema_message))
158
rmdir(schema_identifier.getPath().c_str());
163
217
if (not pthread_rwlock_wrlock(&schema_lock))
165
219
pair<SchemaCache::iterator, bool> ret=
166
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
220
schema_cache.insert(make_pair(schema_message.name(), schema_message));
169
223
if (ret.second == false)
179
bool Schema::doDropSchema(SchemaIdentifier &schema_identifier)
233
bool Schema::doDropSchema(const std::string &schema_name)
181
236
message::Schema schema_message;
183
string schema_file(schema_identifier.getPath());
238
drizzled::build_table_filename(path, schema_name.c_str(), "", false);
239
path.erase(path.length()-1);
241
string schema_file(path);
184
242
schema_file.append(1, FN_LIBCHAR);
185
243
schema_file.append(MY_DB_OPT_FILE);
187
if (not doGetSchemaDefinition(schema_identifier, schema_message))
245
if (not doGetSchemaDefinition(schema_name, schema_message))
190
248
// No db.opt file, no love from us.
197
255
if (unlink(schema_file.c_str()))
199
256
perror(schema_file.c_str());
203
if (rmdir(schema_identifier.getPath().c_str()))
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());
258
if (rmdir(path.c_str()))
259
perror(path.c_str());
212
261
if (not pthread_rwlock_wrlock(&schema_lock))
214
schema_cache.erase(schema_identifier.getPath());
263
schema_cache.erase(schema_message.name());
215
264
pthread_rwlock_unlock(&schema_lock);
270
int Schema::doDropTable(Session&, TableIdentifier &identifier)
272
string path(identifier.getPath());
274
path.append(DEFAULT_FILE_EXTENSION);
276
return internal::my_delete(path.c_str(), MYF(0));
221
279
bool Schema::doAlterSchema(const drizzled::message::Schema &schema_message)
223
SchemaIdentifier schema_identifier(schema_message.name());
282
drizzled::build_table_filename(path, schema_message.name().c_str(), "", false);
283
path.erase(path.length()-1);
225
if (access(schema_identifier.getPath().c_str(), F_OK))
285
if (access(path.c_str(), F_OK))
228
if (writeSchemaFile(schema_identifier, schema_message))
288
if (writeSchemaFile(path.c_str(), schema_message))
230
290
if (not pthread_rwlock_wrlock(&schema_lock))
232
schema_cache.erase(schema_identifier.getPath());
292
schema_cache.erase(schema_message.name());
234
294
pair<SchemaCache::iterator, bool> ret=
235
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
295
schema_cache.insert(make_pair(schema_message.name(), schema_message));
237
297
if (ret.second == false)
256
316
@note we do the rename to make it crash safe.
258
bool Schema::writeSchemaFile(SchemaIdentifier &schema_identifier, const message::Schema &db)
318
bool Schema::writeSchemaFile(const char *path, const message::Schema &db)
260
320
char schema_file_tmp[FN_REFLEN];
261
string schema_file(schema_identifier.getPath());
321
string schema_file(path);
323
snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
264
325
schema_file.append(1, FN_LIBCHAR);
265
326
schema_file.append(MY_DB_OPT_FILE);
267
snprintf(schema_file_tmp, FN_REFLEN, "%sXXXXXX", schema_file.c_str());
269
328
int fd= mkstemp(schema_file_tmp);
273
perror(schema_file_tmp);
278
333
if (not db.SerializeToFileDescriptor(fd))
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);
336
unlink(schema_file_tmp);
302
341
if (rename(schema_file_tmp, schema_file.c_str()) == -1)
304
if (unlink(schema_file_tmp))
305
perror(schema_file_tmp);
314
bool Schema::readSchemaFile(const std::string &schema_file_name, drizzled::message::Schema &schema_message)
316
string db_opt_path(schema_file_name);
353
bool Schema::readTableFile(const std::string &path, message::Table &table_message)
355
fstream input(path.c_str(), ios::in | ios::binary);
359
if (table_message.ParseFromIstream(&input))
366
perror(path.c_str());
373
bool Schema::readSchemaFile(const std::string &schema_name, drizzled::message::Schema &schema_message)
319
378
Pass an empty file name, and the database options file name as extension
320
379
to avoid table name to file name encoding.
322
db_opt_path.append(1, FN_LIBCHAR);
381
build_table_filename(db_opt_path, schema_name.c_str(), "", false);
323
382
db_opt_path.append(MY_DB_OPT_FILE);
325
384
fstream input(db_opt_path.c_str(), ios::in | ios::binary);
360
void Schema::doGetTableIdentifiers(drizzled::CachedDirectory&,
361
drizzled::SchemaIdentifier&,
362
drizzled::TableIdentifiers&)
416
bool Schema::doDoesTableExist(Session&, TableIdentifier &identifier)
418
string proto_path(identifier.getPath());
419
proto_path.append(DEFAULT_FILE_EXTENSION);
421
if (access(proto_path.c_str(), F_OK))