16
16
/* Describe, check and repair of MyISAM tables */
18
#include <drizzled/global.h>
18
#include "myisamdef.h"
20
21
#include <mystrings/m_ctype.h>
22
22
#include <mysys/my_getopt.h>
23
23
#include <mysys/my_bit.h>
25
24
#include <mystrings/m_string.h>
26
27
#ifdef HAVE_SYS_VADVICE_H
27
28
#include <sys/vadvise.h>
29
30
#ifdef HAVE_SYS_MMAN_H
30
31
#include <sys/mman.h>
33
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
34
#define my_raid_delete(A,B,C) my_delete(A,B)
36
#include "myisamdef.h"
33
#include <drizzled/util/test.h>
36
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
38
38
static uint32_t decode_bits;
39
39
static char **default_argv;
155
155
"Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.",
156
156
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
157
{"block-search", 'b',
158
"No help available.",
159
0, 0, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
161
158
"Make a backup of the .MYD file as 'filename-time.BAK'.",
162
159
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
163
{"character-sets-dir", OPT_CHARSETS_DIR,
164
"Directory where character sets are.",
165
(char**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
167
161
"Check table for errors.",
168
162
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
276
270
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
277
271
{ "key_buffer_size", OPT_KEY_BUFFER_SIZE, "",
278
272
(char**) &check_param.use_buffers, (char**) &check_param.use_buffers, 0,
279
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
273
GET_UINT64, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
280
274
INT32_MAX, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
281
275
{ "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "",
282
276
(char**) &opt_key_cache_block_size,
289
283
MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
290
284
{ "read_buffer_size", OPT_READ_BUFFER_SIZE, "",
291
285
(char**) &check_param.read_buffer_length,
292
(char**) &check_param.read_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
286
(char**) &check_param.read_buffer_length, 0, GET_SIZE, REQUIRED_ARG,
293
287
(long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
294
INT32_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
288
SIZE_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
295
289
{ "write_buffer_size", OPT_WRITE_BUFFER_SIZE, "",
296
290
(char**) &check_param.write_buffer_length,
297
(char**) &check_param.write_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
291
(char**) &check_param.write_buffer_length, 0, GET_SIZE, REQUIRED_ARG,
298
292
(long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
299
INT32_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
293
SIZE_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
300
294
{ "sort_buffer_size", OPT_SORT_BUFFER_SIZE, "",
301
295
(char**) &check_param.sort_buffer_length,
302
(char**) &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
296
(char**) &check_param.sort_buffer_length, 0, GET_SIZE, REQUIRED_ARG,
303
297
(long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD),
304
INT32_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
298
SIZE_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
305
299
{ "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "",
306
300
(char**) &check_param.sort_key_blocks,
307
(char**) &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG,
301
(char**) &check_param.sort_key_blocks, 0, GET_SIZE, REQUIRED_ARG,
308
302
BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
309
303
{ "decode_bits", OPT_DECODE_BITS, "", (char**) &decode_bits,
310
304
(char**) &decode_bits, 0, GET_UINT, REQUIRED_ARG, 9L, 4L, 17L, 0L, 1L, 0},
1171
1157
if (share->state.changed & STATE_CRASHED)
1172
my_stpcpy(buff,"crashed");
1158
strcpy(buff,"crashed");
1175
1161
if (share->state.open_count)
1176
pos=my_stpcpy(pos,"open,");
1162
pos= strcpy(pos,"open,")+5;
1177
1163
if (share->state.changed & STATE_CHANGED)
1178
pos=my_stpcpy(pos,"changed,");
1164
pos= strcpy(pos,"changed,")+8;
1180
pos=my_stpcpy(pos,"checked,");
1166
pos= strcpy(pos,"checked,")+8;
1181
1167
if (!(share->state.changed & STATE_NOT_ANALYZED))
1182
pos=my_stpcpy(pos,"analyzed,");
1168
pos= strcpy(pos,"analyzed,")+9;
1183
1169
if (!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))
1184
pos=my_stpcpy(pos,"optimized keys,");
1170
pos= strcpy(pos,"optimized keys,")+15;
1185
1171
if (!(share->state.changed & STATE_NOT_SORTED_PAGES))
1186
pos=my_stpcpy(pos,"sorted index pages,");
1172
pos= strcpy(pos,"sorted index pages,")+19;
1187
1173
pos[-1]=0; /* Remove extra ',' */
1189
1175
printf("Status: %s\n",buff);
1190
1176
if (share->base.auto_key)
1218
1197
printf("Init-relocation: %13s\n",llstr(share->base.reloc,llbuff));
1220
1199
printf("Datafile parts: %13s Deleted data: %13s\n",
1221
llstr(share->state.split,llbuff),
1222
llstr(info->state->empty,llbuff2));
1200
llstr(share->state.split,llbuff),
1201
llstr(info->state->empty,llbuff2));
1223
1202
printf("Datafile pointer (bytes):%9d Keyfile pointer (bytes):%9d\n",
1224
share->rec_reflength,share->base.key_reflength);
1203
share->rec_reflength,share->base.key_reflength);
1225
1204
printf("Datafile length: %13s Keyfile length: %13s\n",
1226
llstr(info->state->data_file_length,llbuff),
1227
llstr(info->state->key_file_length,llbuff2));
1205
llstr(info->state->data_file_length,llbuff),
1206
llstr(info->state->key_file_length,llbuff2));
1229
1208
if (info->s->base.reloc == 1L && info->s->base.records == 1L)
1230
1209
puts("This is a one-record table");
1233
1212
if (share->base.max_data_file_length != HA_OFFSET_ERROR ||
1234
share->base.max_key_file_length != HA_OFFSET_ERROR)
1235
printf("Max datafile length: %13s Max keyfile length: %13s\n",
1236
llstr(share->base.max_data_file_length-1,llbuff),
1237
llstr(share->base.max_key_file_length-1,llbuff2));
1213
share->base.max_key_file_length != HA_OFFSET_ERROR)
1214
printf("Max datafile length: %13s Max keyfile length: %13s\n",
1215
llstr(share->base.max_data_file_length-1,llbuff),
1216
llstr(share->base.max_key_file_length-1,llbuff2));
1263
1242
if (keyseg->flag & HA_REVERSE_SORT)
1265
pos=my_stpcpy(pos,type_names[keyseg->type]);
1244
pos= strcpy(pos,type_names[keyseg->type]);
1245
pos+= strlen(type_names[keyseg->type]);
1268
1248
if (keyinfo->flag & HA_PACK_KEY)
1269
pos=my_stpcpy(pos,prefix_packed_txt);
1249
pos= strcpy(pos,prefix_packed_txt) + strlen(prefix_packed_txt);
1270
1250
if (keyinfo->flag & HA_BINARY_PACK_KEY)
1271
pos=my_stpcpy(pos,bin_packed_txt);
1251
pos= strcpy(pos,bin_packed_txt) + strlen(bin_packed_txt);
1272
1252
if (keyseg->flag & HA_SPACE_PACK)
1273
pos=my_stpcpy(pos,diff_txt);
1253
pos= strcpy(pos,diff_txt) + strlen(diff_txt);
1274
1254
if (keyseg->flag & HA_BLOB_PART)
1275
pos=my_stpcpy(pos,blob_txt);
1255
pos= strcpy(pos,blob_txt) + strlen(blob_txt);
1276
1256
if (keyseg->flag & HA_NULL_PART)
1277
pos=my_stpcpy(pos,null_txt);
1257
pos= strcpy(pos,null_txt) + strlen(null_txt);
1280
1260
printf("%-4d%-6ld%-3d %-8s%-21s",
1281
key+1,(long) keyseg->start+1,keyseg->length,text,buff);
1261
key+1,(long) keyseg->start+1,keyseg->length,text,buff);
1282
1262
if (share->state.key_root[key] != HA_OFFSET_ERROR)
1283
1263
llstr(share->state.key_root[key],buff);
1286
1266
if (param->testflag & T_VERBOSE)
1287
1267
printf("%11lu %12s %10d",
1288
share->state.rec_per_key_part[keyseg_nr++],
1289
buff,keyinfo->block_length);
1268
share->state.rec_per_key_part[keyseg_nr++],
1269
buff,keyinfo->block_length);
1291
1271
while ((++keyseg)->type != HA_KEYTYPE_END)
1294
1274
if (keyseg->flag & HA_REVERSE_SORT)
1296
pos=my_stpcpy(pos,type_names[keyseg->type]);
1276
pos= strcpy(pos,type_names[keyseg->type]);
1277
pos+= strlen(type_names[keyseg->type]);
1298
1279
if (keyseg->flag & HA_SPACE_PACK)
1299
pos=my_stpcpy(pos,diff_txt);
1280
pos= strcpy(pos,diff_txt) + strlen(diff_txt);
1300
1281
if (keyseg->flag & HA_BLOB_PART)
1301
pos=my_stpcpy(pos,blob_txt);
1282
pos= strcpy(pos,blob_txt) + strlen(blob_txt);
1302
1283
if (keyseg->flag & HA_NULL_PART)
1303
pos=my_stpcpy(pos,null_txt);
1284
pos= strcpy(pos,null_txt) + strlen(null_txt);
1305
1286
printf(" %-6ld%-3d %-21s",
1306
1287
(long) keyseg->start+1,keyseg->length,buff);
1307
1288
if (param->testflag & T_VERBOSE)
1308
printf("%11lu", share->state.rec_per_key_part[keyseg_nr++]);
1289
printf("%11lu", share->state.rec_per_key_part[keyseg_nr++]);
1315
1296
MI_UNIQUEDEF *uniqueinfo;
1316
1297
puts("\nUnique Key Start Len Nullpos Nullbit Type");
1317
1298
for (key=0,uniqueinfo= &share->uniqueinfo[0] ;
1318
key < share->state.header.uniques; key++, uniqueinfo++)
1299
key < share->state.header.uniques; key++, uniqueinfo++)
1320
1301
bool new_row=0;
1321
1302
char null_bit[8],null_pos[8];
1322
1303
printf("%-8d%-5d",key+1,uniqueinfo->key+1);
1323
1304
for (keyseg=uniqueinfo->seg ; keyseg->type != HA_KEYTYPE_END ; keyseg++)
1327
null_bit[0]=null_pos[0]=0;
1328
if (keyseg->null_bit)
1330
sprintf(null_bit,"%d",keyseg->null_bit);
1331
sprintf(null_pos,"%ld",(long) keyseg->null_pos+1);
1333
printf("%-7ld%-5d%-9s%-10s%-30s\n",
1334
(long) keyseg->start+1,keyseg->length,
1336
type_names[keyseg->type]);
1308
null_bit[0]=null_pos[0]=0;
1309
if (keyseg->null_bit)
1311
sprintf(null_bit,"%d",keyseg->null_bit);
1312
sprintf(null_pos,"%ld",(long) keyseg->null_pos+1);
1314
printf("%-7ld%-5d%-9s%-10s%-30s\n",
1315
(long) keyseg->start+1,keyseg->length,
1317
type_names[keyseg->type]);
1349
1330
for (field=0 ; field < share->base.fields ; field++)
1351
1332
if (share->options & HA_OPTION_COMPRESS_RECORD)
1352
type=share->rec[field].base_type;
1333
type=share->rec[field].base_type;
1354
type=(enum en_fieldtype) share->rec[field].type;
1355
end=my_stpcpy(buff,field_pack[type]);
1335
type=(enum en_fieldtype) share->rec[field].type;
1336
end= strcpy(buff, field_pack[type]);
1337
end+= strlen(field_pack[type]);
1356
1338
if (share->options & HA_OPTION_COMPRESS_RECORD)
1358
if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
1359
end=my_stpcpy(end,", not_always");
1360
if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
1361
end=my_stpcpy(end,", no empty");
1362
if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
1364
sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
1365
end= strchr(end, '\0');
1340
if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
1341
end= strcpy(end,", not_always")+12;
1342
if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
1343
end= strcpy(end,", no empty")+10;
1344
if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
1346
sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
1347
end= strchr(end, '\0');
1368
1350
if (buff[0] == ',')
1369
my_stpcpy(buff,buff+2);
1351
strcpy(buff,buff+2);
1370
1352
int10_to_str((long) share->rec[field].length,length,10);
1371
1353
null_bit[0]=null_pos[0]=0;
1372
1354
if (share->rec[field].null_bit)
1374
sprintf(null_bit,"%d",share->rec[field].null_bit);
1375
sprintf(null_pos,"%d",share->rec[field].null_pos+1);
1356
sprintf(null_bit,"%d",share->rec[field].null_bit);
1357
sprintf(null_pos,"%d",share->rec[field].null_pos+1);
1377
1359
printf("%-6d%-6d%-7s%-8s%-8s%-35s",field+1,start,length,
1378
1360
null_pos, null_bit, buff);
1444
1426
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
1445
1427
return(0); /* Nothing to do */
1447
init_key_cache(dflt_key_cache, opt_key_cache_block_size, param->use_buffers,
1429
init_key_cache(dflt_key_cache, opt_key_cache_block_size,
1430
(size_t)param->use_buffers,
1449
1432
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
1450
1433
WRITE_CACHE,share->pack.header_length,1,
1453
1436
info->opt_flag|=WRITE_CACHE_USED;
1455
if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
1438
if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
1457
1440
mi_check_print_error(param,"Not enough memory for key block");
1461
if (!mi_alloc_rec_buff(info, -1, &sort_param.record))
1444
if (!mi_alloc_rec_buff(info, (ulong)-1, &sort_param.record))
1463
1446
mi_check_print_error(param,"Not enough memory for record");
1466
1449
fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
1467
new_file=my_raid_create(fn_format(param->temp_filename,
1468
param->temp_filename,"",
1470
0,param->tmpfile_createflag,
1471
share->base.raid_type,
1472
share->base.raid_chunks,
1473
share->base.raid_chunksize,
1450
new_file=my_create(fn_format(param->temp_filename,
1451
param->temp_filename,"",
1453
0,param->tmpfile_createflag,
1475
1455
if (new_file < 0)
1477
1457
mi_check_print_error(param,"Can't create new tempfile: '%s'",