summaryrefslogtreecommitdiff
path: root/myisam
diff options
context:
space:
mode:
Diffstat (limited to 'myisam')
-rw-r--r--myisam/ft_boolean_search.c24
-rw-r--r--myisam/mi_check.c2
-rw-r--r--myisam/mi_close.c6
-rw-r--r--myisam/mi_create.c13
-rw-r--r--myisam/mi_locking.c60
-rw-r--r--myisam/mi_open.c4
-rw-r--r--myisam/mi_test1.c2
-rw-r--r--myisam/myisam_ftdump.c2
-rw-r--r--myisam/myisamchk.c2
-rw-r--r--myisam/myisampack.c34
10 files changed, 109 insertions, 40 deletions
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 13f46849210..1958619c2dd 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -161,7 +161,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
if (param.trunc) ftbw->flags|=FTB_FLAG_TRUNC;
ftbw->weight=weight;
ftbw->up=up;
- ftbw->docid[0]=ftbw->docid[1]=HA_POS_ERROR;
+ ftbw->docid[0]=ftbw->docid[1]=HA_OFFSET_ERROR;
ftbw->ndepth= (param.yesno<0) + depth;
memcpy(ftbw->word+1, w.pos, w.len);
ftbw->word[0]=w.len;
@@ -177,7 +177,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
ftbe->weight=weight;
ftbe->up=up;
ftbe->ythresh=ftbe->yweaks=0;
- ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR;
+ ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
if ((ftbe->quot=param.quot)) ftb->with_scan|=2;
if (param.yesno > 0) up->ythresh++;
_ftb_parse_query(ftb, start, end, ftbe, depth+1);
@@ -245,9 +245,9 @@ static void _ftb_init_index_search(FT_INFO *ftb)
ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */
{
FTB_EXPR *top_ftbe=ftbe->up->up;
- ftbw->docid[0]=HA_POS_ERROR;
+ ftbw->docid[0]=HA_OFFSET_ERROR;
for (ftbe=ftbw->up; ftbe != top_ftbe; ftbe=ftbe->up)
- if (ftbe->flags & FTB_FLAG_YES)
+ if (!(ftbe->flags & FTB_FLAG_NO))
ftbe->yweaks++;
ftbe=0;
break;
@@ -255,7 +255,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
}
if (!ftbe)
continue;
- /* 3 */
+ /* 4 */
if (!is_tree_inited(& ftb->no_dupes))
init_tree(& ftb->no_dupes,0,0,sizeof(my_off_t),
_ftb_no_dupes_cmp,0,0,0);
@@ -319,7 +319,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
default_charset_info :
info->s->keyinfo[keynr].seg->charset);
ftb->with_scan=0;
- ftb->lastpos=HA_POS_ERROR;
+ ftb->lastpos=HA_OFFSET_ERROR;
bzero(& ftb->no_dupes, sizeof(TREE));
init_alloc_root(&ftb->mem_root, 1024, 1024);
@@ -342,7 +342,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftbe->quot=0;
ftbe->up=0;
ftbe->ythresh=ftbe->yweaks=0;
- ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR;
+ ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
ftb->root=ftbe;
_ftb_parse_query(ftb, &query, query+query_len, ftbe, 0);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
@@ -496,7 +496,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
while (ftb->state == INDEX_SEARCH &&
(curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid[0]) !=
- HA_POS_ERROR)
+ HA_OFFSET_ERROR)
{
while (curdoc==(ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
{
@@ -521,7 +521,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
}
if (r) /* not found */
{
- ftbw->docid[0]=HA_POS_ERROR;
+ ftbw->docid[0]=HA_OFFSET_ERROR;
if (ftbw->flags&FTB_FLAG_YES && ftbw->up->up==0)
{
/*
@@ -580,7 +580,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
const byte *end;
my_off_t docid=ftb->info->lastpos;
- if (docid == HA_POS_ERROR)
+ if (docid == HA_OFFSET_ERROR)
return -2.0;
if (!ftb->queue.elements)
return 0;
@@ -592,9 +592,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
for (i=0; i < ftb->queue.elements; i++)
{
- ftb->list[i]->docid[1]=HA_POS_ERROR;
+ ftb->list[i]->docid[1]=HA_OFFSET_ERROR;
for (x=ftb->list[i]->up; x; x=x->up)
- x->docid[1]=HA_POS_ERROR;
+ x->docid[1]=HA_OFFSET_ERROR;
}
}
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 078f7787dc3..e78d831fde7 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -3520,7 +3520,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
create_info.raid_chunksize= share.base.raid_chunksize;
create_info.language = (param->language ? param->language :
share.state.header.language);
-
+ create_info.key_file_length= status_info.key_file_length;
/* We don't have to handle symlinks here because we are using
HA_DONT_TOUCH_DATA */
if (mi_create(filename,
diff --git a/myisam/mi_close.c b/myisam/mi_close.c
index dbaaebb1143..2712f0ca283 100644
--- a/myisam/mi_close.c
+++ b/myisam/mi_close.c
@@ -70,6 +70,12 @@ int mi_close(register MI_INFO *info)
error=my_errno;
if (share->kfile >= 0)
{
+ /*
+ If we are crashed, we can safely flush the current state as it will
+ not change the crashed state.
+ We can NOT write the state in other cases as other threads
+ may be using the file at this point
+ */
if (share->mode != O_RDONLY && mi_is_crashed(info))
mi_state_info_write(share->kfile, &share->state, 1);
if (my_close(share->kfile,MYF(0)))
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 328450c70db..99e9ca5ba5f 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -46,7 +46,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
- ulonglong tot_length,max_rows;
+ ulonglong tot_length,max_rows, tmp;
enum en_fieldtype type;
MYISAM_SHARE share;
MI_KEYDEF *keydef,tmp_keydef;
@@ -442,10 +442,15 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.state.auto_increment=ci->auto_increment;
share.options=options;
share.base.rec_reflength=pointer;
+ /* Get estimate for index file length (this may be wrong for FT keys) */
+ tmp= (tot_length + max_key_block_length * keys *
+ MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
+ /*
+ use maximum of key_file_length we calculated and key_file_length value we
+ got from MYI file header (see also myisampack.c:save_state)
+ */
share.base.key_reflength=
- mi_get_pointer_length((tot_length + max_key_block_length * keys *
- MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH,
- 3);
+ mi_get_pointer_length(max(ci->key_file_length,tmp),3);
share.base.keys= share.state.header.keys = keys;
share.state.header.uniques= uniques;
mi_int2store(share.state.header.key_parts,key_segs);
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index f3bfa8deb90..d5212cdee47 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -19,7 +19,7 @@
reads info from a isam-table. Must be first request before doing any furter
calls to any isamfunktion. Is used to allow many process use the same
isamdatabase.
- */
+*/
#include "myisamdef.h"
#ifdef __WIN__
@@ -35,12 +35,17 @@ int mi_lock_database(MI_INFO *info, int lock_type)
MYISAM_SHARE *share=info->s;
uint flag;
DBUG_ENTER("mi_lock_database");
- DBUG_PRINT("info",("lock_type: %d", lock_type));
+ DBUG_PRINT("enter",("lock_type: %d old lock %d r_locks: %u w_locks: %u "
+ "global_changed: %d open_count: %u name: '%s'",
+ lock_type, info->lock_type, share->r_locks,
+ share->w_locks,
+ share->global_changed, share->state.open_count,
+ share->index_file_name));
if (share->options & HA_OPTION_READ_ONLY_DATA ||
info->lock_type == lock_type)
DBUG_RETURN(0);
- if (lock_type == F_EXTRA_LCK)
+ if (lock_type == F_EXTRA_LCK) /* Used by TMP tables */
{
++share->w_locks;
++share->tot_locks;
@@ -54,7 +59,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
{
switch (lock_type) {
case F_UNLCK:
- DBUG_PRINT("info", ("old lock: %d", info->lock_type));
if (info->lock_type == F_RDLCK)
count= --share->r_locks;
else
@@ -83,7 +87,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->state.process= share->last_process=share->this_process;
share->state.unique= info->last_unique= info->this_unique;
share->state.update_count= info->last_loop= ++info->this_loop;
- if (mi_state_info_write(share->kfile, &share->state, 1))
+ if (mi_state_info_write(share->kfile, &share->state, 1))
error=my_errno;
share->changed=0;
if (myisam_flush)
@@ -121,11 +125,17 @@ int mi_lock_database(MI_INFO *info, int lock_type)
break;
case F_RDLCK:
if (info->lock_type == F_WRLCK)
- { /* Change RW to READONLY */
+ {
+ /*
+ Change RW to READONLY
+
+ mysqld does not turn write locks to read locks,
+ so we're never here in mysqld.
+ */
if (share->w_locks == 1)
{
flag=1;
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
+ if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
MYF(MY_SEEK_NOT_DONE)))
{
error=my_errno;
@@ -333,9 +343,10 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
} /* _mi_readinfo */
- /* Every isam-function that uppdates the isam-database must! end */
- /* with this request */
- /* ARGSUSED */
+/*
+ Every isam-function that uppdates the isam-database MUST end with this
+ request
+*/
int _mi_writeinfo(register MI_INFO *info, uint operation)
{
@@ -402,12 +413,31 @@ int _mi_test_if_changed(register MI_INFO *info)
} /* _mi_test_if_changed */
-/* Put a mark in the .MYI file that someone is updating the table */
+/*
+ Put a mark in the .MYI file that someone is updating the table
+
+
+ DOCUMENTATION
+
+ state.open_count in the .MYI file is used the following way:
+ - For the first change of the .MYI file in this process open_count is
+ incremented by mi_mark_file_change(). (We have a write lock on the file
+ when this happens)
+ - In mi_close() it's decremented by _mi_decrement_open_count() if it
+ was incremented in the same process.
+
+ This mean that if we are the only process using the file, the open_count
+ tells us if the MYISAM file wasn't properly closed. (This is true if
+ my_disable_locking is set).
+*/
+
int _mi_mark_file_changed(MI_INFO *info)
{
char buff[3];
register MYISAM_SHARE *share=info->s;
+ DBUG_ENTER("_mi_mark_file_changed");
+
if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
{
share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
@@ -421,12 +451,12 @@ int _mi_mark_file_changed(MI_INFO *info)
{
mi_int2store(buff,share->state.open_count);
buff[2]=1; /* Mark that it's changed */
- return (my_pwrite(share->kfile,buff,sizeof(buff),
- sizeof(share->state.header),
- MYF(MY_NABP)));
+ DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff),
+ sizeof(share->state.header),
+ MYF(MY_NABP)));
}
}
- return 0;
+ DBUG_RETURN(0);
}
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 944a8af01e9..339ce2de291 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -188,7 +188,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share->state_diff_length=len-MI_STATE_INFO_SIZE;
if (share->state.header.fulltext_keys)
+ {
fprintf(stderr, "Warning: table file %s was created in MySQL 4.1+, use REPAIR TABLE ... USE_FRM to recreate it as a valid MySQL 4.0 table\n", name_buff);
+ my_errno=HA_ERR_UNSUPPORTED;
+ goto err;
+ }
mi_state_info_read(disk_cache, &share->state);
len= mi_uint2korr(share->state.header.base_info_length);
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index 88e6c5c89d3..8ea97c8e489 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -643,7 +643,7 @@ static void get_options(int argc, char *argv[])
{
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL)))
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
return;
diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c
index 35182bc8abb..838f90feae5 100644
--- a/myisam/myisam_ftdump.c
+++ b/myisam/myisam_ftdump.c
@@ -66,7 +66,7 @@ int main(int argc,char *argv[])
struct { MI_INFO *info; } aio0, *aio=&aio0; /* for GWS_IN_USE */
MY_INIT(argv[0]);
- if (error=handle_options(&argc, &argv, my_long_options, get_one_option, NULL))
+ if (error=handle_options(&argc, &argv, my_long_options, get_one_option))
exit(error);
if (count || dump)
verbose=0;
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index e8e85345897..5377ecc18a5 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -677,7 +677,7 @@ static void get_options(register int *argc,register char ***argv)
if (isatty(fileno(stdout)))
check_param.testflag|=T_WRITE_LOOP;
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL)))
+ if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
/* If using repair, then update checksum if one uses --update-state */
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 51f8ad1bb11..9f4e3bde65a 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -111,6 +111,8 @@ typedef struct st_isam_mrg {
uint ref_length;
uint max_blob_length;
my_off_t records;
+ /* true if at least one source file has at least one disabled index */
+ my_bool src_file_has_indexes_disabled;
} PACK_MRG_INFO;
@@ -350,7 +352,7 @@ static void get_options(int *argc,char ***argv)
if (isatty(fileno(stdout)))
write_loop=1;
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option, NULL)))
+ if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
if (!*argc)
@@ -413,10 +415,15 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count)
mrg->current=0;
mrg->file=(MI_INFO**) my_malloc(sizeof(MI_INFO*)*count,MYF(MY_FAE));
mrg->free_file=1;
+ mrg->src_file_has_indexes_disabled= 0;
for (i=0; i < count ; i++)
{
if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY)))
goto error;
+
+ mrg->src_file_has_indexes_disabled|= ((mrg->file[i]->s->state.key_map !=
+ (((ulonglong) 1) <<
+ mrg->file[i]->s->base. keys) - 1));
}
/* Check that files are identical */
for (j=0 ; j < count-1 ; j++)
@@ -2040,8 +2047,21 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
share->state.dellink= HA_OFFSET_ERROR;
share->state.split=(ha_rows) mrg->records;
share->state.version=(ulong) time((time_t*) 0);
+ if (share->state.key_map != (((ulonglong)1) << share->base.keys) - 1)
+ {
+ /*
+ Some indexes are disabled, cannot use current key_file_length value
+ as an estimate of upper bound of index file size. Use packed data file
+ size instead.
+ */
+ share->state.state.key_file_length= new_length;
+ }
+ /*
+ If there are no disabled indexes, keep key_file_length value from
+ original file so "myisamchk -rq" can use this value (this is necessary
+ because index size cannot be easily calculated for fulltext keys)
+ */
share->state.key_map=0;
- share->state.state.key_file_length=share->base.keystart;
for (key=0 ; key < share->base.keys ; key++)
share->state.key_root[key]= HA_OFFSET_ERROR;
for (key=0 ; key < share->state.header.max_block_size ; key++)
@@ -2050,8 +2070,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
share->changed=1; /* Force write of header */
share->state.open_count=0;
share->global_changed=0;
- VOID(my_chsize(share->kfile, share->state.state.key_file_length, 0,
- MYF(0)));
+ VOID(my_chsize(share->kfile, share->base.keystart, 0, MYF(0)));
if (share->base.keys)
isamchk_neaded=1;
DBUG_RETURN(mi_state_info_write(share->kfile,&share->state,1+2));
@@ -2074,7 +2093,12 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length,
state.state.del=0;
state.state.empty=0;
state.state.records=state.split=(ha_rows) mrg->records;
- state.state.key_file_length=isam_file->s->base.keystart;
+ /* See comment above in save_state about key_file_length handling. */
+ if (mrg->src_file_has_indexes_disabled)
+ {
+ isam_file->s->state.state.key_file_length=
+ max(isam_file->s->state.state.key_file_length, new_length);
+ }
state.dellink= HA_OFFSET_ERROR;
state.version=(ulong) time((time_t*) 0);
state.key_map=0;