~drizzle-trunk/drizzle/development

1273.20.1 by Brian Aker
Basic engine with test.
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2010 Brian Aker
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 */
20
21
#include "config.h"
22
1273.20.2 by Brian Aker
Adding on more bits for schema engine.
23
#include "plugin/schema_engine/schema.h"
24
#include "drizzled/db.h"
1273.19.20 by Brian Aker
Remove meta data call from db.cc
25
#include "drizzled/sql_table.h"
1309.1.2 by Brian Aker
Move IO for default DFE out of SE (more of).
26
#include "drizzled/global_charset_info.h"
27
#include "drizzled/charset.h"
28
#include "drizzled/charset_info.h"
29
#include "drizzled/cursor.h"
1273.20.1 by Brian Aker
Basic engine with test.
30
1309.1.30 by Brian Aker
Simplify dropTable() (will add exceptions right now)
31
#include "drizzled/internal/my_sys.h"
32
1309.1.1 by Brian Aker
This removes the special case read of proto from SE interface, down to
33
#include <fcntl.h>
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
34
#include <sys/stat.h>
35
#include <sys/types.h>
36
1309.1.1 by Brian Aker
This removes the special case read of proto from SE interface, down to
37
#include <google/protobuf/io/zero_copy_stream.h>
38
#include <google/protobuf/io/zero_copy_stream_impl.h>
39
1273.19.20 by Brian Aker
Remove meta data call from db.cc
40
#include <iostream>
41
#include <fstream>
1273.20.1 by Brian Aker
Basic engine with test.
42
#include <string>
43
44
using namespace std;
45
using namespace drizzled;
46
1556.1.1 by Brian Aker
Updates for moving temporary directory.
47
// This should always be the same value as GLOBAL_TEMPORARY_EXT but be
48
// CASE_UP. --Brian
1567 by Brian Aker
Remove restriction on schemas named temporary.
49
static SchemaIdentifier TEMPORARY_IDENTIFIER(".TEMPORARY");
1415 by Brian Aker
Mass overhaul to use schema_identifier.
50
1273.19.31 by Brian Aker
Fix dropSchema().
51
#define MY_DB_OPT_FILE "db.opt"
1309.1.2 by Brian Aker
Move IO for default DFE out of SE (more of).
52
#define DEFAULT_FILE_EXTENSION ".dfe" // Deep Fried Elephant
1273.19.31 by Brian Aker
Fix dropSchema().
53
1273.20.1 by Brian Aker
Basic engine with test.
54
Schema::Schema():
55
  drizzled::plugin::StorageEngine("schema",
56
                                  HTON_ALTER_NOT_SUPPORTED |
1273.19.30 by Brian Aker
Performance patch... we now only cycle through engines that actually have
57
                                  HTON_HAS_SCHEMA_DICTIONARY |
1273.20.1 by Brian Aker
Basic engine with test.
58
                                  HTON_SKIP_STORE_LOCK |
1309.1.3 by Brian Aker
Cache for Schema.
59
                                  HTON_TEMPORARY_NOT_SUPPORTED),
60
  schema_cache_filled(false)
61
{
62
  table_definition_ext= DEFAULT_FILE_EXTENSION;
63
  pthread_rwlock_init(&schema_lock, NULL);
64
  prime();
65
}
66
67
Schema::~Schema()
68
{
69
  pthread_rwlock_destroy(&schema_lock);
1273.20.1 by Brian Aker
Basic engine with test.
70
}
71
1309.1.3 by Brian Aker
Cache for Schema.
72
void Schema::prime()
73
{
1300.5.11 by Monty Taylor
Merged in trunk.
74
  CachedDirectory directory(data_home, CachedDirectory::DIRECTORY);
1309.1.3 by Brian Aker
Cache for Schema.
75
  CachedDirectory::Entries files= directory.getEntries();
76
77
  pthread_rwlock_wrlock(&schema_lock);
78
79
  for (CachedDirectory::Entries::iterator fileIter= files.begin();
80
       fileIter != files.end(); fileIter++)
81
  {
82
    CachedDirectory::Entry *entry= *fileIter;
83
    message::Schema schema_message;
84
1556.1.2 by Brian Aker
Creates a "cleanup" of Innodb's temp files in case of a crash of the DB.
85
    if (not entry->filename.compare(GLOBAL_TEMPORARY_EXT))
86
      continue;
87
1309.1.3 by Brian Aker
Cache for Schema.
88
    if (readSchemaFile(entry->filename, schema_message))
89
    {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
90
      SchemaIdentifier schema_identifier(schema_message.name());
91
1309.1.3 by Brian Aker
Cache for Schema.
92
      pair<SchemaCache::iterator, bool> ret=
1415 by Brian Aker
Mass overhaul to use schema_identifier.
93
        schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
1309.1.3 by Brian Aker
Cache for Schema.
94
95
      if (ret.second == false)
1415 by Brian Aker
Mass overhaul to use schema_identifier.
96
     {
1309.1.3 by Brian Aker
Cache for Schema.
97
        abort(); // If this has happened, something really bad is going down.
98
      }
99
    }
100
  }
101
  pthread_rwlock_unlock(&schema_lock);
102
}
103
1415 by Brian Aker
Mass overhaul to use schema_identifier.
104
void Schema::doGetSchemaIdentifiers(SchemaIdentifierList &set_of_names)
1273.20.1 by Brian Aker
Basic engine with test.
105
{
1309.1.3 by Brian Aker
Cache for Schema.
106
  if (not pthread_rwlock_rdlock(&schema_lock))
107
  {
108
    for (SchemaCache::iterator iter= schema_cache.begin();
109
         iter != schema_cache.end();
110
         iter++)
111
    {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
112
      set_of_names.push_back(SchemaIdentifier((*iter).second.name()));
1309.1.3 by Brian Aker
Cache for Schema.
113
    }
114
    pthread_rwlock_unlock(&schema_lock);
115
116
    return;
117
  }
118
119
  // If for some reason getting a lock should fail, we resort to disk
120
1300.5.11 by Monty Taylor
Merged in trunk.
121
  CachedDirectory directory(data_home, CachedDirectory::DIRECTORY);
1273.20.1 by Brian Aker
Basic engine with test.
122
123
  CachedDirectory::Entries files= directory.getEntries();
124
125
  for (CachedDirectory::Entries::iterator fileIter= files.begin();
126
       fileIter != files.end(); fileIter++)
127
  {
128
    CachedDirectory::Entry *entry= *fileIter;
1415 by Brian Aker
Mass overhaul to use schema_identifier.
129
    set_of_names.push_back(entry->filename);
1273.20.1 by Brian Aker
Basic engine with test.
130
  }
131
}
1273.20.2 by Brian Aker
Adding on more bits for schema engine.
132
1415 by Brian Aker
Mass overhaul to use schema_identifier.
133
bool Schema::doGetSchemaDefinition(SchemaIdentifier &schema_identifier, message::Schema &schema_message)
1273.20.2 by Brian Aker
Adding on more bits for schema engine.
134
{
1309.1.3 by Brian Aker
Cache for Schema.
135
  if (not pthread_rwlock_rdlock(&schema_lock))
1273.19.20 by Brian Aker
Remove meta data call from db.cc
136
  {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
137
    SchemaCache::iterator iter= schema_cache.find(schema_identifier.getPath());
138
1309.1.3 by Brian Aker
Cache for Schema.
139
    if (iter != schema_cache.end())
1273.19.20 by Brian Aker
Remove meta data call from db.cc
140
    {
1309.1.3 by Brian Aker
Cache for Schema.
141
      schema_message.CopyFrom(((*iter).second));
142
      pthread_rwlock_unlock(&schema_lock);
1273.19.20 by Brian Aker
Remove meta data call from db.cc
143
      return true;
144
    }
1309.1.3 by Brian Aker
Cache for Schema.
145
    pthread_rwlock_unlock(&schema_lock);
146
147
    return false;
148
  }
149
150
  // Fail to disk based means
1415 by Brian Aker
Mass overhaul to use schema_identifier.
151
  return readSchemaFile(schema_identifier.getPath(), schema_message);
1273.20.2 by Brian Aker
Adding on more bits for schema engine.
152
}
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
153
154
bool Schema::doCreateSchema(const drizzled::message::Schema &schema_message)
155
{
1415 by Brian Aker
Mass overhaul to use schema_identifier.
156
  SchemaIdentifier schema_identifier(schema_message.name());
157
158
  if (mkdir(schema_identifier.getPath().c_str(), 0777) == -1)
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
159
    return false;
160
1415 by Brian Aker
Mass overhaul to use schema_identifier.
161
  if (not writeSchemaFile(schema_identifier, schema_message))
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
162
  {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
163
    rmdir(schema_identifier.getPath().c_str());
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
164
165
    return false;
166
  }
167
1309.1.3 by Brian Aker
Cache for Schema.
168
  if (not pthread_rwlock_wrlock(&schema_lock))
169
  {
170
      pair<SchemaCache::iterator, bool> ret=
1415 by Brian Aker
Mass overhaul to use schema_identifier.
171
        schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
1309.1.3 by Brian Aker
Cache for Schema.
172
173
174
      if (ret.second == false)
175
      {
176
        abort(); // If this has happened, something really bad is going down.
177
      }
178
    pthread_rwlock_unlock(&schema_lock);
179
  }
180
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
181
  return true;
182
}
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
183
1415 by Brian Aker
Mass overhaul to use schema_identifier.
184
bool Schema::doDropSchema(SchemaIdentifier &schema_identifier)
1273.19.31 by Brian Aker
Fix dropSchema().
185
{
186
  message::Schema schema_message;
187
1415 by Brian Aker
Mass overhaul to use schema_identifier.
188
  string schema_file(schema_identifier.getPath());
1273.19.31 by Brian Aker
Fix dropSchema().
189
  schema_file.append(1, FN_LIBCHAR);
190
  schema_file.append(MY_DB_OPT_FILE);
191
1415 by Brian Aker
Mass overhaul to use schema_identifier.
192
  if (not doGetSchemaDefinition(schema_identifier, schema_message))
1273.19.31 by Brian Aker
Fix dropSchema().
193
    return false;
194
195
  // No db.opt file, no love from us.
196
  if (access(schema_file.c_str(), F_OK))
197
  {
198
    perror(schema_file.c_str());
199
    return false;
200
  }
201
202
  if (unlink(schema_file.c_str()))
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
203
  {
1273.19.31 by Brian Aker
Fix dropSchema().
204
    perror(schema_file.c_str());
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
205
    return false;
206
  }
1273.19.31 by Brian Aker
Fix dropSchema().
207
1415 by Brian Aker
Mass overhaul to use schema_identifier.
208
  if (rmdir(schema_identifier.getPath().c_str()))
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
209
  {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
210
    perror(schema_identifier.getPath().c_str());
211
    //@todo If this happens, we want a report of it. For the moment I dump
212
    //to stderr so I can catch it in Hudson.
213
    CachedDirectory dir(schema_identifier.getPath());
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
214
    cerr << dir;
215
  }
1273.19.31 by Brian Aker
Fix dropSchema().
216
1309.1.3 by Brian Aker
Cache for Schema.
217
  if (not pthread_rwlock_wrlock(&schema_lock))
218
  {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
219
    schema_cache.erase(schema_identifier.getPath());
1309.1.3 by Brian Aker
Cache for Schema.
220
    pthread_rwlock_unlock(&schema_lock);
221
  }
222
1273.19.31 by Brian Aker
Fix dropSchema().
223
  return true;
224
}
225
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
226
bool Schema::doAlterSchema(const drizzled::message::Schema &schema_message)
227
{
1415 by Brian Aker
Mass overhaul to use schema_identifier.
228
  SchemaIdentifier schema_identifier(schema_message.name());
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
229
1415 by Brian Aker
Mass overhaul to use schema_identifier.
230
  if (access(schema_identifier.getPath().c_str(), F_OK))
1273.19.28 by Brian Aker
More cleanup on ALTER SCHEMA. Hey! MySQL never had errors on half of it...
231
    return false;
232
1415 by Brian Aker
Mass overhaul to use schema_identifier.
233
  if (writeSchemaFile(schema_identifier, schema_message))
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
234
  {
1309.1.3 by Brian Aker
Cache for Schema.
235
    if (not pthread_rwlock_wrlock(&schema_lock))
236
    {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
237
      schema_cache.erase(schema_identifier.getPath());
1309.1.3 by Brian Aker
Cache for Schema.
238
239
      pair<SchemaCache::iterator, bool> ret=
1415 by Brian Aker
Mass overhaul to use schema_identifier.
240
        schema_cache.insert(make_pair(schema_identifier.getPath(), schema_message));
1309.1.3 by Brian Aker
Cache for Schema.
241
242
      if (ret.second == false)
243
      {
244
        abort(); // If this has happened, something really bad is going down.
245
      }
246
247
      pthread_rwlock_unlock(&schema_lock);
248
    }
249
    else
250
    {
251
      abort(); // This would leave us out of sync, suck.
252
    }
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
253
  }
254
255
  return true;
256
}
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
257
258
/**
259
  path is path to database, not schema file 
260
261
  @note we do the rename to make it crash safe.
262
*/
1415 by Brian Aker
Mass overhaul to use schema_identifier.
263
bool Schema::writeSchemaFile(SchemaIdentifier &schema_identifier, const message::Schema &db)
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
264
{
265
  char schema_file_tmp[FN_REFLEN];
1415 by Brian Aker
Mass overhaul to use schema_identifier.
266
  string schema_file(schema_identifier.getPath());
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
267
268
269
  schema_file.append(1, FN_LIBCHAR);
270
  schema_file.append(MY_DB_OPT_FILE);
271
1395.1.18 by Brian Aker
Small update.
272
  snprintf(schema_file_tmp, FN_REFLEN, "%sXXXXXX", schema_file.c_str());
273
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
274
  int fd= mkstemp(schema_file_tmp);
275
276
  if (fd == -1)
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
277
  {
278
    perror(schema_file_tmp);
1395.1.18 by Brian Aker
Small update.
279
1309.1.3 by Brian Aker
Cache for Schema.
280
    return false;
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
281
  }
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
282
1608.1.2 by Brian Aker
Merge enum test
283
  bool success;
284
285
  try {
286
    success= db.SerializeToFileDescriptor(fd);
287
  }
288
  catch (...)
289
  {
290
    success= false;
291
  }
292
293
  if (not success)
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
294
  {
1567.1.1 by Brian Aker
This fixes bug 586009, increases the size of the log files so that the UNION
295
    my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), schema_file.c_str(),
296
             db.InitializationErrorString().empty() ? "unknown" :  db.InitializationErrorString().c_str());
1395.1.18 by Brian Aker
Small update.
297
298
    if (close(fd) == -1)
299
      perror(schema_file_tmp);
300
301
    if (unlink(schema_file_tmp))
302
      perror(schema_file_tmp);
303
304
    return false;
305
  }
306
307
  if (close(fd) == -1)
308
  {
309
    perror(schema_file_tmp);
310
311
    if (unlink(schema_file_tmp))
312
      perror(schema_file_tmp);
1309.1.3 by Brian Aker
Cache for Schema.
313
314
    return false;
1273.19.27 by Brian Aker
Move schema writing code to schema engine plugin.
315
  }
316
317
  if (rename(schema_file_tmp, schema_file.c_str()) == -1)
318
  {
1395.1.18 by Brian Aker
Small update.
319
    if (unlink(schema_file_tmp))
320
      perror(schema_file_tmp);
1309.1.3 by Brian Aker
Cache for Schema.
321
322
    return false;
323
  }
324
325
  return true;
326
}
327
328
1415 by Brian Aker
Mass overhaul to use schema_identifier.
329
bool Schema::readSchemaFile(const std::string &schema_file_name, drizzled::message::Schema &schema_message)
1309.1.3 by Brian Aker
Cache for Schema.
330
{
1415 by Brian Aker
Mass overhaul to use schema_identifier.
331
  string db_opt_path(schema_file_name);
1309.1.3 by Brian Aker
Cache for Schema.
332
333
  /*
334
    Pass an empty file name, and the database options file name as extension
335
    to avoid table name to file name encoding.
336
  */
1415 by Brian Aker
Mass overhaul to use schema_identifier.
337
  db_opt_path.append(1, FN_LIBCHAR);
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
338
  db_opt_path.append(MY_DB_OPT_FILE);
1309.1.3 by Brian Aker
Cache for Schema.
339
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
340
  fstream input(db_opt_path.c_str(), ios::in | ios::binary);
1309.1.3 by Brian Aker
Cache for Schema.
341
342
  /**
343
    @note If parsing fails, either someone has done a "mkdir" or has deleted their opt file.
344
    So what do we do? We muddle through the adventure by generating 
345
    one with a name in it, and the charset set to the default.
346
  */
347
  if (input.good())
348
  {
349
    if (schema_message.ParseFromIstream(&input))
350
    {
351
      return true;
352
    }
1415 by Brian Aker
Mass overhaul to use schema_identifier.
353
1567.1.1 by Brian Aker
This fixes bug 586009, increases the size of the log files so that the UNION
354
    my_error(ER_CORRUPT_SCHEMA_DEFINITION, MYF(0), db_opt_path.c_str(),
355
             schema_message.InitializationErrorString().empty() ? "unknown" :  schema_message.InitializationErrorString().c_str());
1309.1.3 by Brian Aker
Cache for Schema.
356
  }
357
  else
358
  {
1358.1.5 by Brian Aker
Cleans up use of static buffer in TableIdentifier.
359
    perror(db_opt_path.c_str());
1309.1.3 by Brian Aker
Cache for Schema.
360
  }
361
362
  return false;
363
}
1320.1.8 by Brian Aker
Temporary fix for allowing engines to say "don't do this".
364
1415 by Brian Aker
Mass overhaul to use schema_identifier.
365
bool Schema::doCanCreateTable(drizzled::TableIdentifier &identifier)
1320.1.8 by Brian Aker
Temporary fix for allowing engines to say "don't do this".
366
{
1415 by Brian Aker
Mass overhaul to use schema_identifier.
367
  if (static_cast<SchemaIdentifier&>(identifier) == TEMPORARY_IDENTIFIER)
1358.1.1 by Brian Aker
Fixes regression in performance from Exists patch.
368
  {
369
    return false;
370
  }
371
372
  return true;
373
}
1429.1.3 by Brian Aker
Merge in work for fetching a list of table identifiers.
374
375
void Schema::doGetTableIdentifiers(drizzled::CachedDirectory&,
376
                                   drizzled::SchemaIdentifier&,
377
                                   drizzled::TableIdentifiers&)
378
{
379
}