~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/schema_engine/schema.cc

  • Committer: Olaf van der Spek
  • Date: 2011-02-12 18:24:24 UTC
  • mto: (2167.1.2 build) (2172.1.4 build)
  • mto: This revision was merged to the branch mainline in revision 2168.
  • Revision ID: olafvdspek@gmail.com-20110212182424-kgnm9osi7qo97at2
casts

Show diffs side-by-side

added added

removed removed

Lines of Context:
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/pthread_globals.h>
 
33
 
 
34
#include <drizzled/execute.h>
30
35
 
31
36
#include "drizzled/internal/my_sys.h"
32
37
 
44
49
using namespace std;
45
50
using namespace drizzled;
46
51
 
47
 
static SchemaIdentifier TEMPORARY_IDENTIFIER("TEMPORARY");
48
52
 
49
53
#define MY_DB_OPT_FILE "db.opt"
50
54
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
58
62
  schema_cache_filled(false)
59
63
{
60
64
  table_definition_ext= DEFAULT_FILE_EXTENSION;
61
 
  pthread_rwlock_init(&schema_lock, NULL);
62
 
  prime();
63
65
}
64
66
 
65
67
Schema::~Schema()
66
68
{
67
 
  pthread_rwlock_destroy(&schema_lock);
68
69
}
69
70
 
70
71
void Schema::prime()
71
72
{
72
 
  CachedDirectory directory(drizzle_data_home, CachedDirectory::DIRECTORY);
 
73
  CachedDirectory directory(getDataHomeCatalog().file_string(), CachedDirectory::DIRECTORY);
73
74
  CachedDirectory::Entries files= directory.getEntries();
74
 
 
75
 
  pthread_rwlock_wrlock(&schema_lock);
 
75
  boost::unique_lock<boost::shared_mutex> scopedLock(mutex);
76
76
 
77
77
  for (CachedDirectory::Entries::iterator fileIter= files.begin();
78
78
       fileIter != files.end(); fileIter++)
80
80
    CachedDirectory::Entry *entry= *fileIter;
81
81
    message::Schema schema_message;
82
82
 
 
83
    if (not entry->filename.compare(GLOBAL_TEMPORARY_EXT))
 
84
      continue;
 
85
 
83
86
    if (readSchemaFile(entry->filename, schema_message))
84
87
    {
85
 
      SchemaIdentifier schema_identifier(schema_message.name());
 
88
      identifier::Schema schema_identifier(schema_message.name());
86
89
 
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)));
89
92
 
90
93
      if (ret.second == false)
91
 
     {
 
94
      {
92
95
        abort(); // If this has happened, something really bad is going down.
93
96
      }
94
97
    }
95
98
  }
96
 
  pthread_rwlock_unlock(&schema_lock);
97
 
}
98
 
 
99
 
void Schema::doGetSchemaIdentifiers(SchemaIdentifierList &set_of_names)
100
 
{
101
 
  if (not pthread_rwlock_rdlock(&schema_lock))
 
99
}
 
100
 
 
101
void Schema::startup(drizzled::Session &)
 
102
{
 
103
}
 
104
 
 
105
void Schema::doGetSchemaIdentifiers(identifier::Schema::vector &set_of_names)
 
106
{
 
107
  mutex.lock_shared();
102
108
  {
103
109
    for (SchemaCache::iterator iter= schema_cache.begin();
104
110
         iter != schema_cache.end();
105
111
         iter++)
106
112
    {
107
 
      set_of_names.push_back(SchemaIdentifier((*iter).second.name()));
 
113
      set_of_names.push_back(identifier::Schema((*iter).second->name()));
108
114
    }
109
 
    pthread_rwlock_unlock(&schema_lock);
110
 
 
111
 
    return;
112
 
  }
113
 
 
114
 
  // If for some reason getting a lock should fail, we resort to disk
115
 
 
116
 
  CachedDirectory directory(drizzle_data_home, CachedDirectory::DIRECTORY);
117
 
 
118
 
  CachedDirectory::Entries files= directory.getEntries();
119
 
 
120
 
  for (CachedDirectory::Entries::iterator fileIter= files.begin();
121
 
       fileIter != files.end(); fileIter++)
122
 
  {
123
 
    CachedDirectory::Entry *entry= *fileIter;
124
 
    set_of_names.push_back(entry->filename);
125
 
  }
 
115
  }
 
116
  mutex.unlock_shared();
126
117
}
127
118
 
128
 
bool Schema::doGetSchemaDefinition(SchemaIdentifier &schema_identifier, message::Schema &schema_message)
 
119
bool Schema::doGetSchemaDefinition(const identifier::Schema &schema_identifier, message::schema::shared_ptr &schema_message)
129
120
{
130
 
  if (not pthread_rwlock_rdlock(&schema_lock))
 
121
  mutex.lock_shared();
 
122
  SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
 
123
 
 
124
  if (iter != schema_cache.end())
131
125
  {
132
 
    SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
133
 
 
134
 
    if (iter != schema_cache.end())
135
 
    {
136
 
      schema_message.CopyFrom(((*iter).second));
137
 
      pthread_rwlock_unlock(&schema_lock);
138
 
      return true;
139
 
    }
140
 
    pthread_rwlock_unlock(&schema_lock);
141
 
 
142
 
    return false;
 
126
    schema_message= (*iter).second;
 
127
    mutex.unlock_shared();
 
128
 
 
129
    return true;
143
130
  }
 
131
  mutex.unlock_shared();
144
132
 
145
 
  // Fail to disk based means
146
 
  return readSchemaFile(schema_identifier.getPath(), schema_message);
 
133
  return false;
147
134
}
148
135
 
 
136
 
149
137
bool Schema::doCreateSchema(const drizzled::message::Schema &schema_message)
150
138
{
151
 
  SchemaIdentifier schema_identifier(schema_message.name());
 
139
  identifier::Schema schema_identifier(schema_message.name());
152
140
 
153
141
  if (mkdir(schema_identifier.getPath().c_str(), 0777) == -1)
 
142
  {
 
143
    sql_perror(schema_identifier.getPath().c_str());
154
144
    return false;
 
145
  }
155
146
 
156
147
  if (not writeSchemaFile(schema_identifier, schema_message))
157
148
  {
160
151
    return false;
161
152
  }
162
153
 
163
 
  if (not pthread_rwlock_wrlock(&schema_lock))
164
154
  {
165
 
      pair<SchemaCache::iterator, bool> ret=
166
 
        schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
167
 
 
168
 
 
169
 
      if (ret.second == false)
170
 
      {
171
 
        abort(); // If this has happened, something really bad is going down.
172
 
      }
173
 
    pthread_rwlock_unlock(&schema_lock);
 
155
    boost::unique_lock<boost::shared_mutex> scopedLock(mutex);
 
156
    pair<SchemaCache::iterator, bool> ret=
 
157
      schema_cache.insert(make_pair(schema_identifier.getPath(), new message::Schema(schema_message)));
 
158
 
 
159
 
 
160
    if (ret.second == false)
 
161
    {
 
162
      abort(); // If this has happened, something really bad is going down.
 
163
    }
174
164
  }
175
165
 
176
166
  return true;
177
167
}
178
168
 
179
 
bool Schema::doDropSchema(SchemaIdentifier &schema_identifier)
 
169
bool Schema::doDropSchema(const identifier::Schema &schema_identifier)
180
170
{
181
 
  message::Schema schema_message;
 
171
  message::schema::shared_ptr schema_message;
182
172
 
183
173
  string schema_file(schema_identifier.getPath());
184
174
  schema_file.append(1, FN_LIBCHAR);
190
180
  // No db.opt file, no love from us.
191
181
  if (access(schema_file.c_str(), F_OK))
192
182
  {
193
 
    perror(schema_file.c_str());
 
183
    sql_perror(schema_file.c_str());
194
184
    return false;
195
185
  }
196
186
 
197
187
  if (unlink(schema_file.c_str()))
198
188
  {
199
 
    perror(schema_file.c_str());
 
189
    sql_perror(schema_file.c_str());
200
190
    return false;
201
191
  }
202
192
 
203
193
  if (rmdir(schema_identifier.getPath().c_str()))
204
194
  {
205
 
    perror(schema_identifier.getPath().c_str());
 
195
    sql_perror(schema_identifier.getPath().c_str());
206
196
    //@todo If this happens, we want a report of it. For the moment I dump
207
197
    //to stderr so I can catch it in Hudson.
208
198
    CachedDirectory dir(schema_identifier.getPath());
209
199
    cerr << dir;
210
200
  }
211
201
 
212
 
  if (not pthread_rwlock_wrlock(&schema_lock))
213
 
  {
214
 
    schema_cache.erase(schema_identifier.getPath());
215
 
    pthread_rwlock_unlock(&schema_lock);
216
 
  }
 
202
  boost::unique_lock<boost::shared_mutex> scopedLock(mutex);
 
203
  schema_cache.erase(schema_identifier.getPath());
217
204
 
218
205
  return true;
219
206
}
220
207
 
221
208
bool Schema::doAlterSchema(const drizzled::message::Schema &schema_message)
222
209
{
223
 
  SchemaIdentifier schema_identifier(schema_message.name());
 
210
  identifier::Schema schema_identifier(schema_message.name());
224
211
 
225
212
  if (access(schema_identifier.getPath().c_str(), F_OK))
226
213
    return false;
227
214
 
228
215
  if (writeSchemaFile(schema_identifier, schema_message))
229
216
  {
230
 
    if (not pthread_rwlock_wrlock(&schema_lock))
231
 
    {
232
 
      schema_cache.erase(schema_identifier.getPath());
233
 
 
234
 
      pair<SchemaCache::iterator, bool> ret=
235
 
        schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
236
 
 
237
 
      if (ret.second == false)
238
 
      {
239
 
        abort(); // If this has happened, something really bad is going down.
240
 
      }
241
 
 
242
 
      pthread_rwlock_unlock(&schema_lock);
243
 
    }
244
 
    else
245
 
    {
246
 
      abort(); // This would leave us out of sync, suck.
 
217
    boost::unique_lock<boost::shared_mutex> scopedLock(mutex);
 
218
    schema_cache.erase(schema_identifier.getPath());
 
219
 
 
220
    pair<SchemaCache::iterator, bool> ret=
 
221
      schema_cache.insert(make_pair(schema_identifier.getPath(), new message::Schema(schema_message)));
 
222
 
 
223
    if (ret.second == false)
 
224
    {
 
225
      abort(); // If this has happened, something really bad is going down.
247
226
    }
248
227
  }
249
228
 
255
234
 
256
235
  @note we do the rename to make it crash safe.
257
236
*/
258
 
bool Schema::writeSchemaFile(SchemaIdentifier &schema_identifier, const message::Schema &db)
 
237
bool Schema::writeSchemaFile(const identifier::Schema &schema_identifier, const message::Schema &db)
259
238
{
260
239
  char schema_file_tmp[FN_REFLEN];
261
240
  string schema_file(schema_identifier.getPath());
270
249
 
271
250
  if (fd == -1)
272
251
  {
273
 
    perror(schema_file_tmp);
 
252
    sql_perror(schema_file_tmp);
274
253
 
275
254
    return false;
276
255
  }
277
256
 
278
 
  if (not db.SerializeToFileDescriptor(fd))
279
 
  {
280
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
281
 
             db.InitializationErrorString().c_str());
 
257
  bool success;
 
258
 
 
259
  try {
 
260
    success= db.SerializeToFileDescriptor(fd);
 
261
  }
 
262
  catch (...)
 
263
  {
 
264
    success= false;
 
265
  }
 
266
 
 
267
  if (not success)
 
268
  {
 
269
    my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), schema_file.c_str(),
 
270
             db.InitializationErrorString().empty() ? "unknown" :  db.InitializationErrorString().c_str());
282
271
 
283
272
    if (close(fd) == -1)
284
 
      perror(schema_file_tmp);
 
273
      sql_perror(schema_file_tmp);
285
274
 
286
275
    if (unlink(schema_file_tmp))
287
 
      perror(schema_file_tmp);
 
276
      sql_perror(schema_file_tmp);
288
277
 
289
278
    return false;
290
279
  }
291
280
 
292
281
  if (close(fd) == -1)
293
282
  {
294
 
    perror(schema_file_tmp);
 
283
    sql_perror(schema_file_tmp);
295
284
 
296
285
    if (unlink(schema_file_tmp))
297
 
      perror(schema_file_tmp);
 
286
      sql_perror(schema_file_tmp);
298
287
 
299
288
    return false;
300
289
  }
302
291
  if (rename(schema_file_tmp, schema_file.c_str()) == -1)
303
292
  {
304
293
    if (unlink(schema_file_tmp))
305
 
      perror(schema_file_tmp);
 
294
      sql_perror(schema_file_tmp);
306
295
 
307
296
    return false;
308
297
  }
311
300
}
312
301
 
313
302
 
314
 
bool Schema::readSchemaFile(const std::string &schema_file_name, drizzled::message::Schema &schema_message)
 
303
bool Schema::readSchemaFile(const drizzled::identifier::Schema &schema_identifier, drizzled::message::Schema &schema)
315
304
{
316
 
  string db_opt_path(schema_file_name);
 
305
  return readSchemaFile(schema_identifier.getPath(), schema); 
 
306
}
317
307
 
 
308
bool Schema::readSchemaFile(std::string db_opt_path, drizzled::message::Schema &schema)
 
309
{
318
310
  /*
319
311
    Pass an empty file name, and the database options file name as extension
320
312
    to avoid table name to file name encoding.
331
323
  */
332
324
  if (input.good())
333
325
  {
334
 
    if (schema_message.ParseFromIstream(&input))
 
326
    if (schema.ParseFromIstream(&input))
335
327
    {
336
328
      return true;
337
329
    }
338
330
 
339
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
340
 
             schema_message.InitializationErrorString().c_str());
 
331
    my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), db_opt_path.c_str(),
 
332
             schema.InitializationErrorString().empty() ? "unknown" :  schema.InitializationErrorString().c_str());
341
333
  }
342
334
  else
343
335
  {
344
 
    perror(db_opt_path.c_str());
 
336
    sql_perror(db_opt_path.c_str());
345
337
  }
346
338
 
347
339
  return false;
348
340
}
349
341
 
350
 
bool Schema::doCanCreateTable(drizzled::TableIdentifier &identifier)
351
 
{
352
 
  if (static_cast<SchemaIdentifier&>(identifier) == TEMPORARY_IDENTIFIER)
353
 
  {
354
 
    return false;
355
 
  }
356
 
 
357
 
  return true;
358
 
}
359
 
 
360
342
void Schema::doGetTableIdentifiers(drizzled::CachedDirectory&,
361
 
                                   drizzled::SchemaIdentifier&,
362
 
                                   drizzled::TableIdentifiers&)
 
343
                                   const drizzled::identifier::Schema&,
 
344
                                   drizzled::identifier::Table::vector&)
363
345
{
364
346
}