27
27
#include "drizzled/charset.h"
28
28
#include "drizzled/charset_info.h"
29
29
#include "drizzled/cursor.h"
30
#include "drizzled/data_home.h"
31
32
#include "drizzled/internal/my_sys.h"
33
#include "drizzled/transaction_services.h"
34
36
#include <sys/stat.h>
58
59
schema_cache_filled(false)
60
61
table_definition_ext= DEFAULT_FILE_EXTENSION;
61
pthread_rwlock_init(&schema_lock, NULL);
67
pthread_rwlock_destroy(&schema_lock);
70
69
void Schema::prime()
72
CachedDirectory directory(drizzle_data_home, CachedDirectory::DIRECTORY);
71
CachedDirectory directory(getDataHomeCatalog().file_string(), CachedDirectory::DIRECTORY);
73
72
CachedDirectory::Entries files= directory.getEntries();
75
pthread_rwlock_wrlock(&schema_lock);
77
76
for (CachedDirectory::Entries::iterator fileIter= files.begin();
78
77
fileIter != files.end(); fileIter++)
80
79
CachedDirectory::Entry *entry= *fileIter;
81
80
message::Schema schema_message;
83
if (readSchemaFile(entry->filename, schema_message))
82
if (not entry->filename.compare(GLOBAL_TEMPORARY_EXT))
85
SchemaIdentifier filename(entry->filename);
86
if (readSchemaFile(filename, schema_message))
85
88
SchemaIdentifier schema_identifier(schema_message.name());
87
90
pair<SchemaCache::iterator, bool> ret=
88
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
91
schema_cache.insert(make_pair(schema_identifier.getPath(), new message::Schema(schema_message)));
90
93
if (ret.second == false)
96
pthread_rwlock_unlock(&schema_lock);
99
void Schema::doGetSchemaIdentifiers(SchemaIdentifierList &set_of_names)
102
void Schema::doGetSchemaIdentifiers(SchemaIdentifiers &set_of_names)
101
if (not pthread_rwlock_rdlock(&schema_lock))
103
106
for (SchemaCache::iterator iter= schema_cache.begin();
104
107
iter != schema_cache.end();
107
set_of_names.push_back(SchemaIdentifier((*iter).second.name()));
110
set_of_names.push_back(SchemaIdentifier((*iter).second->name()));
109
pthread_rwlock_unlock(&schema_lock);
114
// If for some reason getting a lock should fail, we resort to disk
116
CachedDirectory directory(drizzle_data_home, CachedDirectory::DIRECTORY);
118
CachedDirectory::Entries files= directory.getEntries();
120
for (CachedDirectory::Entries::iterator fileIter= files.begin();
121
fileIter != files.end(); fileIter++)
123
CachedDirectory::Entry *entry= *fileIter;
124
set_of_names.push_back(entry->filename);
113
mutex.unlock_shared();
128
bool Schema::doGetSchemaDefinition(SchemaIdentifier &schema_identifier, message::Schema &schema_message)
116
bool Schema::doGetSchemaDefinition(const SchemaIdentifier &schema_identifier, message::SchemaPtr &schema_message)
130
if (not pthread_rwlock_rdlock(&schema_lock))
119
SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
121
if (iter != schema_cache.end())
132
SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
134
if (iter != schema_cache.end())
136
schema_message.CopyFrom(((*iter).second));
137
pthread_rwlock_unlock(&schema_lock);
140
pthread_rwlock_unlock(&schema_lock);
123
schema_message= (*iter).second;
124
mutex.unlock_shared();
127
mutex.unlock_shared();
145
// Fail to disk based means
146
return readSchemaFile(schema_identifier.getPath(), schema_message);
149
133
bool Schema::doCreateSchema(const drizzled::message::Schema &schema_message)
151
135
SchemaIdentifier schema_identifier(schema_message.name());
163
if (not pthread_rwlock_wrlock(&schema_lock))
165
pair<SchemaCache::iterator, bool> ret=
166
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
169
if (ret.second == false)
171
abort(); // If this has happened, something really bad is going down.
173
pthread_rwlock_unlock(&schema_lock);
149
pair<SchemaCache::iterator, bool> ret=
150
schema_cache.insert(make_pair(schema_identifier.getPath(), new message::Schema(schema_message)));
153
if (ret.second == false)
155
abort(); // If this has happened, something really bad is going down.
160
TransactionServices &transaction_services= TransactionServices::singleton();
161
transaction_services.allocateNewTransactionId();
179
bool Schema::doDropSchema(SchemaIdentifier &schema_identifier)
166
bool Schema::doDropSchema(const SchemaIdentifier &schema_identifier)
181
message::Schema schema_message;
168
message::SchemaPtr schema_message;
183
170
string schema_file(schema_identifier.getPath());
184
171
schema_file.append(1, FN_LIBCHAR);
212
if (not pthread_rwlock_wrlock(&schema_lock))
214
schema_cache.erase(schema_identifier.getPath());
215
pthread_rwlock_unlock(&schema_lock);
200
schema_cache.erase(schema_identifier.getPath());
203
TransactionServices &transaction_services= TransactionServices::singleton();
204
transaction_services.allocateNewTransactionId();
228
216
if (writeSchemaFile(schema_identifier, schema_message))
230
if (not pthread_rwlock_wrlock(&schema_lock))
232
220
schema_cache.erase(schema_identifier.getPath());
234
222
pair<SchemaCache::iterator, bool> ret=
235
schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
223
schema_cache.insert(make_pair(schema_identifier.getPath(), new message::Schema(schema_message)));
237
225
if (ret.second == false)
239
227
abort(); // If this has happened, something really bad is going down.
242
pthread_rwlock_unlock(&schema_lock);
246
abort(); // This would leave us out of sync, suck.
232
TransactionServices &transaction_services= TransactionServices::singleton();
233
transaction_services.allocateNewTransactionId();
256
242
@note we do the rename to make it crash safe.
258
bool Schema::writeSchemaFile(SchemaIdentifier &schema_identifier, const message::Schema &db)
244
bool Schema::writeSchemaFile(const SchemaIdentifier &schema_identifier, const message::Schema &db)
260
246
char schema_file_tmp[FN_REFLEN];
261
247
string schema_file(schema_identifier.getPath());
278
if (not db.SerializeToFileDescriptor(fd))
280
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
281
db.InitializationErrorString().c_str());
267
success= db.SerializeToFileDescriptor(fd);
276
my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), schema_file.c_str(),
277
db.InitializationErrorString().empty() ? "unknown" : db.InitializationErrorString().c_str());
283
279
if (close(fd) == -1)
284
280
perror(schema_file_tmp);
314
bool Schema::readSchemaFile(const std::string &schema_file_name, drizzled::message::Schema &schema_message)
310
bool Schema::readSchemaFile(const drizzled::SchemaIdentifier &schema_identifier, drizzled::message::Schema &schema)
316
string db_opt_path(schema_file_name);
312
string db_opt_path(schema_identifier.getPath());
319
315
Pass an empty file name, and the database options file name as extension
332
328
if (input.good())
334
if (schema_message.ParseFromIstream(&input))
330
if (schema.ParseFromIstream(&input))
339
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
340
schema_message.InitializationErrorString().c_str());
335
my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), db_opt_path.c_str(),
336
schema.InitializationErrorString().empty() ? "unknown" : schema.InitializationErrorString().c_str());
350
bool Schema::doCanCreateTable(drizzled::TableIdentifier &identifier)
346
bool Schema::doCanCreateTable(const drizzled::TableIdentifier &identifier)
352
if (static_cast<SchemaIdentifier&>(identifier) == TEMPORARY_IDENTIFIER)
349
// This should always be the same value as GLOBAL_TEMPORARY_EXT but be
352
// This needs to be done static in here for ordering reasons
353
static SchemaIdentifier TEMPORARY_IDENTIFIER(".TEMPORARY");
354
if (static_cast<const SchemaIdentifier&>(identifier) == TEMPORARY_IDENTIFIER)
360
362
void Schema::doGetTableIdentifiers(drizzled::CachedDirectory&,
361
drizzled::SchemaIdentifier&,
363
const drizzled::SchemaIdentifier&,
362
364
drizzled::TableIdentifiers&)