~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/schema_engine/schema.cc

  • Committer: Stewart Smith
  • Date: 2010-11-03 03:27:09 UTC
  • mto: (1902.1.1 build) (1910.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1903.
  • Revision ID: stewart@flamingspork.com-20101103032709-oyvfrc6eb8fzj0mr
fix docs warning: docs/unlock.rst:2: (WARNING/2) Title underline too short.

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"
30
31
 
31
32
#include "drizzled/internal/my_sys.h"
 
33
#include "drizzled/transaction_services.h"
32
34
 
33
35
#include <fcntl.h>
34
36
#include <sys/stat.h>
44
46
using namespace std;
45
47
using namespace drizzled;
46
48
 
47
 
static SchemaIdentifier TEMPORARY_IDENTIFIER("TEMPORARY");
48
49
 
49
50
#define MY_DB_OPT_FILE "db.opt"
50
51
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
58
59
  schema_cache_filled(false)
59
60
{
60
61
  table_definition_ext= DEFAULT_FILE_EXTENSION;
61
 
  pthread_rwlock_init(&schema_lock, NULL);
62
62
  prime();
63
63
}
64
64
 
65
65
Schema::~Schema()
66
66
{
67
 
  pthread_rwlock_destroy(&schema_lock);
68
67
}
69
68
 
70
69
void Schema::prime()
71
70
{
72
 
  CachedDirectory directory(drizzle_data_home, CachedDirectory::DIRECTORY);
 
71
  CachedDirectory directory(getDataHomeCatalog().file_string(), CachedDirectory::DIRECTORY);
73
72
  CachedDirectory::Entries files= directory.getEntries();
74
73
 
75
 
  pthread_rwlock_wrlock(&schema_lock);
 
74
  mutex.lock();
76
75
 
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;
82
81
 
83
 
    if (readSchemaFile(entry->filename, schema_message))
 
82
    if (not entry->filename.compare(GLOBAL_TEMPORARY_EXT))
 
83
      continue;
 
84
 
 
85
    SchemaIdentifier filename(entry->filename);
 
86
    if (readSchemaFile(filename, schema_message))
84
87
    {
85
88
      SchemaIdentifier 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
     {
93
96
      }
94
97
    }
95
98
  }
96
 
  pthread_rwlock_unlock(&schema_lock);
 
99
  mutex.unlock();
97
100
}
98
101
 
99
 
void Schema::doGetSchemaIdentifiers(SchemaIdentifierList &set_of_names)
 
102
void Schema::doGetSchemaIdentifiers(SchemaIdentifiers &set_of_names)
100
103
{
101
 
  if (not pthread_rwlock_rdlock(&schema_lock))
 
104
  mutex.lock_shared();
102
105
  {
103
106
    for (SchemaCache::iterator iter= schema_cache.begin();
104
107
         iter != schema_cache.end();
105
108
         iter++)
106
109
    {
107
 
      set_of_names.push_back(SchemaIdentifier((*iter).second.name()));
 
110
      set_of_names.push_back(SchemaIdentifier((*iter).second->name()));
108
111
    }
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
 
  }
 
112
  }
 
113
  mutex.unlock_shared();
126
114
}
127
115
 
128
 
bool Schema::doGetSchemaDefinition(SchemaIdentifier &schema_identifier, message::Schema &schema_message)
 
116
bool Schema::doGetSchemaDefinition(const SchemaIdentifier &schema_identifier, message::SchemaPtr &schema_message)
129
117
{
130
 
  if (not pthread_rwlock_rdlock(&schema_lock))
 
118
  mutex.lock_shared();
 
119
  SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
 
120
 
 
121
  if (iter != schema_cache.end())
131
122
  {
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;
 
123
    schema_message= (*iter).second;
 
124
    mutex.unlock_shared();
 
125
    return true;
143
126
  }
 
127
  mutex.unlock_shared();
144
128
 
145
 
  // Fail to disk based means
146
 
  return readSchemaFile(schema_identifier.getPath(), schema_message);
 
129
  return false;
147
130
}
148
131
 
 
132
 
149
133
bool Schema::doCreateSchema(const drizzled::message::Schema &schema_message)
150
134
{
151
135
  SchemaIdentifier schema_identifier(schema_message.name());
160
144
    return false;
161
145
  }
162
146
 
163
 
  if (not pthread_rwlock_wrlock(&schema_lock))
 
147
  mutex.lock();
164
148
  {
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);
 
149
    pair<SchemaCache::iterator, bool> ret=
 
150
      schema_cache.insert(make_pair(schema_identifier.getPath(), new message::Schema(schema_message)));
 
151
 
 
152
 
 
153
    if (ret.second == false)
 
154
    {
 
155
      abort(); // If this has happened, something really bad is going down.
 
156
    }
174
157
  }
 
158
  mutex.unlock();
 
159
 
 
160
  TransactionServices &transaction_services= TransactionServices::singleton();
 
161
  transaction_services.allocateNewTransactionId();
175
162
 
176
163
  return true;
177
164
}
178
165
 
179
 
bool Schema::doDropSchema(SchemaIdentifier &schema_identifier)
 
166
bool Schema::doDropSchema(const SchemaIdentifier &schema_identifier)
180
167
{
181
 
  message::Schema schema_message;
 
168
  message::SchemaPtr schema_message;
182
169
 
183
170
  string schema_file(schema_identifier.getPath());
184
171
  schema_file.append(1, FN_LIBCHAR);
209
196
    cerr << dir;
210
197
  }
211
198
 
212
 
  if (not pthread_rwlock_wrlock(&schema_lock))
213
 
  {
214
 
    schema_cache.erase(schema_identifier.getPath());
215
 
    pthread_rwlock_unlock(&schema_lock);
216
 
  }
 
199
  mutex.lock();
 
200
  schema_cache.erase(schema_identifier.getPath());
 
201
  mutex.unlock();
 
202
 
 
203
  TransactionServices &transaction_services= TransactionServices::singleton();
 
204
  transaction_services.allocateNewTransactionId();
217
205
 
218
206
  return true;
219
207
}
227
215
 
228
216
  if (writeSchemaFile(schema_identifier, schema_message))
229
217
  {
230
 
    if (not pthread_rwlock_wrlock(&schema_lock))
 
218
    mutex.lock();
231
219
    {
232
220
      schema_cache.erase(schema_identifier.getPath());
233
221
 
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)));
236
224
 
237
225
      if (ret.second == false)
238
226
      {
239
227
        abort(); // If this has happened, something really bad is going down.
240
228
      }
 
229
    }
 
230
    mutex.unlock();
241
231
 
242
 
      pthread_rwlock_unlock(&schema_lock);
243
 
    }
244
 
    else
245
 
    {
246
 
      abort(); // This would leave us out of sync, suck.
247
 
    }
 
232
    TransactionServices &transaction_services= TransactionServices::singleton();
 
233
    transaction_services.allocateNewTransactionId();
248
234
  }
249
235
 
250
236
  return true;
255
241
 
256
242
  @note we do the rename to make it crash safe.
257
243
*/
258
 
bool Schema::writeSchemaFile(SchemaIdentifier &schema_identifier, const message::Schema &db)
 
244
bool Schema::writeSchemaFile(const SchemaIdentifier &schema_identifier, const message::Schema &db)
259
245
{
260
246
  char schema_file_tmp[FN_REFLEN];
261
247
  string schema_file(schema_identifier.getPath());
275
261
    return false;
276
262
  }
277
263
 
278
 
  if (not db.SerializeToFileDescriptor(fd))
279
 
  {
280
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
281
 
             db.InitializationErrorString().c_str());
 
264
  bool success;
 
265
 
 
266
  try {
 
267
    success= db.SerializeToFileDescriptor(fd);
 
268
  }
 
269
  catch (...)
 
270
  {
 
271
    success= false;
 
272
  }
 
273
 
 
274
  if (not success)
 
275
  {
 
276
    my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), schema_file.c_str(),
 
277
             db.InitializationErrorString().empty() ? "unknown" :  db.InitializationErrorString().c_str());
282
278
 
283
279
    if (close(fd) == -1)
284
280
      perror(schema_file_tmp);
311
307
}
312
308
 
313
309
 
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)
315
311
{
316
 
  string db_opt_path(schema_file_name);
 
312
  string db_opt_path(schema_identifier.getPath());
317
313
 
318
314
  /*
319
315
    Pass an empty file name, and the database options file name as extension
331
327
  */
332
328
  if (input.good())
333
329
  {
334
 
    if (schema_message.ParseFromIstream(&input))
 
330
    if (schema.ParseFromIstream(&input))
335
331
    {
336
332
      return true;
337
333
    }
338
334
 
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());
341
337
  }
342
338
  else
343
339
  {
347
343
  return false;
348
344
}
349
345
 
350
 
bool Schema::doCanCreateTable(drizzled::TableIdentifier &identifier)
 
346
bool Schema::doCanCreateTable(const drizzled::TableIdentifier &identifier)
351
347
{
352
 
  if (static_cast<SchemaIdentifier&>(identifier) == TEMPORARY_IDENTIFIER)
 
348
 
 
349
  // This should always be the same value as GLOBAL_TEMPORARY_EXT but be
 
350
  // CASE_UP. --Brian 
 
351
  //
 
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)
353
355
  {
354
356
    return false;
355
357
  }
358
360
}
359
361
 
360
362
void Schema::doGetTableIdentifiers(drizzled::CachedDirectory&,
361
 
                                   drizzled::SchemaIdentifier&,
 
363
                                   const drizzled::SchemaIdentifier&,
362
364
                                   drizzled::TableIdentifiers&)
363
365
{
364
366
}