~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* Describe, check and repair of MyISAM tables */
17
685.1.3 by Monty Taylor
Turned off stdinc - and then fixed the carnage.
18
#include "myisamdef.h"
19
#include "myisam.h"
1 by brian
clean slate
20
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
21
#include <mystrings/m_ctype.h>
212.5.21 by Monty Taylor
Moved my_getopt.h
22
#include <mysys/my_getopt.h>
212.5.28 by Monty Taylor
Moved my_bit and my_list
23
#include <mysys/my_bit.h>
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
24
#include <mystrings/m_string.h>
685.1.3 by Monty Taylor
Turned off stdinc - and then fixed the carnage.
25
#include <stdio.h>
26
#include <stdarg.h>
1 by brian
clean slate
27
#ifdef HAVE_SYS_VADVICE_H
28
#include <sys/vadvise.h>
29
#endif
30
#ifdef HAVE_SYS_MMAN_H
31
#include <sys/mman.h>
32
#endif
492.1.7 by Monty Taylor
Moved test() to its own file.
33
#include <drizzled/util/test.h>
34
1 by brian
clean slate
35
598 by Brian Aker
Removed mutex which are myisam from global to just engine.
36
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
37
482 by Brian Aker
Remove uint.
38
static uint32_t decode_bits;
1 by brian
clean slate
39
static char **default_argv;
40
static const char *load_default_groups[]= { "myisamchk", 0 };
41
static const char *set_collation_name, *opt_tmpdir;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
42
static const CHARSET_INFO *set_collation;
1 by brian
clean slate
43
static long opt_myisam_block_size;
44
static long opt_key_cache_block_size;
45
static const char *my_progname_short;
46
47
static const char *type_names[]=
48
{ "impossible","char","binary", "short", "long", "float",
49
  "double","number","unsigned short",
152 by Brian Aker
longlong replacement
50
  "unsigned long","int64_t","uint64_t","int24",
1 by brian
clean slate
51
  "uint24","int8","varchar", "varbin","?",
52
  "?"};
53
54
static const char *prefix_packed_txt="packed ",
55
		  *bin_packed_txt="prefix ",
56
		  *diff_txt="stripped ",
57
		  *null_txt="NULL",
58
		  *blob_txt="BLOB ";
59
60
static const char *field_pack[]=
61
{"","no endspace", "no prespace",
62
 "no zeros", "blob", "constant", "table-lockup",
63
 "always zero","varchar","unique-hash","?","?"};
64
65
static const char *myisam_stats_method_str="nulls_unequal";
66
67
static void get_options(int *argc,char * * *argv);
68
static void print_version(void);
69
static void usage(void);
70
static int myisamchk(MI_CHECK *param, char *filename);
71
static void descript(MI_CHECK *param, register MI_INFO *info, char * name);
72
static int mi_sort_records(MI_CHECK *param, register MI_INFO *info,
482 by Brian Aker
Remove uint.
73
                           char * name, uint32_t sort_key,
281 by Brian Aker
Converted myisam away from my_bool
74
			   bool write_info, bool update_index);
1 by brian
clean slate
75
static int sort_record_index(MI_SORT_PARAM *sort_param, MI_INFO *info,
76
                             MI_KEYDEF *keyinfo,
482 by Brian Aker
Remove uint.
77
			     my_off_t page,unsigned char *buff,uint32_t sortkey,
281 by Brian Aker
Converted myisam away from my_bool
78
			     File new_file, bool update_index);
1 by brian
clean slate
79
80
MI_CHECK check_param;
81
82
	/* Main program */
83
84
int main(int argc, char **argv)
85
{
86
  int error;
87
  MY_INIT(argv[0]);
88
  my_progname_short= my_progname+dirname_length(my_progname);
89
90
  myisamchk_init(&check_param);
91
  check_param.opt_lock_memory=1;		/* Lock memory if possible */
92
  check_param.using_global_keycache = 0;
93
  get_options(&argc,(char***) &argv);
94
  myisam_quick_table_bits=decode_bits;
95
  error=0;
96
  while (--argc >= 0)
97
  {
98
    int new_error=myisamchk(&check_param, *(argv++));
99
    if ((check_param.testflag & T_REP_ANY) != T_REP)
100
      check_param.testflag&= ~T_REP;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
101
    fflush(stdout);
102
    fflush(stderr);
1 by brian
clean slate
103
    if ((check_param.error_printed | check_param.warning_printed) &&
104
	(check_param.testflag & T_FORCE_CREATE) &&
105
	(!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
106
				   T_SORT_INDEX))))
107
    {
482 by Brian Aker
Remove uint.
108
      uint32_t old_testflag=check_param.testflag;
1 by brian
clean slate
109
      if (!(check_param.testflag & T_REP))
110
	check_param.testflag|= T_REP_BY_SORT;
111
      check_param.testflag&= ~T_EXTEND;			/* Don't needed  */
112
      error|=myisamchk(&check_param, argv[-1]);
113
      check_param.testflag= old_testflag;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
114
      fflush(stdout);
115
      fflush(stderr);
1 by brian
clean slate
116
    }
117
    else
118
      error|=new_error;
119
    if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO))
120
    {
121
      puts("\n---------\n");
398.1.10 by Monty Taylor
Actually removed VOID() this time.
122
      fflush(stdout);
1 by brian
clean slate
123
    }
124
  }
125
  if (check_param.total_files > 1)
126
  {					/* Only if descript */
127
    char buff[22],buff2[22];
128
    if (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO)
129
      puts("\n---------\n");
130
    printf("\nTotal of all %d MyISAM-files:\nData records: %9s   Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff),
131
	   llstr(check_param.total_deleted,buff2));
132
  }
598 by Brian Aker
Removed mutex which are myisam from global to just engine.
133
134
  pthread_mutex_destroy(&THR_LOCK_myisam);
135
1 by brian
clean slate
136
  free_defaults(default_argv);
137
  my_end(check_param.testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
138
  exit(error);
139
#ifndef _lint
140
  return 0;				/* No compiler warning */
141
#endif
142
} /* main */
143
144
enum options_mc {
145
  OPT_CHARSETS_DIR=256, OPT_SET_COLLATION,OPT_START_CHECK_POS,
146
  OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE,
147
  OPT_KEY_CACHE_BLOCK_SIZE, OPT_MYISAM_BLOCK_SIZE,
148
  OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
160.1.2 by mark
remove FTPARSER and last remains of full text search
149
  OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS,
1 by brian
clean slate
150
  OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD
151
};
152
153
static struct my_option my_long_options[] =
154
{
155
  {"analyze", 'a',
156
   "Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.",
157
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
158
  {"block-search", 'b',
159
   "No help available.",
160
   0, 0, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
161
  {"backup", 'B',
162
   "Make a backup of the .MYD file as 'filename-time.BAK'.",
163
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
164
  {"character-sets-dir", OPT_CHARSETS_DIR,
165
   "Directory where character sets are.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
166
   (char**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
167
  {"check", 'c',
168
   "Check table for errors.",
169
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
170
  {"check-only-changed", 'C',
171
   "Check only tables that have changed since last check. It also applies to other requested actions (e.g. --analyze will be ignored if the table is already analyzed).",
172
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
173
  {"correct-checksum", OPT_CORRECT_CHECKSUM,
174
   "Correct checksum information for table.",
175
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
176
  {"description", 'd',
177
   "Prints some information about table.",
178
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
179
  {"data-file-length", 'D',
180
   "Max length of data file (when recreating data-file when it's full).",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
181
   (char**) &check_param.max_data_file_length,
182
   (char**) &check_param.max_data_file_length,
1 by brian
clean slate
183
   0, GET_LL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
184
  {"extend-check", 'e',
185
   "If used when checking a table, ensure that the table is 100 percent consistent, which will take a long time. If used when repairing a table, try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option with repair if you are not totally desperate.",
186
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
187
  {"fast", 'F',
188
   "Check only tables that haven't been closed properly. It also applies to other requested actions (e.g. --analyze will be ignored if the table is already analyzed).",
189
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
190
  {"force", 'f',
191
   "Restart with -r if there are any errors in the table. States will be updated as with --update-state.",
192
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
193
  {"HELP", 'H',
194
   "Display this help and exit.",
195
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
196
  {"help", '?',
197
   "Display this help and exit.",
198
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
199
  {"information", 'i',
200
   "Print statistics information about table that is checked.",
201
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
202
  {"keys-used", 'k',
203
   "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
204
   (char**) &check_param.keys_in_use,
205
   (char**) &check_param.keys_in_use,
1 by brian
clean slate
206
   0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0},
207
  {"max-record-length", OPT_MAX_RECORD_LENGTH,
208
   "Skip rows bigger than this if myisamchk can't allocate memory to hold it",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
209
   (char**) &check_param.max_record_length,
210
   (char**) &check_param.max_record_length,
163 by Brian Aker
Merge Monty's code.
211
   0, GET_ULL, REQUIRED_ARG, INT64_MAX, 0, INT64_MAX, 0, 0, 0},
1 by brian
clean slate
212
  {"medium-check", 'm',
213
   "Faster than extend-check, but only finds 99.99% of all errors. Should be good enough for most cases.",
214
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
215
  {"quick", 'q', "Faster repair by not modifying the data file.",
216
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
217
  {"read-only", 'T',
218
   "Don't mark table as checked.",
219
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
220
  {"recover", 'r',
221
   "Can fix almost anything except unique keys that aren't unique.",
222
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
223
  {"parallel-recover", 'p',
224
   "Same as '-r' but creates all the keys in parallel.",
225
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
226
  {"safe-recover", 'o',
227
   "Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file.",
228
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
229
  {"sort-recover", 'n',
230
   "Force recovering with sorting even if the temporary file was very big.",
231
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
232
#ifdef DEBUG
233
  {"start-check-pos", OPT_START_CHECK_POS,
234
   "No help available.",
235
   0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
236
#endif
237
  {"set-auto-increment", 'A',
238
   "Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
239
   (char**) &check_param.auto_increment_value,
240
   (char**) &check_param.auto_increment_value,
1 by brian
clean slate
241
   0, GET_ULL, OPT_ARG, 0, 0, 0, 0, 0, 0},
242
  {"set-collation", OPT_SET_COLLATION,
243
   "Change the collation used by the index",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
244
   (char**) &set_collation_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1 by brian
clean slate
245
  {"set-variable", 'O',
246
   "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
247
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
248
  {"silent", 's',
249
   "Only print errors. One can use two -s to make myisamchk very silent.",
250
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
251
  {"sort-index", 'S',
252
   "Sort index blocks. This speeds up 'read-next' in applications.",
253
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
254
  {"sort-records", 'R',
255
   "Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!)",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
256
   (char**) &check_param.opt_sort_key,
257
   (char**) &check_param.opt_sort_key,
1 by brian
clean slate
258
   0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
259
  {"tmpdir", 't',
260
   "Path for temporary files.",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
261
   (char**) &opt_tmpdir,
1 by brian
clean slate
262
   0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
263
  {"update-state", 'U',
264
   "Mark tables as crashed if any errors were found.",
265
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
266
  {"unpack", 'u',
267
   "Unpack file packed with myisampack.",
268
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
269
  {"verbose", 'v',
270
   "Print more information. This can be used with --description and --check. Use many -v for more verbosity!",
271
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
272
  {"version", 'V',
273
   "Print version and exit.",
274
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
275
  {"wait", 'w',
276
   "Wait if table is locked.",
277
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
278
  { "key_buffer_size", OPT_KEY_BUFFER_SIZE, "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
279
    (char**) &check_param.use_buffers, (char**) &check_param.use_buffers, 0,
1 by brian
clean slate
280
    GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
365.2.8 by Monty Taylor
More MAX macros.
281
    INT32_MAX, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
1 by brian
clean slate
282
  { "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,  "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
283
    (char**) &opt_key_cache_block_size,
284
    (char**) &opt_key_cache_block_size, 0,
1 by brian
clean slate
285
    GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
286
    MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
287
  { "myisam_block_size", OPT_MYISAM_BLOCK_SIZE,  "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
288
    (char**) &opt_myisam_block_size, (char**) &opt_myisam_block_size, 0,
1 by brian
clean slate
289
    GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
290
    MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
291
  { "read_buffer_size", OPT_READ_BUFFER_SIZE, "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
292
    (char**) &check_param.read_buffer_length,
293
    (char**) &check_param.read_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
1 by brian
clean slate
294
    (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
365.2.8 by Monty Taylor
More MAX macros.
295
    INT32_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
1 by brian
clean slate
296
  { "write_buffer_size", OPT_WRITE_BUFFER_SIZE, "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
297
    (char**) &check_param.write_buffer_length,
298
    (char**) &check_param.write_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
1 by brian
clean slate
299
    (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
365.2.8 by Monty Taylor
More MAX macros.
300
    INT32_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
1 by brian
clean slate
301
  { "sort_buffer_size", OPT_SORT_BUFFER_SIZE, "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
302
    (char**) &check_param.sort_buffer_length,
303
    (char**) &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
1 by brian
clean slate
304
    (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD),
365.2.8 by Monty Taylor
More MAX macros.
305
    INT32_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
1 by brian
clean slate
306
  { "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
307
    (char**) &check_param.sort_key_blocks,
308
    (char**) &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG,
1 by brian
clean slate
309
    BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
310
  { "decode_bits", OPT_DECODE_BITS, "", (char**) &decode_bits,
311
    (char**) &decode_bits, 0, GET_UINT, REQUIRED_ARG, 9L, 4L, 17L, 0L, 1L, 0},
1 by brian
clean slate
312
  {"stats_method", OPT_STATS_METHOD,
313
   "Specifies how index statistics collection code should treat NULLs. "
314
   "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), "
315
   "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".",
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
316
   (char**) &myisam_stats_method_str, (char**) &myisam_stats_method_str, 0,
1 by brian
clean slate
317
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
318
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
319
};
320
321
322
static void print_version(void)
323
{
324
  printf("%s  Ver 2.7 for %s at %s\n", my_progname, SYSTEM_TYPE,
325
	 MACHINE_TYPE);
326
}
327
328
329
static void usage(void)
330
{
331
  print_version();
332
  puts("By Monty, for your professional use");
333
  puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
334
  puts("Description, check and repair of MyISAM tables.");
335
  puts("Used without options all tables on the command will be checked for errors");
336
  printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname_short);
337
  printf("\nGlobal options:\n");
338
  printf("\
339
  -?, --help          Display this help and exit.\n\
340
  -O, --set-variable var=option.\n\
341
                      Change the value of a variable. Please note that\n\
342
                      this option is deprecated; you can set variables\n\
343
                      directly with '--variable-name=value'.\n\
344
  -t, --tmpdir=path   Path for temporary files. Multiple paths can be\n\
345
                      specified, separated by ");
206.2.1 by Jay Pipes
* Removed two files, only needed for Netware:
346
#if defined( __WIN__)
1 by brian
clean slate
347
   printf("semicolon (;)");
348
#else
349
   printf("colon (:)");
350
#endif
351
                      printf(", they will be used\n\
352
                      in a round-robin fashion.\n\
353
  -s, --silent	      Only print errors.  One can use two -s to make\n\
354
		      myisamchk very silent.\n\
355
  -v, --verbose       Print more information. This can be used with\n\
356
                      --description and --check. Use many -v for more verbosity.\n\
357
  -V, --version       Print version and exit.\n\
358
  -w, --wait          Wait if table is locked.\n\n");
359
#ifdef DEBUG
360
  puts("  --start-check-pos=# Start reading file at given offset.\n");
361
#endif
362
363
  puts("Check options (check is the default action for myisamchk):\n\
364
  -c, --check	      Check table for errors.\n\
365
  -e, --extend-check  Check the table VERY throughly.  Only use this in\n\
366
                      extreme cases as myisamchk should normally be able to\n\
367
                      find out if the table is ok even without this switch.\n\
368
  -F, --fast	      Check only tables that haven't been closed properly.\n\
369
  -C, --check-only-changed\n\
370
		      Check only tables that have changed since last check.\n\
371
  -f, --force         Restart with '-r' if there are any errors in the table.\n\
372
		      States will be updated as with '--update-state'.\n\
373
  -i, --information   Print statistics information about table that is checked.\n\
374
  -m, --medium-check  Faster than extend-check, but only finds 99.99% of\n\
375
		      all errors.  Should be good enough for most cases.\n\
376
  -U  --update-state  Mark tables as crashed if you find any errors.\n\
377
  -T, --read-only     Don't mark table as checked.\n");
378
379
  puts("Repair options (When using '-r' or '-o'):\n\
380
  -B, --backup	      Make a backup of the .MYD file as 'filename-time.BAK'.\n\
381
  --correct-checksum  Correct checksum information for table.\n\
382
  -D, --data-file-length=#  Max length of data file (when recreating data\n\
383
                      file when it's full).\n\
384
  -e, --extend-check  Try to recover every possible row from the data file\n\
385
		      Normally this will also find a lot of garbage rows;\n\
386
		      Don't use this option if you are not totally desperate.\n\
387
  -f, --force         Overwrite old temporary files.\n\
388
  -k, --keys-used=#   Tell MyISAM to update only some specific keys. # is a\n\
389
	              bit mask of which keys to use. This can be used to\n\
390
		      get faster inserts.\n\
391
  --max-record-length=#\n\
392
                      Skip rows bigger than this if myisamchk can't allocate\n\
393
		      memory to hold it.\n\
394
  -r, --recover       Can fix almost anything except unique keys that aren't\n\
395
                      unique.\n\
396
  -n, --sort-recover  Forces recovering with sorting even if the temporary\n\
397
		      file would be very big.\n\
398
  -p, --parallel-recover\n\
399
                      Uses the same technique as '-r' and '-n', but creates\n\
400
                      all the keys in parallel, in different threads.\n\
401
  -o, --safe-recover  Uses old recovery method; Slower than '-r' but can\n\
402
		      handle a couple of cases where '-r' reports that it\n\
403
		      can't fix the data file.\n\
404
  --character-sets-dir=...\n\
405
                      Directory where character sets are.\n\
406
  --set-collation=name\n\
407
 		      Change the collation used by the index.\n\
408
  -q, --quick         Faster repair by not modifying the data file.\n\
409
                      One can give a second '-q' to force myisamchk to\n\
410
		      modify the original datafile in case of duplicate keys.\n\
411
		      NOTE: Tables where the data file is currupted can't be\n\
412
		      fixed with this option.\n\
413
  -u, --unpack        Unpack file packed with myisampack.\n\
414
");
415
416
  puts("Other actions:\n\
417
  -a, --analyze	      Analyze distribution of keys. Will make some joins in\n\
418
		      MySQL faster.  You can check the calculated distribution\n\
419
		      by using '--description --verbose table_name'.\n\
420
  --stats_method=name Specifies how index statistics collection code should\n\
421
                      treat NULLs. Possible values of name are \"nulls_unequal\"\n\
422
                      (default for 4.1/5.0), \"nulls_equal\" (emulate 4.0), and \n\
423
                      \"nulls_ignored\".\n\
424
  -d, --description   Prints some information about table.\n\
425
  -A, --set-auto-increment[=value]\n\
426
		      Force auto_increment to start at this or higher value\n\
427
		      If no value is given, then sets the next auto_increment\n\
428
		      value to the highest used value for the auto key + 1.\n\
429
  -S, --sort-index    Sort index blocks.  This speeds up 'read-next' in\n\
430
		      applications.\n\
431
  -R, --sort-records=#\n\
432
		      Sort records according to an index.  This makes your\n\
433
		      data much more localized and may speed up things\n\
434
		      (It may be VERY slow to do a sort the first time!).\n\
435
  -b,  --block-search=#\n\
436
                       Find a record, a block at given offset belongs to.");
437
520.4.28 by Monty Taylor
Changed my.cnf to drizzle.cnf and /etc/mysql to /etc/drizzle.
438
  print_defaults("drizzle", load_default_groups);
1 by brian
clean slate
439
  my_print_variables(my_long_options);
440
}
441
442
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
461 by Monty Taylor
Removed NullS. bu-bye.
443
                                           "nulls_ignored", NULL};
1 by brian
clean slate
444
TYPELIB myisam_stats_method_typelib= {
445
  array_elements(myisam_stats_method_names) - 1, "",
446
  myisam_stats_method_names, NULL};
447
448
	 /* Read options */
449
147 by Brian Aker
More my_bool conversion. This time the set_var class.
450
static bool
1 by brian
clean slate
451
get_one_option(int optid,
452
	       const struct my_option *opt __attribute__((unused)),
453
	       char *argument)
454
{
455
  switch (optid) {
456
  case 'a':
457
    if (argument == disabled_my_option)
458
      check_param.testflag&= ~T_STATISTICS;
459
    else
460
      check_param.testflag|= T_STATISTICS;
461
    break;
462
  case 'A':
463
    if (argument)
464
      check_param.auto_increment_value= strtoull(argument, NULL, 0);
465
    else
466
      check_param.auto_increment_value= 0;	/* Set to max used value */
467
    check_param.testflag|= T_AUTO_INC;
468
    break;
469
  case 'b':
470
    check_param.search_after_block= strtoul(argument, NULL, 10);
471
    break;
472
  case 'B':
473
    if (argument == disabled_my_option)
474
      check_param.testflag&= ~T_BACKUP_DATA;
475
    else
476
      check_param.testflag|= T_BACKUP_DATA;
477
    break;
478
  case 'c':
479
    if (argument == disabled_my_option)
480
      check_param.testflag&= ~T_CHECK;
481
    else
482
      check_param.testflag|= T_CHECK;
483
    break;
484
  case 'C':
485
    if (argument == disabled_my_option)
486
      check_param.testflag&= ~(T_CHECK | T_CHECK_ONLY_CHANGED);
487
    else
488
      check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED;
489
    break;
490
  case 'D':
491
    check_param.max_data_file_length=strtoll(argument, NULL, 10);
492
    break;
493
  case 's':				/* silent */
494
    if (argument == disabled_my_option)
495
      check_param.testflag&= ~(T_SILENT | T_VERY_SILENT);
496
    else
497
    {
498
      if (check_param.testflag & T_SILENT)
499
	check_param.testflag|= T_VERY_SILENT;
500
      check_param.testflag|= T_SILENT;
501
      check_param.testflag&= ~T_WRITE_LOOP;
502
    }
503
    break;
504
  case 'w':
505
    if (argument == disabled_my_option)
506
      check_param.testflag&= ~T_WAIT_FOREVER;
507
    else
508
      check_param.testflag|= T_WAIT_FOREVER;
509
    break;
510
  case 'd':				/* description if isam-file */
511
    if (argument == disabled_my_option)
512
      check_param.testflag&= ~T_DESCRIPT;
513
    else
514
      check_param.testflag|= T_DESCRIPT;
515
    break;
516
  case 'e':				/* extend check */
517
    if (argument == disabled_my_option)
518
      check_param.testflag&= ~T_EXTEND;
519
    else
520
      check_param.testflag|= T_EXTEND;
521
    break;
522
  case 'i':
523
    if (argument == disabled_my_option)
524
      check_param.testflag&= ~T_INFO;
525
    else
526
      check_param.testflag|= T_INFO;
527
    break;
528
  case 'f':
529
    if (argument == disabled_my_option)
530
    {
531
      check_param.tmpfile_createflag= O_RDWR | O_TRUNC | O_EXCL;
532
      check_param.testflag&= ~(T_FORCE_CREATE | T_UPDATE_STATE);
533
    }
534
    else
535
    {
536
      check_param.tmpfile_createflag= O_RDWR | O_TRUNC;
537
      check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE;
538
    }
539
    break;
540
  case 'F':
541
    if (argument == disabled_my_option)
542
      check_param.testflag&= ~T_FAST;
543
    else
544
      check_param.testflag|= T_FAST;
545
    break;
546
  case 'k':
151 by Brian Aker
Ulonglong to uint64_t
547
    check_param.keys_in_use= (uint64_t) strtoll(argument, NULL, 10);
1 by brian
clean slate
548
    break;
549
  case 'm':
550
    if (argument == disabled_my_option)
551
      check_param.testflag&= ~T_MEDIUM;
552
    else
553
      check_param.testflag|= T_MEDIUM;		/* Medium check */
554
    break;
555
  case 'r':				/* Repair table */
556
    check_param.testflag&= ~T_REP_ANY;
557
    if (argument != disabled_my_option)
558
      check_param.testflag|= T_REP_BY_SORT;
559
    break;
560
  case 'p':
561
    check_param.testflag&= ~T_REP_ANY;
562
    if (argument != disabled_my_option)
563
      check_param.testflag|= T_REP_PARALLEL;
564
    break;
565
  case 'o':
566
    check_param.testflag&= ~T_REP_ANY;
567
    check_param.force_sort= 0;
568
    if (argument != disabled_my_option)
569
    {
570
      check_param.testflag|= T_REP;
571
      my_disable_async_io= 1;		/* More safety */
572
    }
573
    break;
574
  case 'n':
575
    check_param.testflag&= ~T_REP_ANY;
576
    if (argument == disabled_my_option)
577
      check_param.force_sort= 0;
578
    else
579
    {
580
      check_param.testflag|= T_REP_BY_SORT;
581
      check_param.force_sort= 1;
582
    }
583
    break;
584
  case 'q':
585
    if (argument == disabled_my_option)
586
      check_param.testflag&= ~(T_QUICK | T_FORCE_UNIQUENESS);
587
    else
588
      check_param.testflag|=
589
        (check_param.testflag & T_QUICK) ? T_FORCE_UNIQUENESS : T_QUICK;
590
    break;
591
  case 'u':
592
    if (argument == disabled_my_option)
593
      check_param.testflag&= ~(T_UNPACK | T_REP_BY_SORT);
594
    else
595
      check_param.testflag|= T_UNPACK | T_REP_BY_SORT;
596
    break;
597
  case 'v':				/* Verbose */
598
    if (argument == disabled_my_option)
599
    {
600
      check_param.testflag&= ~T_VERBOSE;
601
      check_param.verbose=0;
602
    }
603
    else
604
    {
605
      check_param.testflag|= T_VERBOSE;
606
      check_param.verbose++;
607
    }
608
    break;
609
  case 'R':				/* Sort records */
610
    if (argument == disabled_my_option)
611
      check_param.testflag&= ~T_SORT_RECORDS;
612
    else
613
    {
614
      check_param.testflag|= T_SORT_RECORDS;
615
      check_param.opt_sort_key= (uint) atoi(argument) - 1;
616
      if (check_param.opt_sort_key >= MI_MAX_KEY)
617
      {
618
	fprintf(stderr,
619
		"The value of the sort key is bigger than max key: %d.\n",
620
		MI_MAX_KEY);
621
	exit(1);
622
      }
623
    }
624
    break;
625
  case 'S':			      /* Sort index */
626
    if (argument == disabled_my_option)
627
      check_param.testflag&= ~T_SORT_INDEX;
628
    else
629
      check_param.testflag|= T_SORT_INDEX;
630
    break;
631
  case 'T':
632
    if (argument == disabled_my_option)
633
      check_param.testflag&= ~T_READONLY;
634
    else
635
      check_param.testflag|= T_READONLY;
636
    break;
637
  case 'U':
638
    if (argument == disabled_my_option)
639
      check_param.testflag&= ~T_UPDATE_STATE;
640
    else
641
      check_param.testflag|= T_UPDATE_STATE;
642
    break;
643
  case 'V':
644
    print_version();
645
    exit(0);
646
  case OPT_CORRECT_CHECKSUM:
647
    if (argument == disabled_my_option)
648
      check_param.testflag&= ~T_CALC_CHECKSUM;
649
    else
650
      check_param.testflag|= T_CALC_CHECKSUM;
651
    break;
652
  case OPT_STATS_METHOD:
653
  {
654
    int method;
655
    enum_mi_stats_method method_conv;
656
    myisam_stats_method_str= argument;
657
    if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
658
    {
659
      fprintf(stderr, "Invalid value of stats_method: %s.\n", argument);
660
      exit(1);
661
    }
662
    switch (method-1) {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
663
    case 0:
1 by brian
clean slate
664
      method_conv= MI_STATS_METHOD_NULLS_EQUAL;
665
      break;
666
    case 1:
667
      method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL;
668
      break;
669
    case 2:
670
      method_conv= MI_STATS_METHOD_IGNORE_NULLS;
671
      break;
672
    default: assert(0);                         /* Impossible */
492.3.25 by Lee
Changes to get drizzle building on Solaris 10 (SPARC)
673
      fprintf(stderr, "Invalid value of stats_method: %s.\n", argument);
674
      exit(1);
1 by brian
clean slate
675
    }
676
    check_param.stats_method= method_conv;
677
    break;
678
  }
679
#ifdef DEBUG					/* Only useful if debugging */
680
  case OPT_START_CHECK_POS:
681
    check_param.start_check_pos= strtoull(argument, NULL, 0);
682
    break;
683
#endif
684
  case 'H':
685
    my_print_help(my_long_options);
686
    exit(0);
687
  case '?':
688
    usage();
689
    exit(0);
690
  }
691
  return 0;
692
}
693
694
695
static void get_options(register int *argc,register char ***argv)
696
{
697
  int ho_error;
698
520.4.28 by Monty Taylor
Changed my.cnf to drizzle.cnf and /etc/mysql to /etc/drizzle.
699
  load_defaults("drizzle", load_default_groups, argc, argv);
1 by brian
clean slate
700
  default_argv= *argv;
701
  if (isatty(fileno(stdout)))
702
    check_param.testflag|=T_WRITE_LOOP;
703
704
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
705
    exit(ho_error);
706
707
  /* If using repair, then update checksum if one uses --update-state */
708
  if ((check_param.testflag & T_UPDATE_STATE) &&
709
      (check_param.testflag & T_REP_ANY))
710
    check_param.testflag|= T_CALC_CHECKSUM;
711
712
  if (*argc == 0)
713
  {
714
    usage();
715
    exit(-1);
716
  }
717
718
  if ((check_param.testflag & T_UNPACK) &&
719
      (check_param.testflag & (T_QUICK | T_SORT_RECORDS)))
720
  {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
721
    fprintf(stderr,
722
            "%s: --unpack can't be used with --quick or --sort-records\n",
723
            my_progname_short);
1 by brian
clean slate
724
    exit(1);
725
  }
726
  if ((check_param.testflag & T_READONLY) &&
727
      (check_param.testflag &
728
       (T_REP_ANY | T_STATISTICS | T_AUTO_INC |
729
	T_SORT_RECORDS | T_SORT_INDEX | T_FORCE_CREATE)))
730
  {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
731
    fprintf(stderr,
732
            "%s: Can't use --readonly when repairing or sorting\n",
733
            my_progname_short);
1 by brian
clean slate
734
    exit(1);
735
  }
736
737
  check_param.key_cache_block_size= opt_key_cache_block_size;
738
739
  if (set_collation_name)
740
    if (!(set_collation= get_charset_by_name(set_collation_name,
741
                                             MYF(MY_WME))))
742
      exit(1);
743
744
  myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
745
  return;
746
} /* get options */
747
748
749
	/* Check table */
750
751
static int myisamchk(MI_CHECK *param, char * filename)
752
{
753
  int error,lock_type,recreate;
754
  int rep_quick= param->testflag & (T_QUICK | T_FORCE_UNIQUENESS);
482 by Brian Aker
Remove uint.
755
  uint32_t raid_chunks;
1 by brian
clean slate
756
  MI_INFO *info;
757
  File datafile;
758
  char llbuff[22],llbuff2[22];
281 by Brian Aker
Converted myisam away from my_bool
759
  bool state_updated=0;
1 by brian
clean slate
760
  MYISAM_SHARE *share;
761
762
  param->out_flag=error=param->warning_printed=param->error_printed=
763
    recreate=0;
764
  datafile=0;
765
  param->isam_file_name=filename;		/* For error messages */
766
  if (!(info=mi_open(filename,
767
		     (param->testflag & (T_DESCRIPT | T_READONLY)) ?
768
		     O_RDONLY : O_RDWR,
769
		     HA_OPEN_FOR_REPAIR |
770
		     ((param->testflag & T_WAIT_FOREVER) ?
771
		      HA_OPEN_WAIT_IF_LOCKED :
772
		      (param->testflag & T_DESCRIPT) ?
773
		      HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED))))
774
  {
775
    /* Avoid twice printing of isam file name */
776
    param->error_printed=1;
777
    switch (my_errno) {
778
    case HA_ERR_CRASHED:
779
      mi_check_print_error(param,"'%s' doesn't have a correct index definition. You need to recreate it before you can do a repair",filename);
780
      break;
781
    case HA_ERR_NOT_A_TABLE:
782
      mi_check_print_error(param,"'%s' is not a MyISAM-table",filename);
783
      break;
784
    case HA_ERR_CRASHED_ON_USAGE:
785
      mi_check_print_error(param,"'%s' is marked as crashed",filename);
786
      break;
787
    case HA_ERR_CRASHED_ON_REPAIR:
788
      mi_check_print_error(param,"'%s' is marked as crashed after last repair",filename);
789
      break;
790
    case HA_ERR_OLD_FILE:
791
      mi_check_print_error(param,"'%s' is a old type of MyISAM-table", filename);
792
      break;
793
    case HA_ERR_END_OF_FILE:
794
      mi_check_print_error(param,"Couldn't read complete header from '%s'", filename);
795
      break;
796
    case EAGAIN:
797
      mi_check_print_error(param,"'%s' is locked. Use -w to wait until unlocked",filename);
798
      break;
799
    case ENOENT:
800
      mi_check_print_error(param,"File '%s' doesn't exist",filename);
801
      break;
802
    case EACCES:
803
      mi_check_print_error(param,"You don't have permission to use '%s'",filename);
804
      break;
805
    default:
806
      mi_check_print_error(param,"%d when opening MyISAM-table '%s'",
807
		  my_errno,filename);
808
      break;
809
    }
51.1.116 by Jay Pipes
DBUG symbol removal
810
    return(1);
1 by brian
clean slate
811
  }
812
  share=info->s;
813
  share->options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */
814
  share->tot_locks-= share->r_locks;
815
  share->r_locks=0;
816
  raid_chunks=share->base.raid_chunks;
817
818
  /*
819
    Skip the checking of the file if:
820
    We are using --fast and the table is closed properly
821
    We are using --check-only-changed-tables and the table hasn't changed
822
  */
823
  if (param->testflag & (T_FAST | T_CHECK_ONLY_CHANGED))
824
  {
281 by Brian Aker
Converted myisam away from my_bool
825
    bool need_to_check= mi_is_crashed(info) || share->state.open_count != 0;
1 by brian
clean slate
826
827
    if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) &&
828
	((share->state.changed & (STATE_CHANGED | STATE_CRASHED |
829
				  STATE_CRASHED_ON_REPAIR) ||
830
	  !(param->testflag & T_CHECK_ONLY_CHANGED))))
831
      need_to_check=1;
832
833
    if (info->s->base.keys && info->state->records)
834
    {
835
      if ((param->testflag & T_STATISTICS) &&
836
          (share->state.changed & STATE_NOT_ANALYZED))
837
        need_to_check=1;
838
      if ((param->testflag & T_SORT_INDEX) &&
839
          (share->state.changed & STATE_NOT_SORTED_PAGES))
840
        need_to_check=1;
841
      if ((param->testflag & T_REP_BY_SORT) &&
842
          (share->state.changed & STATE_NOT_OPTIMIZED_KEYS))
843
        need_to_check=1;
844
    }
845
    if ((param->testflag & T_CHECK_ONLY_CHANGED) &&
846
	(share->state.changed & (STATE_CHANGED | STATE_CRASHED |
847
				 STATE_CRASHED_ON_REPAIR)))
848
      need_to_check=1;
849
    if (!need_to_check)
850
    {
851
      if (!(param->testflag & T_SILENT) || param->testflag & T_INFO)
852
	printf("MyISAM file: %s is already checked\n",filename);
853
      if (mi_close(info))
854
      {
855
	mi_check_print_error(param,"%d when closing MyISAM-table '%s'",
856
			     my_errno,filename);
51.1.116 by Jay Pipes
DBUG symbol removal
857
	return(1);
1 by brian
clean slate
858
      }
51.1.116 by Jay Pipes
DBUG symbol removal
859
      return(0);
1 by brian
clean slate
860
    }
861
  }
862
  if ((param->testflag & (T_REP_ANY | T_STATISTICS |
863
			  T_SORT_RECORDS | T_SORT_INDEX)) &&
864
      (((param->testflag & T_UNPACK) &&
865
	share->data_file_type == COMPRESSED_RECORD) ||
866
       mi_uint2korr(share->state.header.state_info_length) !=
867
       MI_STATE_INFO_SIZE ||
868
       mi_uint2korr(share->state.header.base_info_length) !=
869
       MI_BASE_INFO_SIZE ||
870
       mi_is_any_intersect_keys_active(param->keys_in_use, share->base.keys,
871
                                       ~share->state.key_map) ||
872
       test_if_almost_full(info) ||
873
       info->s->state.header.file_version[3] != myisam_file_magic[3] ||
874
       (set_collation &&
875
        set_collation->number != share->state.header.language) ||
876
       myisam_block_size != MI_KEY_BLOCK_LENGTH))
877
  {
878
    if (set_collation)
879
      param->language= set_collation->number;
880
    if (recreate_table(param, &info,filename))
881
    {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
882
      fprintf(stderr,
883
              "MyISAM-table '%s' is not fixed because of errors\n",
884
              filename);
1 by brian
clean slate
885
      return(-1);
886
    }
887
    recreate=1;
888
    if (!(param->testflag & T_REP_ANY))
889
    {
890
      param->testflag|=T_REP_BY_SORT;		/* if only STATISTICS */
891
      if (!(param->testflag & T_SILENT))
892
	printf("- '%s' has old table-format. Recreating index\n",filename);
893
      rep_quick|=T_QUICK;
894
    }
895
    share=info->s;
896
    share->tot_locks-= share->r_locks;
897
    share->r_locks=0;
898
  }
899
900
  if (param->testflag & T_DESCRIPT)
901
  {
902
    param->total_files++;
903
    param->total_records+=info->state->records;
904
    param->total_deleted+=info->state->del;
905
    descript(param, info, filename);
906
  }
907
  else
908
  {
909
910
    if (!(param->testflag & T_READONLY))
911
      lock_type = F_WRLCK;			/* table is changed */
912
    else
913
      lock_type= F_RDLCK;
914
    if (info->lock_type == F_RDLCK)
915
      info->lock_type=F_UNLCK;			/* Read only table */
916
    if (_mi_readinfo(info,lock_type,0))
917
    {
918
      mi_check_print_error(param,"Can't lock indexfile of '%s', error: %d",
919
		  filename,my_errno);
920
      param->error_printed=0;
921
      goto end2;
922
    }
923
    /*
924
      _mi_readinfo() has locked the table.
925
      We mark the table as locked (without doing file locks) to be able to
926
      use functions that only works on locked tables (like row caching).
927
    */
928
    mi_lock_database(info, F_EXTRA_LCK);
929
    datafile=info->dfile;
930
931
    if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX))
932
    {
933
      if (param->testflag & T_REP_ANY)
934
      {
151 by Brian Aker
Ulonglong to uint64_t
935
	uint64_t tmp=share->state.key_map;
1 by brian
clean slate
936
	mi_copy_keys_active(share->state.key_map, share->base.keys,
937
                            param->keys_in_use);
938
	if (tmp != share->state.key_map)
939
	  info->update|=HA_STATE_CHANGED;
940
      }
941
      if (rep_quick && chk_del(param, info, param->testflag & ~T_VERBOSE))
942
      {
943
	if (param->testflag & T_FORCE_CREATE)
944
	{
945
	  rep_quick=0;
946
	  mi_check_print_info(param,"Creating new data file\n");
947
	}
948
	else
949
	{
950
	  error=1;
951
	  mi_check_print_error(param,
952
			       "Quick-recover aborted; Run recovery without switch 'q'");
953
	}
954
      }
955
      if (!error)
956
      {
957
	if ((param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) &&
958
	    (mi_is_any_key_active(share->state.key_map) ||
959
	     (rep_quick && !param->keys_in_use && !recreate)) &&
960
	    mi_test_if_sort_rep(info, info->state->records,
961
				info->s->state.key_map,
962
				param->force_sort))
963
	{
964
          if (param->testflag & T_REP_BY_SORT)
965
            error=mi_repair_by_sort(param,info,filename,rep_quick);
966
          else
967
            error=mi_repair_parallel(param,info,filename,rep_quick);
968
	  state_updated=1;
969
	}
970
	else if (param->testflag & T_REP_ANY)
971
	  error=mi_repair(param, info,filename,rep_quick);
972
      }
973
      if (!error && param->testflag & T_SORT_RECORDS)
974
      {
482 by Brian Aker
Remove uint.
975
	uint32_t key;
1 by brian
clean slate
976
	/*
28.1.37 by Monty Taylor
Removed everything marked TO_BE_REMOVED.
977
	  We can't update the index in mi_sort_records if we have a
978
	  prefix compressed or fulltext index
1 by brian
clean slate
979
	*/
281 by Brian Aker
Converted myisam away from my_bool
980
	bool update_index=1;
28.1.37 by Monty Taylor
Removed everything marked TO_BE_REMOVED.
981
	for (key=0 ; key < share->base.keys; key++)
249 by Brian Aker
Random key cleanup (it is a friday...)
982
	  if (share->keyinfo[key].flag & (HA_BINARY_PACK_KEY))
28.1.37 by Monty Taylor
Removed everything marked TO_BE_REMOVED.
983
	    update_index=0;
984
985
	error=mi_sort_records(param,info,filename,param->opt_sort_key,
986
                           /* what is the following parameter for ? */
281 by Brian Aker
Converted myisam away from my_bool
987
	   		      (bool) !(param->testflag & T_REP),
28.1.37 by Monty Taylor
Removed everything marked TO_BE_REMOVED.
988
			      update_index);
989
	datafile=info->dfile;	/* This is now locked */
990
	if (!error && !update_index)
1 by brian
clean slate
991
	{
28.1.37 by Monty Taylor
Removed everything marked TO_BE_REMOVED.
992
	  if (param->verbose)
993
	    puts("Table had a compressed index;  We must now recreate the index");
994
	  error=mi_repair_by_sort(param,info,filename,1);
1 by brian
clean slate
995
	}
996
      }
997
      if (!error && param->testflag & T_SORT_INDEX)
998
	error=mi_sort_index(param,info,filename);
999
      if (!error)
1000
	share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
1001
				 STATE_CRASHED_ON_REPAIR);
1002
      else
1003
	mi_mark_crashed(info);
1004
    }
1005
    else if ((param->testflag & T_CHECK) || !(param->testflag & T_AUTO_INC))
1006
    {
1007
      if (!(param->testflag & T_SILENT) || param->testflag & T_INFO)
1008
	printf("Checking MyISAM file: %s\n",filename);
1009
      if (!(param->testflag & T_SILENT))
1010
	printf("Data records: %7s   Deleted blocks: %7s\n",
1011
	       llstr(info->state->records,llbuff),
1012
	       llstr(info->state->del,llbuff2));
1013
      error =chk_status(param,info);
1014
      mi_intersect_keys_active(share->state.key_map, param->keys_in_use);
1015
      error =chk_size(param,info);
1016
      if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)))
1017
	error|=chk_del(param, info,param->testflag);
1018
      if ((!error || (!(param->testflag & (T_FAST | T_FORCE_CREATE)) &&
1019
		      !param->start_check_pos)))
1020
      {
1021
	error|=chk_key(param, info);
1022
	if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC)))
1023
	  error=update_state_info(param, info,
1024
				  ((param->testflag & T_STATISTICS) ?
1025
				   UPDATE_STAT : 0) |
1026
				  ((param->testflag & T_AUTO_INC) ?
1027
				   UPDATE_AUTO_INC : 0));
1028
      }
1029
      if ((!rep_quick && !error) ||
1030
	  !(param->testflag & (T_FAST | T_FORCE_CREATE)))
1031
      {
1032
	if (param->testflag & (T_EXTEND | T_MEDIUM))
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1033
	  init_key_cache(dflt_key_cache,opt_key_cache_block_size,
1034
                         param->use_buffers, 0, 0);
1035
	init_io_cache(&param->read_cache,datafile,
1036
                      (uint) param->read_buffer_length,
1037
                      READ_CACHE,
1038
                      (param->start_check_pos ?
1039
                       param->start_check_pos :
1040
                       share->pack.header_length),
1041
                      1,
1042
                      MYF(MY_WME));
1 by brian
clean slate
1043
	lock_memory(param);
1044
	if ((info->s->options & (HA_OPTION_PACK_RECORD |
1045
				 HA_OPTION_COMPRESS_RECORD)) ||
1046
	    (param->testflag & (T_EXTEND | T_MEDIUM)))
1047
	  error|=chk_data_link(param, info, param->testflag & T_EXTEND);
1048
	error|=flush_blocks(param, share->key_cache, share->kfile);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1049
	end_io_cache(&param->read_cache);
1 by brian
clean slate
1050
      }
1051
      if (!error)
1052
      {
1053
	if ((share->state.changed & STATE_CHANGED) &&
1054
	    (param->testflag & T_UPDATE_STATE))
1055
	  info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
1056
	share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED |
1057
				 STATE_CRASHED_ON_REPAIR);
1058
      }
1059
      else if (!mi_is_crashed(info) &&
1060
	       (param->testflag & T_UPDATE_STATE))
1061
      {						/* Mark crashed */
1062
	mi_mark_crashed(info);
1063
	info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
1064
      }
1065
    }
1066
  }
1067
  if ((param->testflag & T_AUTO_INC) ||
1068
      ((param->testflag & T_REP_ANY) && info->s->base.auto_key))
1069
    update_auto_increment_key(param, info,
281 by Brian Aker
Converted myisam away from my_bool
1070
			      (bool) !test(param->testflag & T_AUTO_INC));
1 by brian
clean slate
1071
1072
  if (!(param->testflag & T_DESCRIPT))
1073
  {
1074
    if (info->update & HA_STATE_CHANGED && ! (param->testflag & T_READONLY))
1075
      error|=update_state_info(param, info,
1076
			       UPDATE_OPEN_COUNT |
1077
			       (((param->testflag & T_REP_ANY) ?
1078
				 UPDATE_TIME : 0) |
1079
				(state_updated ? UPDATE_STAT : 0) |
1080
				((param->testflag & T_SORT_RECORDS) ?
1081
				 UPDATE_SORT : 0)));
1082
    info->update&= ~HA_STATE_CHANGED;
1083
  }
1084
  mi_lock_database(info, F_UNLCK);
1085
end2:
1086
  if (mi_close(info))
1087
  {
1088
    mi_check_print_error(param,"%d when closing MyISAM-table '%s'",my_errno,filename);
51.1.116 by Jay Pipes
DBUG symbol removal
1089
    return(1);
1 by brian
clean slate
1090
  }
1091
  if (error == 0)
1092
  {
1093
    if (param->out_flag & O_NEW_DATA)
1094
      error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
1095
			       raid_chunks,
1096
			       ((param->testflag & T_BACKUP_DATA) ?
1097
				MYF(MY_REDEL_MAKE_BACKUP) : MYF(0)));
1098
    if (param->out_flag & O_NEW_INDEX)
1099
      error|=change_to_newfile(filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1100
			       MYF(0));
1101
  }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1102
  fflush(stdout); fflush(stderr);
1 by brian
clean slate
1103
  if (param->error_printed)
1104
  {
1105
    if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX))
1106
    {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1107
      fprintf(stderr,
1108
              "MyISAM-table '%s' is not fixed because of errors\n",
1109
              filename);
1 by brian
clean slate
1110
      if (param->testflag & T_REP_ANY)
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1111
	fprintf(stderr,
1112
                "Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag\n");
1 by brian
clean slate
1113
    }
1114
    else if (!(param->error_printed & 2) &&
1115
	     !(param->testflag & T_FORCE_CREATE))
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1116
      fprintf(stderr,
1117
              "MyISAM-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n",
1118
	      filename);
1 by brian
clean slate
1119
  }
1120
  else if (param->warning_printed &&
1121
	   ! (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
1122
			  T_FORCE_CREATE)))
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1123
    fprintf(stderr, "MyISAM-table '%s' is usable but should be fixed\n",
1124
            filename);
1125
  fflush(stderr);
51.1.116 by Jay Pipes
DBUG symbol removal
1126
  return(error);
1 by brian
clean slate
1127
} /* myisamchk */
1128
1129
1130
	 /* Write info about table */
1131
1132
static void descript(MI_CHECK *param, register MI_INFO *info, char * name)
1133
{
482 by Brian Aker
Remove uint.
1134
  uint32_t key,keyseg_nr,field,start;
1 by brian
clean slate
1135
  register MI_KEYDEF *keyinfo;
1136
  register HA_KEYSEG *keyseg;
1137
  register const char *text;
1138
  char buff[160],length[10],*pos,*end;
1139
  enum en_fieldtype type;
1140
  MYISAM_SHARE *share=info->s;
1141
  char llbuff[22],llbuff2[22];
1142
1143
  printf("\nMyISAM file:         %s\n",name);
1144
  fputs("Record format:       ",stdout);
1145
  if (share->options & HA_OPTION_COMPRESS_RECORD)
1146
    puts("Compressed");
1147
  else if (share->options & HA_OPTION_PACK_RECORD)
1148
    puts("Packed");
1149
  else
1150
    puts("Fixed length");
1151
  printf("Character set:       %s (%d)\n",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1152
  get_charset_name(share->state.header.language),
1153
  share->state.header.language);
1 by brian
clean slate
1154
1155
  if (param->testflag & T_VERBOSE)
1156
  {
1157
    printf("File-version:        %d\n",
1158
	   (int) share->state.header.file_version[3]);
1159
    if (share->state.create_time)
1160
    {
1161
      get_date(buff,1,share->state.create_time);
1162
      printf("Creation time:       %s\n",buff);
1163
    }
1164
    if (share->state.check_time)
1165
    {
1166
      get_date(buff,1,share->state.check_time);
1167
      printf("Recover time:        %s\n",buff);
1168
    }
1169
    pos=buff;
1170
    if (share->state.changed & STATE_CRASHED)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1171
      strcpy(buff,"crashed");
1 by brian
clean slate
1172
    else
1173
    {
1174
      if (share->state.open_count)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1175
        pos= strcpy(pos,"open,")+5;
1 by brian
clean slate
1176
      if (share->state.changed & STATE_CHANGED)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1177
        pos= strcpy(pos,"changed,")+8;
1 by brian
clean slate
1178
      else
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1179
        pos= strcpy(pos,"checked,")+8;
1 by brian
clean slate
1180
      if (!(share->state.changed & STATE_NOT_ANALYZED))
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1181
        pos= strcpy(pos,"analyzed,")+9;
1 by brian
clean slate
1182
      if (!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1183
        pos= strcpy(pos,"optimized keys,")+15;
1 by brian
clean slate
1184
      if (!(share->state.changed & STATE_NOT_SORTED_PAGES))
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1185
        pos= strcpy(pos,"sorted index pages,")+19;
1 by brian
clean slate
1186
      pos[-1]=0;				/* Remove extra ',' */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1187
    }
1 by brian
clean slate
1188
    printf("Status:              %s\n",buff);
1189
    if (share->base.auto_key)
1190
    {
1191
      printf("Auto increment key:  %13d  Last value:         %13s\n",
1192
	     share->base.auto_key,
1193
	     llstr(share->state.auto_increment,llbuff));
1194
    }
1195
    if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
1196
      printf("Checksum:  %23s\n",llstr(info->state->checksum,llbuff));
1197
;
1198
    if (share->options & HA_OPTION_DELAY_KEY_WRITE)
1199
      printf("Keys are only flushed at close\n");
1200
1201
  }
1202
  printf("Data records:        %13s  Deleted blocks:     %13s\n",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1203
  llstr(info->state->records,llbuff),llstr(info->state->del,llbuff2));
1 by brian
clean slate
1204
  if (param->testflag & T_SILENT)
51.1.116 by Jay Pipes
DBUG symbol removal
1205
    return;				/* This is enough */
1 by brian
clean slate
1206
1207
  if (param->testflag & T_VERBOSE)
1208
  {
1209
#ifdef USE_RELOC
1210
    printf("Init-relocation:     %13s\n",llstr(share->base.reloc,llbuff));
1211
#endif
1212
    printf("Datafile parts:      %13s  Deleted data:       %13s\n",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1213
    llstr(share->state.split,llbuff),
1214
    llstr(info->state->empty,llbuff2));
1 by brian
clean slate
1215
    printf("Datafile pointer (bytes):%9d  Keyfile pointer (bytes):%9d\n",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1216
    share->rec_reflength,share->base.key_reflength);
1 by brian
clean slate
1217
    printf("Datafile length:     %13s  Keyfile length:     %13s\n",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1218
    llstr(info->state->data_file_length,llbuff),
1219
    llstr(info->state->key_file_length,llbuff2));
1 by brian
clean slate
1220
1221
    if (info->s->base.reloc == 1L && info->s->base.records == 1L)
1222
      puts("This is a one-record table");
1223
    else
1224
    {
1225
      if (share->base.max_data_file_length != HA_OFFSET_ERROR ||
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1226
          share->base.max_key_file_length != HA_OFFSET_ERROR)
1227
        printf("Max datafile length: %13s  Max keyfile length: %13s\n",
1228
	             llstr(share->base.max_data_file_length-1,llbuff),
1229
	             llstr(share->base.max_key_file_length-1,llbuff2));
1 by brian
clean slate
1230
    }
1231
  }
1232
1233
  printf("Recordlength:        %13d\n",(int) share->base.pack_reclength);
1234
  if (! mi_is_all_keys_active(share->state.key_map, share->base.keys))
1235
  {
152 by Brian Aker
longlong replacement
1236
    int64_t2str(share->state.key_map,buff,2);
1 by brian
clean slate
1237
    printf("Using only keys '%s' of %d possibly keys\n",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1238
    buff, share->base.keys);
1 by brian
clean slate
1239
  }
1240
  puts("\ntable description:");
1241
  printf("Key Start Len Index   Type");
1242
  if (param->testflag & T_VERBOSE)
1243
    printf("                     Rec/key         Root  Blocksize");
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1244
  putchar('\n');
1 by brian
clean slate
1245
1246
  for (key=keyseg_nr=0, keyinfo= &share->keyinfo[0] ;
1247
       key < share->base.keys;
1248
       key++,keyinfo++)
1249
  {
1250
    keyseg=keyinfo->seg;
1251
    if (keyinfo->flag & HA_NOSAME) text="unique ";
1252
    else text="multip.";
1253
1254
    pos=buff;
1255
    if (keyseg->flag & HA_REVERSE_SORT)
1256
      *pos++ = '-';
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1257
    pos= strcpy(pos,type_names[keyseg->type]);
1258
    pos+= strlen(type_names[keyseg->type]);
1 by brian
clean slate
1259
    *pos++ = ' ';
1260
    *pos=0;
1261
    if (keyinfo->flag & HA_PACK_KEY)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1262
      pos= strcpy(pos,prefix_packed_txt) + strlen(prefix_packed_txt);
1 by brian
clean slate
1263
    if (keyinfo->flag & HA_BINARY_PACK_KEY)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1264
      pos= strcpy(pos,bin_packed_txt) + strlen(bin_packed_txt);
1 by brian
clean slate
1265
    if (keyseg->flag & HA_SPACE_PACK)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1266
      pos= strcpy(pos,diff_txt) + strlen(diff_txt);
1 by brian
clean slate
1267
    if (keyseg->flag & HA_BLOB_PART)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1268
      pos= strcpy(pos,blob_txt) + strlen(blob_txt);
1 by brian
clean slate
1269
    if (keyseg->flag & HA_NULL_PART)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1270
      pos= strcpy(pos,null_txt) + strlen(null_txt);
1 by brian
clean slate
1271
    *pos=0;
1272
1273
    printf("%-4d%-6ld%-3d %-8s%-21s",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1274
           key+1,(long) keyseg->start+1,keyseg->length,text,buff);
1 by brian
clean slate
1275
    if (share->state.key_root[key] != HA_OFFSET_ERROR)
1276
      llstr(share->state.key_root[key],buff);
1277
    else
1278
      buff[0]=0;
1279
    if (param->testflag & T_VERBOSE)
1280
      printf("%11lu %12s %10d",
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1281
    share->state.rec_per_key_part[keyseg_nr++],
1282
    buff,keyinfo->block_length);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1283
    putchar('\n');
1 by brian
clean slate
1284
    while ((++keyseg)->type != HA_KEYTYPE_END)
1285
    {
1286
      pos=buff;
1287
      if (keyseg->flag & HA_REVERSE_SORT)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1288
        *pos++ = '-';
1289
      pos= strcpy(pos,type_names[keyseg->type]);
1290
      pos+= strlen(type_names[keyseg->type]);
1 by brian
clean slate
1291
      *pos++= ' ';
1292
      if (keyseg->flag & HA_SPACE_PACK)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1293
        pos= strcpy(pos,diff_txt) + strlen(diff_txt);
1 by brian
clean slate
1294
      if (keyseg->flag & HA_BLOB_PART)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1295
        pos= strcpy(pos,blob_txt) + strlen(blob_txt);
1 by brian
clean slate
1296
      if (keyseg->flag & HA_NULL_PART)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1297
        pos= strcpy(pos,null_txt) + strlen(null_txt);
1 by brian
clean slate
1298
      *pos=0;
1299
      printf("    %-6ld%-3d         %-21s",
1300
	     (long) keyseg->start+1,keyseg->length,buff);
1301
      if (param->testflag & T_VERBOSE)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1302
        printf("%11lu", share->state.rec_per_key_part[keyseg_nr++]);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1303
      putchar('\n');
1 by brian
clean slate
1304
    }
1305
    keyseg++;
1306
  }
1307
  if (share->state.header.uniques)
1308
  {
1309
    MI_UNIQUEDEF *uniqueinfo;
1310
    puts("\nUnique  Key  Start  Len  Nullpos  Nullbit  Type");
1311
    for (key=0,uniqueinfo= &share->uniqueinfo[0] ;
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1312
         key < share->state.header.uniques; key++, uniqueinfo++)
1 by brian
clean slate
1313
    {
281 by Brian Aker
Converted myisam away from my_bool
1314
      bool new_row=0;
1 by brian
clean slate
1315
      char null_bit[8],null_pos[8];
1316
      printf("%-8d%-5d",key+1,uniqueinfo->key+1);
1317
      for (keyseg=uniqueinfo->seg ; keyseg->type != HA_KEYTYPE_END ; keyseg++)
1318
      {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1319
        if (new_row)
1320
          fputs("             ",stdout);
1321
        null_bit[0]=null_pos[0]=0;
1322
        if (keyseg->null_bit)
1323
        {
1324
          sprintf(null_bit,"%d",keyseg->null_bit);
1325
          sprintf(null_pos,"%ld",(long) keyseg->null_pos+1);
1326
        }
1327
        printf("%-7ld%-5d%-9s%-10s%-30s\n",
1328
               (long) keyseg->start+1,keyseg->length,
1329
               null_pos,null_bit,
1330
               type_names[keyseg->type]);
1331
        new_row=1;
1 by brian
clean slate
1332
      }
1333
    }
1334
  }
1335
  if (param->verbose > 1)
1336
  {
1337
    char null_bit[8],null_pos[8];
1338
    printf("\nField Start Length Nullpos Nullbit Type");
1339
    if (share->options & HA_OPTION_COMPRESS_RECORD)
1340
      printf("                         Huff tree  Bits");
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1341
    putchar('\n');
1 by brian
clean slate
1342
    start=1;
1343
    for (field=0 ; field < share->base.fields ; field++)
1344
    {
1345
      if (share->options & HA_OPTION_COMPRESS_RECORD)
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1346
        type=share->rec[field].base_type;
1 by brian
clean slate
1347
      else
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1348
        type=(enum en_fieldtype) share->rec[field].type;
1349
      end= strcpy(buff, field_pack[type]);
1350
      end+= strlen(field_pack[type]);
1 by brian
clean slate
1351
      if (share->options & HA_OPTION_COMPRESS_RECORD)
1352
      {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1353
        if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
1354
          end= strcpy(end,", not_always")+12;
1355
        if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
1356
          end= strcpy(end,", no empty")+10;
1357
        if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
1358
        {
1359
          sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
1360
          end= strchr(end, '\0');
1361
        }
1 by brian
clean slate
1362
      }
1363
      if (buff[0] == ',')
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1364
        strcpy(buff,buff+2);
1 by brian
clean slate
1365
      int10_to_str((long) share->rec[field].length,length,10);
1366
      null_bit[0]=null_pos[0]=0;
1367
      if (share->rec[field].null_bit)
1368
      {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1369
        sprintf(null_bit,"%d",share->rec[field].null_bit);
1370
        sprintf(null_pos,"%d",share->rec[field].null_pos+1);
1 by brian
clean slate
1371
      }
1372
      printf("%-6d%-6d%-7s%-8s%-8s%-35s",field+1,start,length,
1373
	     null_pos, null_bit, buff);
1374
      if (share->options & HA_OPTION_COMPRESS_RECORD)
1375
      {
1376
	if (share->rec[field].huff_tree)
1377
	  printf("%3d    %2d",
1378
		 (uint) (share->rec[field].huff_tree-share->decode_trees)+1,
1379
		 share->rec[field].huff_tree->quick_table_bits);
1380
      }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1381
      putchar('\n');
1 by brian
clean slate
1382
      start+=share->rec[field].length;
1383
    }
1384
  }
51.1.116 by Jay Pipes
DBUG symbol removal
1385
  return;
1 by brian
clean slate
1386
} /* describe */
1387
1388
1389
	/* Sort records according to one key */
1390
1391
static int mi_sort_records(MI_CHECK *param,
1392
			   register MI_INFO *info, char * name,
482 by Brian Aker
Remove uint.
1393
			   uint32_t sort_key,
281 by Brian Aker
Converted myisam away from my_bool
1394
			   bool write_info,
1395
			   bool update_index)
1 by brian
clean slate
1396
{
1397
  int got_error;
482 by Brian Aker
Remove uint.
1398
  uint32_t key;
1 by brian
clean slate
1399
  MI_KEYDEF *keyinfo;
1400
  File new_file;
481 by Brian Aker
Remove all of uchar.
1401
  unsigned char *temp_buff;
1 by brian
clean slate
1402
  ha_rows old_record_count;
1403
  MYISAM_SHARE *share=info->s;
1404
  char llbuff[22],llbuff2[22];
1405
  SORT_INFO sort_info;
1406
  MI_SORT_PARAM sort_param;
1407
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1408
  memset(&sort_info, 0, sizeof(sort_info));
1409
  memset(&sort_param, 0, sizeof(sort_param));
1 by brian
clean slate
1410
  sort_param.sort_info=&sort_info;
1411
  sort_info.param=param;
1412
  keyinfo= &share->keyinfo[sort_key];
1413
  got_error=1;
1414
  temp_buff=0;
1415
  new_file= -1;
1416
1417
  if (! mi_is_key_active(share->state.key_map, sort_key))
1418
  {
1419
    mi_check_print_warning(param,
1420
			   "Can't sort table '%s' on key %d;  No such key",
1421
		name,sort_key+1);
1422
    param->error_printed=0;
51.1.116 by Jay Pipes
DBUG symbol removal
1423
    return(0);				/* Nothing to do */
1 by brian
clean slate
1424
  }
1425
  if (share->data_file_type == COMPRESSED_RECORD)
1426
  {
1427
    mi_check_print_warning(param,"Can't sort read-only table '%s'", name);
1428
    param->error_printed=0;
51.1.116 by Jay Pipes
DBUG symbol removal
1429
    return(0);				/* Nothing to do */
1 by brian
clean slate
1430
  }
1431
  if (!(param->testflag & T_SILENT))
1432
  {
1433
    printf("- Sorting records for MyISAM-table '%s'\n",name);
1434
    if (write_info)
1435
      printf("Data records: %9s   Deleted: %9s\n",
1436
	     llstr(info->state->records,llbuff),
1437
	     llstr(info->state->del,llbuff2));
1438
  }
1439
  if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
51.1.116 by Jay Pipes
DBUG symbol removal
1440
    return(0);				/* Nothing to do */
1 by brian
clean slate
1441
1442
  init_key_cache(dflt_key_cache, opt_key_cache_block_size, param->use_buffers,
1443
                 0, 0);
1444
  if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
1445
		   WRITE_CACHE,share->pack.header_length,1,
1446
		   MYF(MY_WME | MY_WAIT_IF_FULL)))
1447
    goto err;
1448
  info->opt_flag|=WRITE_CACHE_USED;
1449
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1450
  if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
1 by brian
clean slate
1451
  {
1452
    mi_check_print_error(param,"Not enough memory for key block");
1453
    goto err;
1454
  }
1455
598.1.1 by Super-User
Fixed solaris build crap.
1456
  if (!mi_alloc_rec_buff(info, (ulong)-1, &sort_param.record))
1 by brian
clean slate
1457
  {
1458
    mi_check_print_error(param,"Not enough memory for record");
1459
    goto err;
1460
  }
1461
  fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
492.1.10 by Monty Taylor
Removed references to my_raid_create and my_raid_delete.
1462
  new_file=my_create(fn_format(param->temp_filename,
1463
                               param->temp_filename,"",
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1464
                               DATA_TMP_EXT,2+4),
492.1.10 by Monty Taylor
Removed references to my_raid_create and my_raid_delete.
1465
                     0,param->tmpfile_createflag,
1466
                     MYF(0));
1 by brian
clean slate
1467
  if (new_file < 0)
1468
  {
1469
    mi_check_print_error(param,"Can't create new tempfile: '%s'",
1470
			 param->temp_filename);
1471
    goto err;
1472
  }
1473
  if (share->pack.header_length)
1474
    if (filecopy(param,new_file,info->dfile,0L,share->pack.header_length,
1475
		 "datafile-header"))
1476
      goto err;
1477
  info->rec_cache.file=new_file;		/* Use this file for cacheing*/
1478
1479
  lock_memory(param);
1480
  for (key=0 ; key < share->base.keys ; key++)
1481
    share->keyinfo[key].flag|= HA_SORT_ALLOWS_SAME;
1482
481 by Brian Aker
Remove all of uchar.
1483
  if (my_pread(share->kfile,(unsigned char*) temp_buff,
1 by brian
clean slate
1484
	       (uint) keyinfo->block_length,
1485
	       share->state.key_root[sort_key],
1486
	       MYF(MY_NABP+MY_WME)))
1487
  {
1488
    mi_check_print_error(param,"Can't read indexpage from filepos: %s",
1489
		(ulong) share->state.key_root[sort_key]);
1490
    goto err;
1491
  }
1492
1493
  /* Setup param for sort_write_record */
1494
  sort_info.info=info;
1495
  sort_info.new_data_file_type=share->data_file_type;
1496
  sort_param.fix_datafile=1;
1497
  sort_param.master=1;
1498
  sort_param.filepos=share->pack.header_length;
1499
  old_record_count=info->state->records;
1500
  info->state->records=0;
1501
  if (sort_info.new_data_file_type != COMPRESSED_RECORD)
1502
    info->state->checksum=0;
1503
1504
  if (sort_record_index(&sort_param,info,keyinfo,share->state.key_root[sort_key],
1505
			temp_buff, sort_key,new_file,update_index) ||
1506
      write_data_suffix(&sort_info,1) ||
1507
      flush_io_cache(&info->rec_cache))
1508
    goto err;
1509
1510
  if (info->state->records != old_record_count)
1511
  {
1512
    mi_check_print_error(param,"found %s of %s records",
1513
		llstr(info->state->records,llbuff),
1514
		llstr(old_record_count,llbuff2));
1515
    goto err;
1516
  }
1517
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1518
  my_close(info->dfile,MYF(MY_WME));
1 by brian
clean slate
1519
  param->out_flag|=O_NEW_DATA;			/* Data in new file */
1520
  info->dfile=new_file;				/* Use new datafile */
1521
  info->state->del=0;
1522
  info->state->empty=0;
1523
  share->state.dellink= HA_OFFSET_ERROR;
1524
  info->state->data_file_length=sort_param.filepos;
1525
  share->state.split=info->state->records;	/* Only hole records */
1526
  share->state.version=(ulong) time((time_t*) 0);
1527
1528
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
1529
1530
  if (param->testflag & T_WRITE_LOOP)
1531
  {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1532
    fputs("          \r",stdout); fflush(stdout);
1 by brian
clean slate
1533
  }
1534
  got_error=0;
1535
1536
err:
1537
  if (got_error && new_file >= 0)
1538
  {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1539
    end_io_cache(&info->rec_cache);
1 by brian
clean slate
1540
    (void) my_close(new_file,MYF(MY_WME));
492.1.10 by Monty Taylor
Removed references to my_raid_create and my_raid_delete.
1541
    (void) my_delete(param->temp_filename, MYF(MY_WME));
1 by brian
clean slate
1542
  }
1543
  if (temp_buff)
1544
  {
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1545
    free((unsigned char*) temp_buff);
1 by brian
clean slate
1546
  }
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1547
  void * rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1548
  if (rec_buff_ptr != NULL)
1549
    free(rec_buff_ptr);
1550
1 by brian
clean slate
1551
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1552
  end_io_cache(&info->rec_cache);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1553
  free(sort_info.buff);
1 by brian
clean slate
1554
  sort_info.buff=0;
1555
  share->state.sortkey=sort_key;
51.1.116 by Jay Pipes
DBUG symbol removal
1556
  return(flush_blocks(param, share->key_cache, share->kfile) |
1 by brian
clean slate
1557
	      got_error);
1558
} /* sort_records */
1559
1560
1561
	 /* Sort records recursive using one index */
1562
1563
static int sort_record_index(MI_SORT_PARAM *sort_param,MI_INFO *info,
1564
                             MI_KEYDEF *keyinfo,
482 by Brian Aker
Remove uint.
1565
			     my_off_t page, unsigned char *buff, uint32_t sort_key,
281 by Brian Aker
Converted myisam away from my_bool
1566
			     File new_file,bool update_index)
1 by brian
clean slate
1567
{
1568
  uint	nod_flag,used_length,key_length;
481 by Brian Aker
Remove all of uchar.
1569
  unsigned char *temp_buff,*keypos,*endpos;
1 by brian
clean slate
1570
  my_off_t next_page,rec_pos;
481 by Brian Aker
Remove all of uchar.
1571
  unsigned char lastkey[MI_MAX_KEY_BUFF];
1 by brian
clean slate
1572
  char llbuff[22];
1573
  SORT_INFO *sort_info= sort_param->sort_info;
1574
  MI_CHECK *param=sort_info->param;
1575
1576
  nod_flag=mi_test_if_nod(buff);
1577
  temp_buff=0;
1578
1579
  if (nod_flag)
1580
  {
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1581
    if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
1 by brian
clean slate
1582
    {
1583
      mi_check_print_error(param,"Not Enough memory");
51.1.116 by Jay Pipes
DBUG symbol removal
1584
      return(-1);
1 by brian
clean slate
1585
    }
1586
  }
1587
  used_length=mi_getint(buff);
1588
  keypos=buff+2+nod_flag;
1589
  endpos=buff+used_length;
1590
  for ( ;; )
1591
  {
1592
    if (nod_flag)
1593
    {
1594
      next_page=_mi_kpos(nod_flag,keypos);
481 by Brian Aker
Remove all of uchar.
1595
      if (my_pread(info->s->kfile,(unsigned char*) temp_buff,
1 by brian
clean slate
1596
		  (uint) keyinfo->block_length, next_page,
1597
		   MYF(MY_NABP+MY_WME)))
1598
      {
1599
	mi_check_print_error(param,"Can't read keys from filepos: %s",
1600
		    llstr(next_page,llbuff));
1601
	goto err;
1602
      }
1603
      if (sort_record_index(sort_param, info,keyinfo,next_page,temp_buff,sort_key,
1604
			    new_file, update_index))
1605
	goto err;
1606
    }
1607
    if (keypos >= endpos ||
1608
	(key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
1609
	== 0)
1610
      break;
1611
    rec_pos= _mi_dpos(info,0,lastkey+key_length);
1612
1613
    if ((*info->s->read_rnd)(info,sort_param->record,rec_pos,0))
1614
    {
1615
      mi_check_print_error(param,"%d when reading datafile",my_errno);
1616
      goto err;
1617
    }
1618
    if (rec_pos != sort_param->filepos && update_index)
1619
    {
1620
      _mi_dpointer(info,keypos-nod_flag-info->s->rec_reflength,
1621
		   sort_param->filepos);
1622
      if (movepoint(info,sort_param->record,rec_pos,sort_param->filepos,
1623
		    sort_key))
1624
      {
1625
	mi_check_print_error(param,"%d when updating key-pointers",my_errno);
1626
	goto err;
1627
      }
1628
    }
1629
    if (sort_write_record(sort_param))
1630
      goto err;
1631
  }
1632
  /* Clear end of block to get better compression if the table is backuped */
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
1633
  memset(buff+used_length, 0, keyinfo->block_length-used_length);
481 by Brian Aker
Remove all of uchar.
1634
  if (my_pwrite(info->s->kfile,(unsigned char*) buff,(uint) keyinfo->block_length,
1 by brian
clean slate
1635
		page,param->myf_rw))
1636
  {
1637
    mi_check_print_error(param,"%d when updating keyblock",my_errno);
1638
    goto err;
1639
  }
1640
  if (temp_buff)
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1641
    free((unsigned char*) temp_buff);
51.1.116 by Jay Pipes
DBUG symbol removal
1642
  return(0);
1 by brian
clean slate
1643
err:
1644
  if (temp_buff)
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
1645
    free((unsigned char*) temp_buff);
51.1.116 by Jay Pipes
DBUG symbol removal
1646
  return(1);
1 by brian
clean slate
1647
} /* sort_record_index */
1648
1649
1650
1651
/*
1652
  Check if myisamchk was killed by a signal
1653
  This is overloaded by other programs that want to be able to abort
1654
  sorting
1655
*/
1656
1657
static int not_killed= 0;
1658
1659
volatile int *killed_ptr(MI_CHECK *param __attribute__((unused)))
1660
{
1661
  return &not_killed;			/* always NULL */
1662
}
1663
1664
	/* print warnings and errors */
1665
	/* VARARGS */
1666
1667
void mi_check_print_info(MI_CHECK *param __attribute__((unused)),
1668
			 const char *fmt,...)
1669
{
1670
  va_list args;
1671
1672
  va_start(args,fmt);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1673
  vfprintf(stdout, fmt, args);
1674
  fputc('\n',stdout);
1 by brian
clean slate
1675
  va_end(args);
1676
}
1677
1678
/* VARARGS */
1679
1680
void mi_check_print_warning(MI_CHECK *param, const char *fmt,...)
1681
{
1682
  va_list args;
1683
1684
  fflush(stdout);
1685
  if (!param->warning_printed && !param->error_printed)
1686
  {
1687
    if (param->testflag & T_SILENT)
1688
      fprintf(stderr,"%s: MyISAM file %s\n",my_progname_short,
1689
	      param->isam_file_name);
1690
    param->out_flag|= O_DATA_LOST;
1691
  }
1692
  param->warning_printed=1;
1693
  va_start(args,fmt);
1694
  fprintf(stderr,"%s: warning: ",my_progname_short);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1695
  vfprintf(stderr, fmt, args);
1696
  fputc('\n',stderr);
1 by brian
clean slate
1697
  fflush(stderr);
1698
  va_end(args);
51.1.116 by Jay Pipes
DBUG symbol removal
1699
  return;
1 by brian
clean slate
1700
}
1701
1702
/* VARARGS */
1703
1704
void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
1705
{
1706
  va_list args;
1707
1708
  fflush(stdout);
1709
  if (!param->warning_printed && !param->error_printed)
1710
  {
1711
    if (param->testflag & T_SILENT)
1712
      fprintf(stderr,"%s: MyISAM file %s\n",my_progname_short,param->isam_file_name);
1713
    param->out_flag|= O_DATA_LOST;
1714
  }
1715
  param->error_printed|=1;
1716
  va_start(args,fmt);
1717
  fprintf(stderr,"%s: error: ",my_progname_short);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1718
  vfprintf(stderr, fmt, args);
1719
  fputc('\n',stderr);
1 by brian
clean slate
1720
  fflush(stderr);
1721
  va_end(args);
51.1.116 by Jay Pipes
DBUG symbol removal
1722
  return;
1 by brian
clean slate
1723
}
1724