~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/transaction_log/transaction_log.cc

  • Committer: Brian Aker
  • Date: 2009-11-27 18:34:26 UTC
  • mfrom: (1143.3.9 transaction-log)
  • Revision ID: brian@gaz-20091127183426-uj7730j5c5xwmo2x
Merge Jay

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
 * Possibly look at a scoreboard approach with multiple file segments.  For
64
64
 * right now, though, this is just a quick simple implementation to serve
65
65
 * as a skeleton and a springboard.
 
66
 *
 
67
 * @todo
 
68
 *
 
69
 * Move the Applier piece of this code out into its own source file and leave
 
70
 * this for all the glue code of the module.
66
71
 */
67
72
 
68
73
#include <drizzled/server_includes.h>
69
74
#include "transaction_log.h"
 
75
#include "transaction_log_index.h"
 
76
#include "info_schema.h"
 
77
#include "print_transaction_message.h"
 
78
#include "hexdump_transaction_message.h"
 
79
#include "background_worker.h"
70
80
 
71
81
#include <unistd.h>
72
82
 
106
116
 */
107
117
static bool sysvar_transaction_log_checksum_enabled= false;
108
118
 
 
119
/** Views defined in info_schema.cc */
 
120
extern plugin::InfoSchemaTable *transaction_log_view;
 
121
extern plugin::InfoSchemaTable *transaction_log_entries_view;
 
122
extern plugin::InfoSchemaTable *transaction_log_transactions_view;
 
123
 
 
124
/** Index defined in transaction_log_index.cc */
 
125
extern TransactionLogIndex *transaction_log_index;
 
126
 
 
127
/** Defined in print_transaction_message.cc */
 
128
extern plugin::Create_function<PrintTransactionMessageFunction> *print_transaction_message_func_factory;
 
129
extern plugin::Create_function<HexdumpTransactionMessageFunction> *hexdump_transaction_message_func_factory;
 
130
 
109
131
TransactionLog::TransactionLog(string name_arg,
110
 
                               const char *in_log_file_path,
 
132
                               const string &in_log_file_path,
111
133
                               bool in_do_checksum)
112
134
  : plugin::TransactionApplier(name_arg),
113
135
    state(OFFLINE),
114
 
    log_file_path(in_log_file_path)
 
136
    log_file_path(in_log_file_path),
 
137
    has_error(false),
 
138
    error_message()
115
139
{
116
140
  do_checksum= in_do_checksum; /* Have to do here, not in initialization list b/c atomic<> */
117
141
 
118
142
  /* Setup our log file and determine the next write offset... */
119
 
  log_file= open(log_file_path, O_APPEND|O_CREAT|O_SYNC|O_WRONLY, S_IRWXU);
 
143
  log_file= open(log_file_path.c_str(), O_APPEND|O_CREAT|O_SYNC|O_WRONLY, S_IRWXU);
120
144
  if (log_file == -1)
121
145
  {
122
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to open transaction log file %s.  Got error: %s\n"), 
123
 
                  log_file_path, 
124
 
                  strerror(errno));
 
146
    error_message.assign(_("Failed to open transaction log file "));
 
147
    error_message.append(log_file_path);
 
148
    error_message.append("  Got error: ");
 
149
    error_message.append(strerror(errno));
 
150
    error_message.push_back('\n');
 
151
    has_error= true;
125
152
    deactivate();
126
153
    return;
127
154
  }
128
155
 
 
156
  /* For convenience, grab the log file name from the path */
 
157
  if (log_file_path.find_first_of('/') != string::npos)
 
158
  {
 
159
    /* Strip to last / */
 
160
    string tmp;
 
161
    tmp= log_file_path.substr(log_file_path.find_last_of('/') + 1);
 
162
    log_file_name.assign(tmp);
 
163
  }
 
164
  else
 
165
    log_file_name.assign(log_file_path);
 
166
 
129
167
  /* 
130
168
   * The offset of the next write is the current position of the log
131
169
   * file, since it's opened in append mode...
251
289
 
252
290
  error_code= my_sync(log_file, 0);
253
291
 
 
292
  transaction_log_index->addEntry(TransactionLogEntry(ReplicationServices::TRANSACTION,
 
293
                                                     cur_offset,
 
294
                                                     total_envelope_length),
 
295
                                  to_apply,
 
296
                                  checksum);
 
297
 
254
298
  if (unlikely(error_code != 0))
255
299
  {
256
300
    errmsg_printf(ERRMSG_LVL_ERROR, 
259
303
  }
260
304
}
261
305
 
 
306
const string &TransactionLog::getLogFilename()
 
307
{
 
308
  return log_file_name;
 
309
}
 
310
 
 
311
const string &TransactionLog::getLogFilepath()
 
312
{
 
313
  return log_file_path;
 
314
}
 
315
 
262
316
void TransactionLog::truncate()
263
317
{
264
318
  bool orig_is_enabled= isEnabled();
288
342
}
289
343
 
290
344
bool TransactionLog::findLogFilenameContainingTransactionId(const ReplicationServices::GlobalTransactionId&,
291
 
                                                        string &out_filename) const
 
345
                                                            string &out_filename) const
292
346
{
293
347
  /* 
294
348
   * Currently, we simply return the single logfile name
299
353
  return true;
300
354
}
301
355
 
302
 
static TransactionLog *transaction_log= NULL; /* The singleton transaction log */
 
356
bool TransactionLog::hasError() const
 
357
{
 
358
  return has_error;
 
359
}
 
360
 
 
361
void TransactionLog::clearError()
 
362
{
 
363
  has_error= false;
 
364
  error_message.clear();
 
365
}
 
366
 
 
367
const std::string &TransactionLog::getErrorMessage() const
 
368
{
 
369
  return error_message;
 
370
}
 
371
 
 
372
TransactionLog *transaction_log= NULL; /* The singleton transaction log */
303
373
 
304
374
static int init(drizzled::plugin::Registry &registry)
305
375
{
 
376
  /* Create and initialize the transaction log itself */
306
377
  if (sysvar_transaction_log_enabled)
307
378
  {
308
 
    transaction_log= new TransactionLog("transaction_log",
309
 
                                        sysvar_transaction_log_file, 
310
 
                                        sysvar_transaction_log_checksum_enabled);
 
379
    transaction_log= new (nothrow) TransactionLog("transaction_log_applier",
 
380
                                                  string(sysvar_transaction_log_file), 
 
381
                                                  sysvar_transaction_log_checksum_enabled);
 
382
 
 
383
    if (transaction_log == NULL)
 
384
    {
 
385
      errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLog instance.  Got error: %s\n"), 
 
386
                    strerror(errno));
 
387
      return 1;
 
388
    }
 
389
    else
 
390
    {
 
391
      /* Check to see if the log was not created properly */
 
392
      if (transaction_log->hasError())
 
393
      {
 
394
        errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log.  Got error: %s\n"), 
 
395
                      transaction_log->getErrorMessage().c_str());
 
396
        return 1;
 
397
      }
 
398
    }
311
399
    registry.add(transaction_log);
 
400
 
 
401
    /* Setup the INFORMATION_SCHEMA views for the transaction log */
 
402
    if (initViewMethods() ||
 
403
        initViewColumns() || 
 
404
        initViews())
 
405
      return 1; /* Error message output handled in functions above */
 
406
 
 
407
    registry.add(transaction_log_view);
 
408
    registry.add(transaction_log_entries_view);
 
409
    registry.add(transaction_log_transactions_view);
 
410
 
 
411
    /* Setup the module's UDFs */
 
412
    print_transaction_message_func_factory=
 
413
      new plugin::Create_function<PrintTransactionMessageFunction>("print_transaction_message");
 
414
    registry.add(print_transaction_message_func_factory);
 
415
 
 
416
    hexdump_transaction_message_func_factory=
 
417
      new plugin::Create_function<HexdumpTransactionMessageFunction>("hexdump_transaction_message");
 
418
    registry.add(hexdump_transaction_message_func_factory);
 
419
 
 
420
    /* Create and initialize the transaction log index */
 
421
    transaction_log_index= new (nothrow) TransactionLogIndex(*transaction_log);
 
422
    if (transaction_log_index == NULL)
 
423
    {
 
424
      errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to allocate the TransactionLogIndex instance.  Got error: %s\n"), 
 
425
                    strerror(errno));
 
426
      return 1;
 
427
    }
 
428
    else
 
429
    {
 
430
      /* Check to see if the index was not created properly */
 
431
      if (transaction_log_index->hasError())
 
432
      {
 
433
        errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize the Transaction Log Index.  Got error: %s\n"), 
 
434
                      transaction_log_index->getErrorMessage().c_str());
 
435
        return 1;
 
436
      }
 
437
    }
 
438
 
 
439
    /* 
 
440
     * Setup the background worker thread which maintains
 
441
     * summary information about the transaction log.
 
442
     */
 
443
    if (initTransactionLogBackgroundWorker())
 
444
      return 1; /* Error message output handled in function above */
312
445
  }
313
446
  return 0;
314
447
}
315
448
 
316
449
static int deinit(drizzled::plugin::Registry &registry)
317
450
{
 
451
  /* Cleanup the transaction log itself */
318
452
  if (transaction_log)
319
453
  {
320
454
    registry.remove(transaction_log);
321
455
    delete transaction_log;
 
456
    delete transaction_log_index;
 
457
 
 
458
    /* Cleanup the INFORMATION_SCHEMA views */
 
459
    registry.remove(transaction_log_view);
 
460
    registry.remove(transaction_log_entries_view);
 
461
    registry.remove(transaction_log_transactions_view);
 
462
 
 
463
    cleanupViewMethods();
 
464
    cleanupViewColumns();
 
465
    cleanupViews();
 
466
 
 
467
    /* Cleanup module UDFs */
 
468
    registry.remove(print_transaction_message_func_factory);
 
469
    delete print_transaction_message_func_factory;
 
470
    registry.remove(hexdump_transaction_message_func_factory);
 
471
    delete hexdump_transaction_message_func_factory;
322
472
  }
 
473
 
323
474
  return 0;
324
475
}
325
476