maria_read_log.c 7.07 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* Copyright (C) 2007 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "maria_def.h"
unknown's avatar
unknown committed
17
#include "ma_recovery.h"
unknown's avatar
unknown committed
18 19 20 21 22 23 24 25
#include <my_getopt.h>

#define LOG_FLAGS 0
#define LOG_FILE_SIZE (1024L*1024L)

static const char *load_default_groups[]= { "maria_read_log",0 };
static void get_options(int *argc,char * * *argv);
#ifndef DBUG_OFF
26 27 28 29
#if defined(__WIN__)
const char *default_dbug_option= "d:t:i:O,\\maria_read_log.trace";
#else
const char *default_dbug_option= "d:t:i:o,/tmp/maria_read_log.trace";
unknown's avatar
unknown committed
30
#endif
31
#endif /* DBUG_OFF */
unknown's avatar
unknown committed
32 33
static my_bool opt_only_display, opt_apply, opt_apply_undo, opt_silent,
  opt_check;
34
static ulong opt_page_buffer_size;
unknown's avatar
unknown committed
35 36 37 38 39

int main(int argc, char **argv)
{
  LSN lsn;
  char **default_argv;
unknown's avatar
unknown committed
40
  uint warnings_count;
unknown's avatar
unknown committed
41 42 43 44 45 46 47
  MY_INIT(argv[0]);

  load_defaults("my", load_default_groups, &argc, &argv);
  default_argv= argv;
  get_options(&argc, &argv);

  maria_data_root= ".";
unknown's avatar
unknown committed
48
  maria_in_recovery= TRUE;
unknown's avatar
unknown committed
49 50 51 52 53 54 55

  if (maria_init())
  {
    fprintf(stderr, "Can't init Maria engine (%d)\n", errno);
    goto err;
  }
  /* we don't want to create a control file, it MUST exist */
unknown's avatar
unknown committed
56
  if (ma_control_file_create_or_open())
unknown's avatar
unknown committed
57 58 59 60 61 62 63 64 65
  {
    fprintf(stderr, "Can't open control file (%d)\n", errno);
    goto err;
  }
  if (last_logno == FILENO_IMPOSSIBLE)
  {
    fprintf(stderr, "Can't find any log\n");
    goto err;
  }
unknown's avatar
unknown committed
66 67
  /* same page cache for log and data; assumes same page size... */
  DBUG_ASSERT(maria_block_size == TRANSLOG_PAGE_SIZE);
68
  if (init_pagecache(maria_pagecache, opt_page_buffer_size, 0, 0,
unknown's avatar
unknown committed
69 70 71 72 73 74 75 76 77 78 79
                     TRANSLOG_PAGE_SIZE) == 0)
  {
    fprintf(stderr, "Got error in init_pagecache() (errno: %d)\n", errno);
    goto err;
  }
  /*
    If log handler does not find the "last_logno" log it will return error,
    which is good.
    But if it finds a log and this log was crashed, it will create a new log,
    which is useless. TODO: start log handler in read-only mode.
  */
80
  if (translog_init(".", LOG_FILE_SIZE, 50112, 0, maria_pagecache,
unknown's avatar
unknown committed
81 82 83 84 85 86 87 88 89
                    TRANSLOG_DEFAULT_FLAGS))
  {
    fprintf(stderr, "Can't init loghandler (%d)\n", errno);
    goto err;
  }

  if (opt_only_display)
    printf("You are using --only-display, NOTHING will be written to disk\n");

90
  /* LSN could be also --start-from-lsn=# */
unknown's avatar
unknown committed
91 92 93 94 95 96 97 98 99 100 101 102
  lsn= translog_first_lsn_in_log();
  if (lsn == LSN_ERROR)
  {
    fprintf(stderr, "Opening transaction log failed\n");
    goto end;
  }
  if (lsn == LSN_IMPOSSIBLE)
  {
     fprintf(stdout, "The transaction log is empty\n");
  }
  fprintf(stdout, "The transaction log starts from lsn (%lu,0x%lx)\n",
          LSN_IN_PARTS(lsn));
unknown's avatar
unknown committed
103

unknown's avatar
unknown committed
104
  fprintf(stdout, "TRACE of the last maria_read_log\n");
unknown's avatar
unknown committed
105 106 107
  if (maria_apply_log(lsn, opt_apply ?  MARIA_LOG_APPLY :
                      (opt_check ? MARIA_LOG_CHECK :
                       MARIA_LOG_DISPLAY_HEADER), opt_silent ? NULL : stdout,
unknown's avatar
unknown committed
108
                      opt_apply_undo, FALSE, FALSE, &warnings_count))
unknown's avatar
unknown committed
109
    goto err;
unknown's avatar
unknown committed
110 111 112 113 114
  if (warnings_count == 0)
    fprintf(stdout, "%s: SUCCESS\n", my_progname_short);
  else
    fprintf(stdout, "%s: DOUBTFUL (%u warnings, check previous output)\n",
            my_progname_short, warnings_count);
unknown's avatar
unknown committed
115 116 117 118

  goto end;
err:
  /* don't touch anything more, in case we hit a bug */
unknown's avatar
unknown committed
119
  fprintf(stderr, "%s: FAILED\n", my_progname_short);
unknown's avatar
unknown committed
120 121
  exit(1);
end:
unknown's avatar
unknown committed
122
  maria_end();
unknown's avatar
unknown committed
123 124 125 126 127 128 129
  free_defaults(default_argv);
  my_end(0);
  exit(0);
  return 0;				/* No compiler warning */
}


unknown's avatar
unknown committed
130 131 132
#include "ma_check_standalone.h"


unknown's avatar
unknown committed
133 134
static struct my_option my_long_options[] =
{
135
  {"apply", 'a',
unknown's avatar
unknown committed
136 137
   "Apply log to tables: modifies tables! you should make a backup first! "
   " Displays a lot of information if not run with --silent",
138 139
   (uchar **) &opt_apply, (uchar **) &opt_apply, 0,
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
140 141 142 143
  {"check", 'c',
   "if --only-display, check if record is fully readable (for debugging)",
   (uchar **) &opt_check, (uchar **) &opt_check, 0,
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
144 145 146 147
#ifndef DBUG_OFF
  {"debug", '#', "Output debug log. Often the argument is 'd:t:o,filename'.",
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
148 149
  {"help", '?', "Display this help and exit.",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
150
  {"only-display", 'o', "display brief info read from records' header",
151 152
   (uchar **) &opt_only_display, (uchar **) &opt_only_display, 0, GET_BOOL,
   NO_ARG,0, 0, 0, 0, 0, 0},
153 154 155 156 157 158 159
  { "page_buffer_size", 'P', "",
    (uchar**) &opt_page_buffer_size, (uchar**) &opt_page_buffer_size, 0,
    GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT,
    (long) MALLOC_OVERHEAD, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD,
    (long) IO_SIZE, 0},
  {"silent", 's', "Print less information during apply/undo phase",
   (uchar **) &opt_silent, (uchar **) &opt_silent, 0,
unknown's avatar
unknown committed
160
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
161
  {"undo", 'u', "Apply UNDO records to tables. (disable with --disable-undo)",
162 163 164 165
   (uchar **) &opt_apply_undo, (uchar **) &opt_apply_undo, 0,
   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
  {"version", 'V', "Print version and exit.",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
166 167 168 169 170 171 172
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};

#include <help_start.h>

static void print_version(void)
{
173
  VOID(printf("%s Ver 1.1 for %s on %s\n",
unknown's avatar
unknown committed
174
              my_progname_short, SYSTEM_TYPE, MACHINE_TYPE));
unknown's avatar
unknown committed
175 176 177 178 179 180 181 182 183 184 185 186 187
  NETWARE_SET_SCREEN_MODE(1);
}


static void usage(void)
{
  print_version();
  puts("Copyright (C) 2007 MySQL AB");
  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
  puts("and you are welcome to modify and redistribute it under the GPL license\n");

  puts("Display and apply log records from a MARIA transaction log");
  puts("found in the current directory (for now)");
unknown's avatar
unknown committed
188
  VOID(printf("\nUsage: %s OPTIONS\n", my_progname_short));
unknown's avatar
unknown committed
189 190 191 192 193 194 195 196 197 198 199 200 201
  puts("You need to use one of -o or -a");
  my_print_help(my_long_options);
  print_defaults("my", load_default_groups);
  my_print_variables(my_long_options);
}

#include <help_end.h>

static my_bool
get_one_option(int optid __attribute__((unused)),
               const struct my_option *opt __attribute__((unused)),
               char *argument __attribute__((unused)))
{
202
  switch (optid) {
203 204 205
  case '?':
    usage();
    exit(0);
206 207 208
  case 'V':
    print_version();
    exit(0);
209 210 211 212 213
#ifndef DBUG_OFF
  case '#':
    DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
    break;
#endif
unknown's avatar
unknown committed
214
  }
unknown's avatar
unknown committed
215 216 217 218 219 220 221 222 223 224
  return 0;
}

static void get_options(int *argc,char ***argv)
{
  int ho_error;

  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
    exit(ho_error);

unknown's avatar
unknown committed
225 226
  if (!opt_apply)
    opt_apply_undo= FALSE;
227 228

  if ((opt_only_display + opt_apply) != 1)
unknown's avatar
unknown committed
229 230 231 232 233
  {
    usage();
    exit(1);
  }
}