~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Stewart Smith
  • Date: 2009-02-02 04:55:56 UTC
  • mto: (859.1.1 nofrm)
  • mto: This revision was merged to the branch mainline in revision 822.
  • Revision ID: stewart@flamingspork.com-20090202045556-mwmdwi60el6a371r
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.

Write db.opt safely (temp file, rename).

LOCK_drizzle_create_db can likely easily go now.

schema.proto: remove charset as it is standard, we only care about collation.

We don't change the epic fail that is the lack of error checking in show.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
166
166
    (collation_server).
167
167
  */
168
168
 
 
169
  load_db_opt_by_name(session, db_name, &db_info);
 
170
 
169
171
  return db_info.default_table_charset;
170
172
}
171
173
 
 
174
/* path is path to database, not schema file */
 
175
static int write_schema_file(Session *session,
 
176
                             const char *path, const char *name,
 
177
                             HA_CREATE_INFO *create)
 
178
{
 
179
  drizzle::Schema db;
 
180
  char schema_file_tmp[FN_REFLEN];
 
181
  string schema_file(path);
 
182
 
 
183
  assert(path);
 
184
  assert(name);
 
185
  assert(create);
 
186
 
 
187
  snprintf(schema_file_tmp, FN_REFLEN, "%s%cdb.opt.tmpXXXXXX",path,FN_LIBCHAR);
 
188
 
 
189
  schema_file.append(1, FN_LIBCHAR);
 
190
  schema_file.append("db.opt");
 
191
 
 
192
  int fd= mkstemp(schema_file_tmp);
 
193
 
 
194
  if (fd==-1)
 
195
    return errno;
 
196
 
 
197
  if (!create->default_table_charset)
 
198
    create->default_table_charset= session->variables.collation_server;
 
199
 
 
200
  db.set_name(name);
 
201
  db.set_collation(create->default_table_charset->name);
 
202
 
 
203
  if (!db.SerializeToFileDescriptor(fd))
 
204
  {
 
205
    close(fd);
 
206
    unlink(schema_file_tmp);
 
207
    return -1;
 
208
  }
 
209
 
 
210
  if (rename(schema_file_tmp, schema_file.c_str()) == -1)
 
211
  {
 
212
    close(fd);
 
213
    return errno;
 
214
  }
 
215
 
 
216
  close(fd);
 
217
  return 0;
 
218
}
 
219
 
 
220
int load_db_opt(Session *session, const char *path, HA_CREATE_INFO *create)
 
221
{
 
222
  drizzle::Schema db;
 
223
  string buffer;
 
224
 
 
225
  memset(create, 0, sizeof(*create));
 
226
  create->default_table_charset= session->variables.collation_server;
 
227
 
 
228
  int fd= open(path, O_RDONLY);
 
229
 
 
230
  if (fd == -1)
 
231
    return errno;
 
232
 
 
233
  if (!db.ParseFromFileDescriptor(fd))
 
234
  {
 
235
    close(fd);
 
236
    return -1;
 
237
  }
 
238
  close(fd);
 
239
 
 
240
  buffer= db.collation();
 
241
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(),
 
242
                                                           MYF(0))))
 
243
  {
 
244
    errmsg_printf(ERRMSG_LVL_ERROR,
 
245
                  _("Error while loading database options: '%s':"),path);
 
246
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
 
247
    create->default_table_charset= default_charset_info;
 
248
    return -1;
 
249
  }
 
250
 
 
251
  return 0;
 
252
}
 
253
 
 
254
int load_db_opt_by_name(Session *session, const char *db_name,
 
255
                        HA_CREATE_INFO *db_create_info)
 
256
{
 
257
  char db_opt_path[FN_REFLEN];
 
258
 
 
259
  /*
 
260
    Pass an empty file name, and the database options file name as extension
 
261
    to avoid table name to file name encoding.
 
262
  */
 
263
  (void) build_table_filename(db_opt_path, sizeof(db_opt_path),
 
264
                              db_name, "", "db.opt", 0);
 
265
 
 
266
  return load_db_opt(session, db_opt_path, db_create_info);
 
267
}
 
268
 
172
269
 
173
270
/*
174
271
  Create a database
200
297
  char   tmp_query[FN_REFLEN+16];
201
298
  long result= 1;
202
299
  int error= 0;
203
 
  struct stat stat_info;
204
300
  uint32_t create_options= create_info ? create_info->options : 0;
205
301
  uint32_t path_len;
206
302
 
235
331
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
236
332
  path[path_len-1]= 0;                    // Remove last '/' from path
237
333
 
238
 
  if (!stat(path,&stat_info))
 
334
  if (mkdir(path,0777) == -1)
239
335
  {
240
 
    if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
336
    if (errno == EEXIST)
241
337
    {
242
 
      my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
243
 
      error= -1;
 
338
      if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
339
      {
 
340
        my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
 
341
        error= -1;
 
342
        goto exit;
 
343
      }
 
344
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
345
                          ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
 
346
      if (!silent)
 
347
        my_ok(session);
 
348
      error= 0;
244
349
      goto exit;
245
350
    }
246
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
247
 
                        ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
248
 
    if (!silent)
249
 
      my_ok(session);
250
 
    error= 0;
 
351
 
 
352
    my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
 
353
    error= -1;
251
354
    goto exit;
252
355
  }
253
 
  else
 
356
 
 
357
  error= write_schema_file(session, path, db, create_info);
 
358
  if (error && error != EEXIST)
254
359
  {
255
 
    if (errno != ENOENT)
256
 
    {
257
 
      my_error(EE_STAT, MYF(0), path, errno);
258
 
      goto exit;
259
 
    }
260
 
    if (mkdir(path,0777) < 0)
261
 
    {
262
 
      my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
 
360
    if (rmdir(path) >= 0)
 
361
    {
263
362
      error= -1;
264
363
      goto exit;
265
364
    }
298
397
bool mysql_alter_db(Session *session, const char *db, HA_CREATE_INFO *create_info)
299
398
{
300
399
  long result=1;
301
 
  int error= false;
 
400
  int error= 0;
 
401
  char   path[FN_REFLEN+16];
 
402
  uint32_t path_len;
302
403
 
303
404
  /*
304
405
    Do not alter database if another thread is holding read lock.
318
419
  pthread_mutex_lock(&LOCK_drizzle_create_db);
319
420
 
320
421
  /* Change options if current database is being altered. */
 
422
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
 
423
  path[path_len-1]= 0;                    // Remove last '/' from path
 
424
 
 
425
  error= write_schema_file(session, path, db, create_info);
 
426
  if (error && error != EEXIST)
 
427
  {
 
428
    /* TODO: find some witty way of getting back an error message */
 
429
    pthread_mutex_unlock(&LOCK_drizzle_create_db);
 
430
    goto exit;
 
431
  }
321
432
 
322
433
  if (session->db && !strcmp(session->db,db))
323
434
  {
390
501
  pthread_mutex_lock(&LOCK_drizzle_create_db);
391
502
 
392
503
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
 
504
  strcpy(path+length, "db.opt");         // Append db option file name
 
505
  unlink(path);
393
506
  path[length]= '\0';                           // Remove file name
394
507
 
395
508
  /* See if the directory exists */