Commit 3411bfe0 authored by unknown's avatar unknown

merge from MyISAM into Maria (last step of merge of 5.1 into Maria).

Tests: "maria" and "ps_maria" fail like before merge (assertions),
"ma_test_all" fails like before merge (ma_test2 segfaults, I'll try
to find out why).


mysys/mf_pagecache.c:
  using a more distinctive tag
storage/maria/ha_maria.cc:
  merge from MyISAM into Maria
storage/maria/ma_check.c:
  merge from MyISAM into Maria
storage/maria/ma_close.c:
  TODO as a word
storage/maria/ma_create.c:
  merge from MyISAM into Maria
storage/maria/ma_delete_all.c:
  TODO as a word
storage/maria/ma_delete_table.c:
  TODO as a word
storage/maria/ma_dynrec.c:
  merge from MyISAM into Maria
storage/maria/ma_extra.c:
  merge from MyISAM into Maria
storage/maria/ma_ft_boolean_search.c:
  merge from MyISAM into Maria
storage/maria/ma_locking.c:
  merge from MyISAM into Maria
storage/maria/ma_loghandler.c:
  fix for compiler warning
storage/maria/ma_open.c:
  merge from MyISAM into Maria.
  I will ask Monty to check the ASKMONTY-marked piece of code.
storage/maria/ma_packrec.c:
  merge from MyISAM into Maria
storage/maria/ma_range.c:
  merge from MyISAM into Maria
storage/maria/ma_rename.c:
  TODO as a word
storage/maria/ma_rt_index.c:
  merge from MyISAM into Maria
storage/maria/ma_rt_split.c:
  merge from MyISAM into Maria
storage/maria/ma_search.c:
  merge from MyISAM into Maria
storage/maria/ma_sort.c:
  merge from MyISAM into Maria
storage/maria/ma_update.c:
  merge from MyISAM into Maria
storage/maria/ma_write.c:
  merge from MyISAM into Maria
storage/maria/maria_chk.c:
  merge from MyISAM into Maria
storage/maria/maria_def.h:
  merge from MyISAM into Maria
storage/maria/maria_pack.c:
  merge from MyISAM into Maria
storage/maria/unittest/ma_test_loghandler_pagecache-t.c:
  fix for compiler warning
storage/myisam/ha_myisam.cc:
  merge from MyISAM into Maria
storage/myisammrg/ha_myisammrg.cc:
  merge from MyISAM into Maria
parent ea57b3d4
...@@ -3228,7 +3228,8 @@ restart: ...@@ -3228,7 +3228,8 @@ restart:
int rc= int rc=
#endif #endif
/* /*
QQ: We are doing an unlock here, so need to give the page its rec_lsn RECOVERY TODO BUG We are doing an unlock here, so need to give the
page its rec_lsn
*/ */
make_lock_and_pin(pagecache, block, make_lock_and_pin(pagecache, block,
write_lock_change_table[lock].unlock_lock, write_lock_change_table[lock].unlock_lock,
...@@ -3590,8 +3591,8 @@ restart: ...@@ -3590,8 +3591,8 @@ restart:
else else
{ {
/* Link the block into a list of blocks 'in switch' */ /* Link the block into a list of blocks 'in switch' */
/* QQ: /*
#warning this unlink_changed() is a serious problem for RECOVERY TODO BUG this unlink_changed() is a serious problem for
Maria's Checkpoint: it removes a page from the list of dirty Maria's Checkpoint: it removes a page from the list of dirty
pages, while it's still dirty. A solution is to abandon pages, while it's still dirty. A solution is to abandon
first_in_switch, just wait for this page to be first_in_switch, just wait for this page to be
......
This diff is collapsed.
...@@ -2310,6 +2310,12 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, my_string name) ...@@ -2310,6 +2310,12 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, my_string name)
MARIA_STATE_INFO old_state; MARIA_STATE_INFO old_state;
DBUG_ENTER("maria_sort_index"); DBUG_ENTER("maria_sort_index");
/* cannot sort index files with R-tree indexes */
for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
key++,keyinfo++)
if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
DBUG_RETURN(0);
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
printf("- Sorting index for MARIA-table '%s'\n",name); printf("- Sorting index for MARIA-table '%s'\n",name);
...@@ -2402,6 +2408,8 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, ...@@ -2402,6 +2408,8 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
char llbuff[22]; char llbuff[22];
DBUG_ENTER("sort_one_index"); DBUG_ENTER("sort_one_index");
/* cannot walk over R-tree indices */
DBUG_ASSERT(keyinfo->key_alg != HA_KEY_ALG_RTREE);
new_page_pos=param->new_file_pos; new_page_pos=param->new_file_pos;
param->new_file_pos+=keyinfo->block_length; param->new_file_pos+=keyinfo->block_length;
......
...@@ -59,7 +59,7 @@ int maria_close(register MARIA_HA *info) ...@@ -59,7 +59,7 @@ int maria_close(register MARIA_HA *info)
} }
flag= !--share->reopen; flag= !--share->reopen;
/* /*
RECOVERYTODO: RECOVERY TODO:
If "flag" is TRUE, in the line below we are going to make the table If "flag" is TRUE, in the line below we are going to make the table
unknown to future checkpoints, so it needs to have fsync'ed itself unknown to future checkpoints, so it needs to have fsync'ed itself
entirely (bitmap, pages, etc) at this point. entirely (bitmap, pages, etc) at this point.
......
...@@ -921,7 +921,7 @@ int maria_create(const char *name, enum data_file_type record_type, ...@@ -921,7 +921,7 @@ int maria_create(const char *name, enum data_file_type record_type,
if (my_close(file,MYF(0))) if (my_close(file,MYF(0)))
goto err; goto err;
/* /*
RECOVERYTODO RECOVERY TODO
Write a log record describing the CREATE operation (just the file Write a log record describing the CREATE operation (just the file
names, link names, and the full header's content). names, link names, and the full header's content).
For this record to be of any use for Recovery, we need the upper For this record to be of any use for Recovery, we need the upper
...@@ -967,18 +967,19 @@ uint maria_get_pointer_length(ulonglong file_length, uint def) ...@@ -967,18 +967,19 @@ uint maria_get_pointer_length(ulonglong file_length, uint def)
if (file_length) /* If not default */ if (file_length) /* If not default */
{ {
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS #ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
if (file_length >= (longlong) 1 << 56) if (file_length >= (ULL(1) << 56))
def=8; def=8;
else
#endif #endif
if (file_length >= (longlong) 1 << 48) if (file_length >= (ULL(1) << 48))
def=7; def=7;
if (file_length >= (longlong) 1 << 40) else if (file_length >= (ULL(1) << 40))
def=6; def=6;
else if (file_length >= (longlong) 1 << 32) else if (file_length >= (ULL(1) << 32))
def=5; def=5;
else if (file_length >= (1L << 24)) else if (file_length >= (ULL(1) << 24))
def=4; def=4;
else if (file_length >= (1L << 16)) else if (file_length >= (ULL(1) << 16))
def=3; def=3;
else else
def=2; def=2;
......
...@@ -30,7 +30,7 @@ int maria_delete_all_rows(MARIA_HA *info) ...@@ -30,7 +30,7 @@ int maria_delete_all_rows(MARIA_HA *info)
{ {
DBUG_RETURN(my_errno=EACCES); DBUG_RETURN(my_errno=EACCES);
} }
/* LOCKTODO take X-lock on table here */ /* LOCK TODO take X-lock on table here */
if (_ma_readinfo(info,F_WRLCK,1)) if (_ma_readinfo(info,F_WRLCK,1))
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
if (_ma_mark_file_changed(info)) if (_ma_mark_file_changed(info))
...@@ -54,7 +54,7 @@ int maria_delete_all_rows(MARIA_HA *info) ...@@ -54,7 +54,7 @@ int maria_delete_all_rows(MARIA_HA *info)
*/ */
flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
/* /*
RECOVERYTODO Log the two chsize and header modifications and force the RECOVERY TODO Log the two chsize and header modifications and force the
log. So that if crash between the two chsize, we finish the work at log. So that if crash between the two chsize, we finish the work at
Recovery. For this scenario: Recovery. For this scenario:
"TRUNCATE TABLE t1; DROP TABLE t1; RENAME TABLE t2 to t1; crash;" "TRUNCATE TABLE t1; DROP TABLE t1; RENAME TABLE t2 to t1; crash;"
...@@ -66,7 +66,7 @@ int maria_delete_all_rows(MARIA_HA *info) ...@@ -66,7 +66,7 @@ int maria_delete_all_rows(MARIA_HA *info)
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) ) my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err; goto err;
/* /*
RECOVERYTODO Consider updating ZeroDirtyPagesLSN here. It is RECOVERY TODO Consider updating ZeroDirtyPagesLSN here. It is
not a necessity (it is one only in RENAME commands) but an optional not a necessity (it is one only in RENAME commands) but an optional
optimization which will allow some REDO skipping at Recovery. optimization which will allow some REDO skipping at Recovery.
*/ */
...@@ -78,7 +78,7 @@ int maria_delete_all_rows(MARIA_HA *info) ...@@ -78,7 +78,7 @@ int maria_delete_all_rows(MARIA_HA *info)
rw_unlock(&info->s->mmap_lock); rw_unlock(&info->s->mmap_lock);
#endif #endif
/* /*
RECOVERYTODO Until we have the TRUNCATE log record and take it into RECOVERY TODO Until we have the TRUNCATE log record and take it into
account for log-low-water-mark calculation and use it in Recovery, we need account for log-low-water-mark calculation and use it in Recovery, we need
to sync. to sync.
*/ */
...@@ -90,10 +90,10 @@ int maria_delete_all_rows(MARIA_HA *info) ...@@ -90,10 +90,10 @@ int maria_delete_all_rows(MARIA_HA *info)
err: err:
{ {
int save_errno=my_errno; int save_errno=my_errno;
/* RECOVERYTODO log the header modifications */ /* RECOVERY TODO log the header modifications */
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */ info->update|=HA_STATE_WRITTEN; /* Buffer changed */
/* RECOVERYTODO until we log above we have to sync */ /* RECOVERY TODO until we log above we have to sync */
if (_ma_sync_table_files(info) && !save_errno) if (_ma_sync_table_files(info) && !save_errno)
save_errno= my_errno; save_errno= my_errno;
allow_break(); /* Allow SIGHUP & SIGINT */ allow_break(); /* Allow SIGHUP & SIGINT */
......
...@@ -31,7 +31,7 @@ int maria_delete_table(const char *name) ...@@ -31,7 +31,7 @@ int maria_delete_table(const char *name)
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
_ma_check_table_is_closed(name,"delete"); _ma_check_table_is_closed(name,"delete");
#endif #endif
/* LOCKTODO take X-lock on table here */ /* LOCK TODO take X-lock on table here */
#ifdef USE_RAID #ifdef USE_RAID
{ {
MARIA_HA *info; MARIA_HA *info;
...@@ -61,7 +61,7 @@ int maria_delete_table(const char *name) ...@@ -61,7 +61,7 @@ int maria_delete_table(const char *name)
fn_format(from,name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); fn_format(from,name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
/* /*
RECOVERYTODO log the two deletes below. RECOVERY TODO log the two deletes below.
Then do the file deletions. Then do the file deletions.
For this log record to be of any use for Recovery, we need the upper MySQL For this log record to be of any use for Recovery, we need the upper MySQL
layer to be crash-safe in DDLs; when it is we should reconsider the moment layer to be crash-safe in DDLs; when it is we should reconsider the moment
......
...@@ -69,6 +69,14 @@ my_bool _ma_dynmap_file(MARIA_HA *info, my_off_t size) ...@@ -69,6 +69,14 @@ my_bool _ma_dynmap_file(MARIA_HA *info, my_off_t size)
DBUG_PRINT("warning", ("File is too large for mmap")); DBUG_PRINT("warning", ("File is too large for mmap"));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/*
Ingo wonders if it is good to use MAP_NORESERVE. From the Linux man page:
MAP_NORESERVE
Do not reserve swap space for this mapping. When swap space is
reserved, one has the guarantee that it is possible to modify the
mapping. When swap space is not reserved one might get SIGSEGV
upon a write if no physical memory is available.
*/
info->s->file_map= (byte*) info->s->file_map= (byte*)
my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN), my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN),
info->s->mode==O_RDONLY ? PROT_READ : info->s->mode==O_RDONLY ? PROT_READ :
...@@ -252,7 +260,7 @@ my_bool _ma_write_blob_record(MARIA_HA *info, const byte *record) ...@@ -252,7 +260,7 @@ my_bool _ma_write_blob_record(MARIA_HA *info, const byte *record)
_ma_calc_total_blob_length(info,record)+ extra); _ma_calc_total_blob_length(info,record)+ extra);
if (!(rec_buff=(byte*) my_alloca(reclength))) if (!(rec_buff=(byte*) my_alloca(reclength)))
{ {
my_errno=ENOMEM; my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(1); return(1);
} }
reclength2= _ma_rec_pack(info, reclength2= _ma_rec_pack(info,
...@@ -289,7 +297,7 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, ...@@ -289,7 +297,7 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos,
#endif #endif
if (!(rec_buff=(byte*) my_alloca(reclength))) if (!(rec_buff=(byte*) my_alloca(reclength)))
{ {
my_errno=ENOMEM; my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(1); return(1);
} }
reclength= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), reclength= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
...@@ -1225,8 +1233,10 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from, ...@@ -1225,8 +1233,10 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
{ {
uint size_length=rec_length- maria_portable_sizeof_char_ptr; uint size_length=rec_length- maria_portable_sizeof_char_ptr;
ulong blob_length= _ma_calc_blob_length(size_length,from); ulong blob_length= _ma_calc_blob_length(size_length,from);
if ((ulong) (from_end-from) - size_length < blob_length || ulong from_left= (ulong) (from_end - from);
min_pack_length > (uint) (from_end -(from+size_length+blob_length))) if (from_left < size_length ||
from_left - size_length < blob_length ||
from_left - size_length - blob_length < min_pack_length)
goto err; goto err;
memcpy((byte*) to,(byte*) from,(size_t) size_length); memcpy((byte*) to,(byte*) from,(size_t) size_length);
from+=size_length; from+=size_length;
......
...@@ -355,7 +355,12 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, ...@@ -355,7 +355,12 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
case HA_EXTRA_MMAP: case HA_EXTRA_MMAP:
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
pthread_mutex_lock(&share->intern_lock); pthread_mutex_lock(&share->intern_lock);
if (!share->file_map) /*
Memory map the data file if it is not already mapped and if there
are no other threads using this table. intern_lock prevents other
threads from starting to use the table while we are mapping it.
*/
if (!share->file_map && (share->tot_locks == 1))
{ {
if (_ma_dynmap_file(info, share->state.state.data_file_length)) if (_ma_dynmap_file(info, share->state.state.data_file_length))
{ {
......
...@@ -676,7 +676,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_ ...@@ -676,7 +676,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
FT_SEG_ITERATOR ftsi; FT_SEG_ITERATOR ftsi;
FTB_EXPR *ftbe; FTB_EXPR *ftbe;
float weight=ftbw->weight; float weight=ftbw->weight;
int yn=ftbw->flags, ythresh, mode=(ftsi_orig != 0); int yn_flag= ftbw->flags, ythresh, mode=(ftsi_orig != 0);
my_off_t curdoc=ftbw->docid[mode]; my_off_t curdoc=ftbw->docid[mode];
struct st_mysql_ftparser *parser= ftb->keynr == NO_SUCH_KEY ? struct st_mysql_ftparser *parser= ftb->keynr == NO_SUCH_KEY ?
&ft_default_parser : &ft_default_parser :
...@@ -693,13 +693,13 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_ ...@@ -693,13 +693,13 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
} }
if (ftbe->nos) if (ftbe->nos)
break; break;
if (yn & FTB_FLAG_YES) if (yn_flag & FTB_FLAG_YES)
{ {
weight /= ftbe->ythresh; weight /= ftbe->ythresh;
ftbe->cur_weight += weight; ftbe->cur_weight += weight;
if ((int) ++ftbe->yesses == ythresh) if ((int) ++ftbe->yesses == ythresh)
{ {
yn=ftbe->flags; yn_flag=ftbe->flags;
weight=ftbe->cur_weight*ftbe->weight; weight=ftbe->cur_weight*ftbe->weight;
if (mode && ftbe->phrase) if (mode && ftbe->phrase)
{ {
...@@ -720,14 +720,14 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_ ...@@ -720,14 +720,14 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
break; break;
} }
else else
if (yn & FTB_FLAG_NO) if (yn_flag & FTB_FLAG_NO)
{ {
/* /*
NOTE: special sort function of queue assures that all NOTE: special sort function of queue assures that all
(yn & FTB_FLAG_NO) != 0 (yn_flag & FTB_FLAG_NO) != 0
events for every particular subexpression will events for every particular subexpression will
"auto-magically" happen BEFORE all the "auto-magically" happen BEFORE all the
(yn & FTB_FLAG_YES) != 0 events. So no (yn_flag & FTB_FLAG_YES) != 0 events. So no
already matched expression can become not-matched again. already matched expression can become not-matched again.
*/ */
++ftbe->nos; ++ftbe->nos;
...@@ -740,8 +740,8 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_ ...@@ -740,8 +740,8 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
ftbe->cur_weight += weight; ftbe->cur_weight += weight;
if ((int) ftbe->yesses < ythresh) if ((int) ftbe->yesses < ythresh)
break; break;
if (!(yn & FTB_FLAG_WONLY)) if (!(yn_flag & FTB_FLAG_WONLY))
yn= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : FTB_FLAG_WONLY ; yn_flag= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : FTB_FLAG_WONLY ;
weight*= ftbe->weight; weight*= ftbe->weight;
} }
} }
......
...@@ -291,6 +291,15 @@ void _ma_update_status(void* param) ...@@ -291,6 +291,15 @@ void _ma_update_status(void* param)
} }
} }
void _ma_restore_status(void *param)
{
MARIA_HA *info= (MARIA_HA*) param;
info->state= &info->s->state.state;
info->append_insert_at_end= 0;
}
void _ma_copy_status(void* to,void *from) void _ma_copy_status(void* to,void *from)
{ {
((MARIA_HA*) to)->state= &((MARIA_HA*) from)->save_state; ((MARIA_HA*) to)->state= &((MARIA_HA*) from)->save_state;
......
...@@ -799,7 +799,7 @@ static void translog_put_sector_protection(byte *page, ...@@ -799,7 +799,7 @@ static void translog_put_sector_protection(byte *page,
static uint32 translog_crc(byte *area, uint length) static uint32 translog_crc(byte *area, uint length)
{ {
return crc32(0L, area, length); return crc32(0L, (unsigned char*) area, length);
} }
......
...@@ -310,7 +310,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -310,7 +310,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++) for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
{ {
disk_pos=_ma_keyseg_read(disk_pos, pos); disk_pos=_ma_keyseg_read(disk_pos, pos);
if (pos->flag & HA_BLOB_PART &&
! (share->options & (HA_OPTION_COMPRESS_RECORD |
HA_OPTION_PACK_RECORD)))
{
my_errno= HA_ERR_CRASHED;
goto err;
}
if (pos->type == HA_KEYTYPE_TEXT || if (pos->type == HA_KEYTYPE_TEXT ||
pos->type == HA_KEYTYPE_VARTEXT1 || pos->type == HA_KEYTYPE_VARTEXT1 ||
pos->type == HA_KEYTYPE_VARTEXT2) pos->type == HA_KEYTYPE_VARTEXT2)
...@@ -346,11 +352,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -346,11 +352,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
} }
else else
{ {
uint j; uint k;
share->keyinfo[i].seg=pos; share->keyinfo[i].seg=pos;
for (j=0; j < FT_SEGS; j++) for (k=0; k < FT_SEGS; k++)
{ {
*pos= ft_keysegs[j]; *pos= ft_keysegs[k];
pos[0].language= pos[-1].language; pos[0].language= pos[-1].language;
if (!(pos[0].charset= pos[-1].charset)) if (!(pos[0].charset= pos[-1].charset))
{ {
...@@ -444,6 +450,32 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -444,6 +450,32 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
} }
} }
share->rec[i].type=(int) FIELD_LAST; /* End marker */ share->rec[i].type=(int) FIELD_LAST; /* End marker */
#ifdef ASKMONTY
/*
This code was added to mi_open.c in this cset:
"ChangeSet 1.1616.2941.5 2007/01/22 16:34:58 svoj@mysql.com
BUG#24401 - MySQL server crashes if you try to retrieve data from
corrupted table
Accessing a table with corrupted column definition results in server
crash.
This is fixed by refusing to open such tables. Affects MyISAM only.
No test case, since it requires crashed table.
storage/myisam/mi_open.c 1.80.2.10 2007/01/22 16:34:57 svoj@mysql.com
Refuse to open MyISAM table with summary columns length bigger than
length of the record."
The problem is that the "offset" variable was removed (by Monty in the
rows-in-block patch). Monty will know how to merge that.
Guilhem will make sure to notify him.
*/
if (offset > share->base.reclength)
{
/* purecov: begin inspected */
my_errno= HA_ERR_CRASHED;
goto err;
/* purecov: end */
}
#endif /* ASKMONTY */
if (_ma_open_datafile(&info, share, -1)) if (_ma_open_datafile(&info, share, -1))
goto err; goto err;
...@@ -465,6 +497,22 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -465,6 +497,22 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
_ma_setup_functions(share); _ma_setup_functions(share);
if ((*share->once_init)(share, info.dfile)) if ((*share->once_init)(share, info.dfile))
goto err; goto err;
if (open_flags & HA_OPEN_MMAP)
{
info.s= share;
if (_ma_dynmap_file(&info, share->state.state.data_file_length))
{
/* purecov: begin inspected */
/* Ignore if mmap fails. Use file I/O instead. */
DBUG_PRINT("warning", ("mmap failed: errno: %d", errno));
/* purecov: end */
}
else
{
share->file_read= _ma_mmap_pread;
share->file_write= _ma_mmap_pwrite;
}
}
share->is_log_table= FALSE; share->is_log_table= FALSE;
#ifdef THREAD #ifdef THREAD
thr_lock_init(&share->lock); thr_lock_init(&share->lock);
...@@ -491,6 +539,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -491,6 +539,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->lock.get_status=_ma_get_status; share->lock.get_status=_ma_get_status;
share->lock.copy_status=_ma_copy_status; share->lock.copy_status=_ma_copy_status;
share->lock.update_status=_ma_update_status; share->lock.update_status=_ma_update_status;
share->lock.restore_status=_ma_restore_status;
share->lock.check_status=_ma_check_status; share->lock.check_status=_ma_check_status;
} }
} }
......
This diff is collapsed.
...@@ -170,6 +170,7 @@ static double _ma_search_pos(register MARIA_HA *info, ...@@ -170,6 +170,7 @@ static double _ma_search_pos(register MARIA_HA *info,
byte *keypos, *buff; byte *keypos, *buff;
double offset; double offset;
DBUG_ENTER("_ma_search_pos"); DBUG_ENTER("_ma_search_pos");
LINT_INIT(max_keynr);
if (pos == HA_OFFSET_ERROR) if (pos == HA_OFFSET_ERROR)
DBUG_RETURN(0.5); DBUG_RETURN(0.5);
......
...@@ -33,7 +33,7 @@ int maria_rename(const char *old_name, const char *new_name) ...@@ -33,7 +33,7 @@ int maria_rename(const char *old_name, const char *new_name)
_ma_check_table_is_closed(old_name,"rename old_table"); _ma_check_table_is_closed(old_name,"rename old_table");
_ma_check_table_is_closed(new_name,"rename new table2"); _ma_check_table_is_closed(new_name,"rename new table2");
#endif #endif
/* LOCKTODO take X-lock on table here */ /* LOCK TODO take X-lock on table here */
#ifdef USE_RAID #ifdef USE_RAID
{ {
MARIA_HA *info; MARIA_HA *info;
...@@ -51,7 +51,7 @@ int maria_rename(const char *old_name, const char *new_name) ...@@ -51,7 +51,7 @@ int maria_rename(const char *old_name, const char *new_name)
fn_format(from,old_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); fn_format(from,old_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
fn_format(to,new_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); fn_format(to,new_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
/* /*
RECOVERYTODO log the two renames below. Update RECOVERY TODO log the two renames below. Update
ZeroDirtyPagesLSN of the table on disk (=> sync the files), this is ZeroDirtyPagesLSN of the table on disk (=> sync the files), this is
needed so that Recovery does not pick a wrong table. needed so that Recovery does not pick a wrong table.
Then do the file renames. Then do the file renames.
......
...@@ -637,8 +637,6 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, byte *key, ...@@ -637,8 +637,6 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, byte *key,
if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
{ {
int res;
if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
return -1; return -1;
info->keybuff_used = 1; info->keybuff_used = 1;
...@@ -929,7 +927,6 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, byte *key, uint key_length) ...@@ -929,7 +927,6 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, byte *key, uint key_length)
ulong i; ulong i;
for (i = 0; i < ReinsertList.n_pages; ++i) for (i = 0; i < ReinsertList.n_pages; ++i)
{ {
uint nod_flag;
byte *page_buf, *k, *last; byte *page_buf, *k, *last;
if (!(page_buf = (byte*) my_alloca((uint)keyinfo->block_length))) if (!(page_buf = (byte*) my_alloca((uint)keyinfo->block_length)))
......
...@@ -188,6 +188,10 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, ...@@ -188,6 +188,10 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries,
int next_node; int next_node;
int i; int i;
SplitStruct *end = node + n_entries; SplitStruct *end = node + n_entries;
LINT_INIT(a);
LINT_INIT(b);
LINT_INIT(next);
LINT_INIT(next_node);
if (all_size < min_size * 2) if (all_size < min_size * 2)
{ {
......
...@@ -477,9 +477,9 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ...@@ -477,9 +477,9 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
else else
{ {
/* We have to compare k and vseg as if they were space extended */ /* We have to compare k and vseg as if they were space extended */
uchar *end= k+ (cmplen - len); uchar *k_end= k+ (cmplen - len);
for ( ; k < end && *k == ' '; k++) ; for ( ; k < k_end && *k == ' '; k++) ;
if (k == end) if (k == k_end)
goto cmp_rest; /* should never happen */ goto cmp_rest; /* should never happen */
if ((uchar) *k < (uchar) ' ') if ((uchar) *k < (uchar) ' ')
{ {
...@@ -491,15 +491,15 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ...@@ -491,15 +491,15 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} }
else if (len > cmplen) else if (len > cmplen)
{ {
uchar *end; uchar *vseg_end;
if ((nextflag & SEARCH_PREFIX) && key_len_left == 0) if ((nextflag & SEARCH_PREFIX) && key_len_left == 0)
goto fix_flag; goto fix_flag;
/* We have to compare k and vseg as if they were space extended */ /* We have to compare k and vseg as if they were space extended */
for (end=vseg + (len-cmplen) ; for (vseg_end= vseg + (len-cmplen) ;
vseg < end && *vseg == (byte) ' '; vseg < vseg_end && *vseg == (byte) ' ';
vseg++, matched++) ; vseg++, matched++) ;
DBUG_ASSERT(vseg < end); DBUG_ASSERT(vseg < vseg_end);
if ((uchar) *vseg > (uchar) ' ') if ((uchar) *vseg > (uchar) ' ')
{ {
......
...@@ -221,9 +221,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, ...@@ -221,9 +221,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
if (my_b_inited(&tempfile_for_exceptions)) if (my_b_inited(&tempfile_for_exceptions))
{ {
MARIA_HA *index=info->sort_info->info; MARIA_HA *idx=info->sort_info->info;
uint keyno=info->key; uint keyno=info->key;
uint key_length, ref_length=index->s->rec_reflength; uint key_length, ref_length=idx->s->rec_reflength;
if (!no_messages) if (!no_messages)
printf(" - Adding exceptions\n"); /* purecov: tested */ printf(" - Adding exceptions\n"); /* purecov: tested */
...@@ -236,7 +236,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, ...@@ -236,7 +236,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
&& !my_b_read(&tempfile_for_exceptions,(byte*)sort_keys, && !my_b_read(&tempfile_for_exceptions,(byte*)sort_keys,
(uint) key_length)) (uint) key_length))
{ {
if (_ma_ck_write(index,keyno,(byte*) sort_keys,key_length-ref_length)) if (_ma_ck_write(idx,keyno,(byte*) sort_keys,key_length-ref_length))
goto err; goto err;
} }
} }
......
...@@ -206,7 +206,8 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec) ...@@ -206,7 +206,8 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
err: err:
DBUG_PRINT("error",("key: %d errno: %d",i,my_errno)); DBUG_PRINT("error",("key: %d errno: %d",i,my_errno));
save_errno=my_errno; save_errno=my_errno;
if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL) if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM ||
my_errno == HA_ERR_RECORD_FILE_FULL)
{ {
info->errkey= (int) i; info->errkey= (int) i;
flag=0; flag=0;
......
...@@ -205,7 +205,8 @@ err: ...@@ -205,7 +205,8 @@ err:
fatal_error= 0; fatal_error= 0;
if (my_errno == HA_ERR_FOUND_DUPP_KEY || if (my_errno == HA_ERR_FOUND_DUPP_KEY ||
my_errno == HA_ERR_RECORD_FILE_FULL || my_errno == HA_ERR_RECORD_FILE_FULL ||
my_errno == HA_ERR_NULL_IN_SPATIAL) my_errno == HA_ERR_NULL_IN_SPATIAL ||
my_errno == HA_ERR_OUT_OF_MEM)
{ {
if (info->bulk_insert) if (info->bulk_insert)
{ {
...@@ -629,6 +630,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ...@@ -629,6 +630,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
my_off_t new_pos; my_off_t new_pos;
MARIA_KEY_PARAM s_temp; MARIA_KEY_PARAM s_temp;
DBUG_ENTER("maria_split_page"); DBUG_ENTER("maria_split_page");
LINT_INIT(after_key);
DBUG_DUMP("buff",(byte*) buff,maria_getint(buff)); DBUG_DUMP("buff",(byte*) buff,maria_getint(buff));
if (info->s->keyinfo+info->lastinx == keyinfo) if (info->s->keyinfo+info->lastinx == keyinfo)
......
...@@ -727,6 +727,7 @@ get_one_option(int optid, ...@@ -727,6 +727,7 @@ get_one_option(int optid,
case 2: case 2:
method_conv= MI_STATS_METHOD_IGNORE_NULLS; method_conv= MI_STATS_METHOD_IGNORE_NULLS;
break; break;
default: assert(0); /* Impossible */
} }
check_param.stats_method= method_conv; check_param.stats_method= method_conv;
break; break;
......
...@@ -817,6 +817,7 @@ my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b, ...@@ -817,6 +817,7 @@ my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b,
my_bool null_are_equal); my_bool null_are_equal);
void _ma_get_status(void *param, int concurrent_insert); void _ma_get_status(void *param, int concurrent_insert);
void _ma_update_status(void *param); void _ma_update_status(void *param);
void _ma_restore_status(void *param);
void _ma_copy_status(void *to, void *from); void _ma_copy_status(void *to, void *from);
my_bool _ma_check_status(void *param); my_bool _ma_check_status(void *param);
......
...@@ -2696,8 +2696,9 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) ...@@ -2696,8 +2696,9 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
} }
case FIELD_VARCHAR: case FIELD_VARCHAR:
{ {
uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1); uint var_pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos : ulong col_length= (var_pack_length == 1 ?
(uint) *(uchar*) start_pos :
uint2korr(start_pos)); uint2korr(start_pos));
/* Empty varchar are encoded with a single 1 bit. */ /* Empty varchar are encoded with a single 1 bit. */
if (!col_length) if (!col_length)
...@@ -2707,7 +2708,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) ...@@ -2707,7 +2708,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
} }
else else
{ {
byte *end=start_pos+pack_length+col_length; byte *end= start_pos + var_pack_length + col_length;
DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1")); DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1"));
write_bits(0,1); write_bits(0,1);
/* Write the varchar length. */ /* Write the varchar length. */
...@@ -2715,7 +2716,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) ...@@ -2715,7 +2716,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
col_length, count->length_bits)); col_length, count->length_bits));
write_bits(col_length,count->length_bits); write_bits(col_length,count->length_bits);
/* Encode the varchar bytes. */ /* Encode the varchar bytes. */
for (start_pos+=pack_length ; start_pos < end ; start_pos++) for (start_pos+= var_pack_length ; start_pos < end ; start_pos++)
{ {
DBUG_PRINT("fields", DBUG_PRINT("fields",
("value: 0x%02x code: 0x%s bits: %2u bin: %s", ("value: 0x%02x code: 0x%s bits: %2u bin: %s",
......
...@@ -21,7 +21,7 @@ static PAGECACHE_FILE file1; ...@@ -21,7 +21,7 @@ static PAGECACHE_FILE file1;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
uint pagen; uint pagen;
uchar long_tr_id[6]; byte long_tr_id[6];
PAGECACHE pagecache; PAGECACHE pagecache;
LSN lsn; LSN lsn;
MY_STAT st, *stat; MY_STAT st, *stat;
......
...@@ -293,7 +293,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, ...@@ -293,7 +293,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
Check for underlying table conformance Check for underlying table conformance
SYNOPSIS SYNOPSIS
check_definition() myisam_check_definition()
t1_keyinfo in First table key definition t1_keyinfo in First table key definition
t1_recinfo in First table record definition t1_recinfo in First table record definition
t1_keys in Number of keys in first table t1_keys in Number of keys in first table
...@@ -323,13 +323,13 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, ...@@ -323,13 +323,13 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
1 - Different definitions. 1 - Different definitions.
*/ */
int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, int myisam_check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
uint t1_keys, uint t1_recs, uint t1_keys, uint t1_recs,
MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo, MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
uint t2_keys, uint t2_recs, bool strict) uint t2_keys, uint t2_recs, bool strict)
{ {
uint i, j; uint i, j;
DBUG_ENTER("check_definition"); DBUG_ENTER("myisam_check_definition");
if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys)) if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
{ {
DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u", DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
......
...@@ -48,9 +48,11 @@ static const char *ha_myisammrg_exts[] = { ...@@ -48,9 +48,11 @@ static const char *ha_myisammrg_exts[] = {
}; };
extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
MI_COLUMNDEF **recinfo_out, uint *records_out); MI_COLUMNDEF **recinfo_out, uint *records_out);
extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, extern int myisam_check_definition(MI_KEYDEF *t1_keyinfo,
MI_COLUMNDEF *t1_recinfo,
uint t1_keys, uint t1_recs, uint t1_keys, uint t1_recs,
MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo, MI_KEYDEF *t2_keyinfo,
MI_COLUMNDEF *t2_recinfo,
uint t2_keys, uint t2_recs, bool strict); uint t2_keys, uint t2_recs, bool strict);
const char **ha_myisammrg::bas_ext() const const char **ha_myisammrg::bas_ext() const
...@@ -115,7 +117,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) ...@@ -115,7 +117,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
} }
for (u_table= file->open_tables; u_table < file->end_table; u_table++) for (u_table= file->open_tables; u_table < file->end_table; u_table++)
{ {
if (check_definition(keyinfo, recinfo, keys, recs, if (myisam_check_definition(keyinfo, recinfo, keys, recs,
u_table->table->s->keyinfo, u_table->table->s->rec, u_table->table->s->keyinfo, u_table->table->s->rec,
u_table->table->s->base.keys, u_table->table->s->base.keys,
u_table->table->s->base.fields, false)) u_table->table->s->base.fields, false))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment