summaryrefslogtreecommitdiff
path: root/myisam/mi_check.c
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2003-12-01 16:14:40 +0100
committerunknown <pem@mysql.com>2003-12-01 16:14:40 +0100
commit38f853d291075a8eaa9d408a23626b09aa7ac1d2 (patch)
tree024f2d18e3cf9f65db53f9f8c2d5413859781e16 /myisam/mi_check.c
parent6573b851e36de43d4cfa39d5eba0b740c3226521 (diff)
parent91de6fdbce2a5c545532acf1124f35378a75ea0c (diff)
downloadmariadb-git-38f853d291075a8eaa9d408a23626b09aa7ac1d2.tar.gz
Merge 4.1 to 5.0
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union configure.in: Auto merged client/mysql.cc: Auto merged client/mysqltest.c: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/mysql_com.h: Auto merged libmysql/libmysql.c: Auto merged myisam/mi_check.c: Auto merged myisam/myisamchk.c: Auto merged myisam/myisamdef.h: Auto merged myisam/sort.c: Auto merged mysql-test/install_test_db.sh: Auto merged mysql-test/r/subselect.result: Auto merged mysql-test/r/symlink.result: Auto merged mysql-test/t/subselect.test: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_myisam.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/log.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/opt_range.cc: Auto merged sql/protocol.cc: Auto merged sql/protocol.h: Auto merged sql/protocol_cursor.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_db.cc: Auto merged sql/sql_derived.cc: Auto merged sql/sql_error.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_list.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_test.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'myisam/mi_check.c')
-rw-r--r--myisam/mi_check.c172
1 files changed, 101 insertions, 71 deletions
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 4f8fc9b981a..c077e267dde 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -77,6 +77,7 @@ void myisamchk_init(MI_CHECK *param)
param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
param->start_check_pos=0;
+ param->max_record_length= LONGLONG_MAX;
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
}
@@ -242,7 +243,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
if (next_link > info->state->key_file_length ||
next_link & (info->s->blocksize-1))
DBUG_RETURN(1);
- if (!(buff=key_cache_read(*info->s->key_cache,
+ if (!(buff=key_cache_read(info->s->key_cache,
info->s->kfile, next_link, DFLT_INIT_HITS,
(byte*) info->buff,
myisam_block_size, block_size, 1)))
@@ -262,7 +263,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
} /* check_k_link */
- /* Kontrollerar storleken p} filerna */
+ /* Check sizes of files */
int chk_size(MI_CHECK *param, register MI_INFO *info)
{
@@ -273,8 +274,9 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
if (!(param->testflag & T_SILENT)) puts("- check file-size");
- flush_key_blocks(*info->s->key_cache,
- info->s->kfile, FLUSH_FORCE_WRITE); /* If called externally */
+ /* The following is needed if called externally (not from myisamchk) */
+ flush_key_blocks(info->s->key_cache,
+ info->s->kfile, FLUSH_FORCE_WRITE);
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
if ((skr=(my_off_t) info->state->key_file_length) != size)
@@ -502,7 +504,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
param->record_checksum=old_record_checksum-init_checksum; /* Remove delete links */
else
param->record_checksum=0;
- DBUG_RETURN(0);
+ DBUG_RETURN(result);
} /* chk_key */
@@ -522,7 +524,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
{
- mi_check_print_error(param,"Not Enough memory");
+ mi_check_print_error(param,"Not enough memory for keyblock");
DBUG_RETURN(-1);
}
@@ -711,7 +713,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
if (!(record= (byte*) my_malloc(info->s->base.pack_reclength,MYF(0))))
{
- mi_check_print_error(param,"Not Enough memory");
+ mi_check_print_error(param,"Not enough memory for record");
DBUG_RETURN(-1);
}
records=del_blocks=0;
@@ -814,16 +816,17 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
goto next;
}
mi_check_print_error(param,"Wrong bytesec: %d-%d-%d at linkstart: %s",
- block_info.header[0],block_info.header[1],
- block_info.header[2],
- llstr(start_block,llbuff));
+ block_info.header[0],block_info.header[1],
+ block_info.header[2],
+ llstr(start_block,llbuff));
goto err2;
}
if (info->state->data_file_length < block_info.filepos+
block_info.block_len)
{
- mi_check_print_error(param,"Recordlink that points outside datafile at %s",
- llstr(pos,llbuff));
+ mi_check_print_error(param,
+ "Recordlink that points outside datafile at %s",
+ llstr(pos,llbuff));
got_error=1;
break;
}
@@ -834,9 +837,9 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
pos=block_info.filepos+block_info.block_len;
if (block_info.rec_len > (uint) info->s->base.max_pack_length)
{
- mi_check_print_error(param,"Found too long record (%d) at %s",
- block_info.rec_len,
- llstr(start_recpos,llbuff));
+ mi_check_print_error(param,"Found too long record (%lu) at %s",
+ (ulong) block_info.rec_len,
+ llstr(start_recpos,llbuff));
got_error=1;
break;
}
@@ -845,8 +848,10 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
if (!(to= mi_alloc_rec_buff(info, block_info.rec_len,
&info->rec_buff)))
{
- mi_check_print_error(param,"Not enough memory for blob at %s",
- llstr(start_recpos,llbuff));
+ mi_check_print_error(param,
+ "Not enough memory (%lu) for blob at %s",
+ (ulong) block_info.rec_len,
+ llstr(start_recpos,llbuff));
got_error=1;
break;
}
@@ -857,9 +862,11 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
}
if (left_length < block_info.data_len)
{
- mi_check_print_error(param,"Found too long record at %s",
- llstr(start_recpos,llbuff));
- got_error=1; break;
+ mi_check_print_error(param,"Found too long record (%lu) at %s",
+ (ulong) block_info.data_len,
+ llstr(start_recpos,llbuff));
+ got_error=1;
+ break;
}
if (_mi_read_cache(&param->read_cache,(byte*) to,block_info.filepos,
(uint) block_info.data_len,
@@ -1142,9 +1149,12 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
}
param->testflag|=T_REP; /* for easy checking */
+ if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
+ param->testflag|=T_CALC_CHECKSUM;
+
if (!param->using_global_keycache)
- VOID(init_key_cache(dflt_keycache, param->key_cache_block_size,
- param->use_buffers, &dflt_key_cache_var));
+ VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
+ param->use_buffers, 0, 0));
if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
@@ -1163,7 +1173,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
MYF(0))) ||
!mi_alloc_rec_buff(info, -1, &sort_param.rec_buff))
{
- mi_check_print_error(param,"Not enough memory for extra record");
+ mi_check_print_error(param, "Not enough memory for extra record");
goto err;
}
@@ -1355,6 +1365,7 @@ err:
VOID(my_close(new_file,MYF(0)));
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
MYF(MY_WME)));
+ info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
}
mi_mark_crashed_on_repair(info);
}
@@ -1365,7 +1376,7 @@ err:
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache));
- got_error|=flush_blocks(param, *share->key_cache, share->kfile);
+ got_error|=flush_blocks(param, share->key_cache, share->kfile);
if (!got_error && param->testflag & T_UNPACK)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
@@ -1501,7 +1512,7 @@ void lock_memory(MI_CHECK *param __attribute__((unused)))
/* Flush all changed blocks to disk */
-int flush_blocks(MI_CHECK *param, KEY_CACHE_HANDLE key_cache, File file)
+int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file)
{
if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
{
@@ -1564,7 +1575,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
}
/* Flush key cache for this file if we are calling this outside myisamchk */
- flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */
@@ -1625,7 +1636,7 @@ static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
{
- mi_check_print_error(param,"Not Enough memory");
+ mi_check_print_error(param,"Not enough memory for key block");
DBUG_RETURN(-1);
}
if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
@@ -1811,6 +1822,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
}
param->testflag|=T_REP; /* for easy checking */
+ if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
+ param->testflag|=T_CALC_CHECKSUM;
+
bzero((char*)&sort_info,sizeof(sort_info));
bzero((char *)&sort_param, sizeof(sort_param));
if (!(sort_info.key_block=
@@ -1834,7 +1848,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
MYF(0))) ||
!mi_alloc_rec_buff(info, -1, &sort_param.rec_buff))
{
- mi_check_print_error(param,"Not enough memory for extra record");
+ mi_check_print_error(param, "Not enough memory for extra record");
goto err;
}
if (!rep_quick)
@@ -1874,7 +1888,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside
myisamchk
*/
- flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
@@ -1884,7 +1898,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
}
else
{
- if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
+ if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
@@ -2076,7 +2090,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param, *share->key_cache, share->kfile);
+ got_error|= flush_blocks(param, share->key_cache, share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@@ -2182,6 +2196,9 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
}
param->testflag|=T_REP; /* for easy checking */
+ if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
+ param->testflag|=T_CALC_CHECKSUM;
+
bzero((char*)&sort_info,sizeof(sort_info));
if (!(sort_info.key_block=
alloc_key_blocks(param,
@@ -2237,7 +2254,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
Flush key cache for this file if we are calling this outside
myisamchk
*/
- flush_key_blocks(*share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
+ flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
@@ -2247,7 +2264,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
}
else
{
- if (flush_key_blocks(*share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
+ if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE))
goto err;
key_map= ~key_map; /* Create the missing keys */
}
@@ -2267,17 +2284,19 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
rec_length=share->base.min_block_length;
else
rec_length=share->base.pack_reclength;
+ /*
+ +1 below is required hack for parallel repair mode.
+ The info->state->records value, that is compared later
+ to sort_info.max_records and cannot exceed it, is
+ increased in sort_key_write. In mi_repair_by_sort, sort_key_write
+ is called after sort_key_read, where the comparison is performed,
+ but in parallel mode master thread can call sort_key_write
+ before some other repair thread calls sort_key_read.
+ Furthermore I'm not even sure +1 would be enough.
+ May be sort_info.max_records shold be always set to max value in
+ parallel mode.
+ */
sort_info.max_records=
- /* +1 below is required hack for parallel repair mode.
- The info->state->records value, that is compared later
- to sort_info.max_records and cannot exceed it, is
- increased in sort_key_write. In mi_repair_by_sort, sort_key_write
- is called after sort_key_read, where the comparison is performed,
- but in parallel mode master thread can call sort_key_write
- before some other repair thread calls sort_key_read.
- Furthermore I'm not even sure +1 would be enough.
- May be sort_info.max_records shold be always set to max value in
- parallel mode. */
((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records + 1:
(ha_rows) (sort_info.filelength/rec_length+1));
@@ -2291,7 +2310,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
(sizeof(MI_SORT_PARAM) + share->base.pack_reclength),
MYF(MY_ZEROFILL))))
{
- mi_check_print_error(param,"Not enough memory!");
+ mi_check_print_error(param,"Not enough memory for key!");
goto err;
}
total_key_length=0;
@@ -2483,7 +2502,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
- got_error|= flush_blocks(param, *share->key_cache, share->kfile);
+ got_error|= flush_blocks(param, share->key_cache, share->kfile);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@@ -2847,9 +2866,20 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
if (!(to=mi_alloc_rec_buff(info,block_info.rec_len,
&(sort_param->rec_buff))))
{
- mi_check_print_error(param,"Not enough memory for blob at %s",
- llstr(sort_param->start_recpos,llbuff));
- DBUG_RETURN(1);
+ if (param->max_record_length >= block_info.rec_len)
+ {
+ mi_check_print_error(param,"Not enough memory for blob at %s (need %lu)",
+ llstr(sort_param->start_recpos,llbuff),
+ (ulong) block_info.rec_len);
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ mi_check_print_info(param,"Not enough memory for blob at %s (need %lu); Row skipped",
+ llstr(sort_param->start_recpos,llbuff),
+ (ulong) block_info.rec_len);
+ goto try_next;
+ }
}
}
else
@@ -2857,14 +2887,16 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param)
}
if (left_length < block_info.data_len || ! block_info.data_len)
{
- mi_check_print_info(param,"Found block with too small length at %s; Skipped",
+ mi_check_print_info(param,
+ "Found block with too small length at %s; Skipped",
llstr(sort_param->start_recpos,llbuff));
goto try_next;
}
if (block_info.filepos + block_info.data_len >
sort_param->read_cache.end_of_file)
{
- mi_check_print_info(param,"Found block that points outside data file at %s",
+ mi_check_print_info(param,
+ "Found block that points outside data file at %s",
llstr(sort_param->start_recpos,llbuff));
goto try_next;
}
@@ -3269,30 +3301,28 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
ft_buf->buf=0;
return error;
}
- else
- {
- /* flushing buffer */
- if ((error=sort_ft_buf_flush(sort_param)))
- return error;
-word_init_ft_buf:
- a_len+=val_len;
- memcpy(ft_buf->lastkey, a, a_len);
- ft_buf->buf=ft_buf->lastkey+a_len;
- ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
- /* 32 is just a safety margin here
- (at least max(val_len, sizeof(nod_flag)) should be there).
- May be better performance could be achieved if we'd put
- (sort_info->keyinfo->block_length-32)/XXX
- instead.
- TODO: benchmark the best value for XXX.
- */
+ /* flushing buffer */
+ if ((error=sort_ft_buf_flush(sort_param)))
+ return error;
- return 0;
- }
- return -1; /* impossible */
+word_init_ft_buf:
+ a_len+=val_len;
+ memcpy(ft_buf->lastkey, a, a_len);
+ ft_buf->buf=ft_buf->lastkey+a_len;
+ /*
+ 32 is just a safety margin here
+ (at least max(val_len, sizeof(nod_flag)) should be there).
+ May be better performance could be achieved if we'd put
+ (sort_info->keyinfo->block_length-32)/XXX
+ instead.
+ TODO: benchmark the best value for XXX.
+ */
+ ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
+ return 0;
} /* sort_ft_key_write */
+
/* get pointer to record from a key */
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
@@ -3499,7 +3529,7 @@ static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
buffer_length+IO_SIZE)*blocks,
MYF(0))))
{
- mi_check_print_error(param,"Not Enough memory for sort-key-blocks");
+ mi_check_print_error(param,"Not enough memory for sort-key-blocks");
return(0);
}
for (i=0 ; i < blocks ; i++)