summaryrefslogtreecommitdiff
path: root/myisam/myisampack.c
diff options
context:
space:
mode:
Diffstat (limited to 'myisam/myisampack.c')
-rw-r--r--myisam/myisampack.c89
1 files changed, 51 insertions, 38 deletions
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 90a14f6207c..39eaf8927a6 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -52,7 +52,7 @@ struct st_file_buffer {
char *buffer,*pos,*end;
my_off_t pos_in_file;
int bits;
- uint byte;
+ uint current_byte;
};
struct st_huff_tree;
@@ -242,12 +242,12 @@ static struct my_option my_long_options[] =
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"backup", 'b', "Make a backup of the table as table_name.OLD",
+ {"backup", 'b', "Make a backup of the table as table_name.OLD.",
(gptr*) &backup, (gptr*) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR_MP,
"Directory where character sets are.", (gptr*) &charsets_dir,
(gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
+ {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f',
"Force packing of table even if it gets bigger or if tempfile exists.",
@@ -618,14 +618,22 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
else
error=my_rename(new_name,org_name,MYF(MY_WME));
if (!error)
+ {
VOID(my_copystat(temp_name,org_name,MYF(MY_COPYTIME)));
+ if (tmp_dir[0])
+ VOID(my_delete(new_name,MYF(MY_WME)));
+ }
}
}
else
{
if (tmp_dir[0])
+ {
error=my_copy(new_name,org_name,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME));
+ if (!error)
+ VOID(my_delete(new_name,MYF(MY_WME)));
+ }
else
error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
}
@@ -686,7 +694,8 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records)
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,NULL,NULL);
+ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL,
+ NULL);
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
count[i].tree_pos=count[i].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
@@ -784,7 +793,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
if (count->tree_buff)
{
global_count=count;
- if (!(element=tree_insert(&count->int_tree,pos,0)) ||
+ if (!(element=tree_insert(&count->int_tree,pos, 0,
+ count->int_tree.custom_arg)) ||
(element->count == 1 &&
count->tree_buff + tree_buff_length <
count->tree_pos + count->field_length) ||
@@ -1090,7 +1100,7 @@ test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records,
{
int min_pos;
uint length_bits,i;
- my_off_t space_count,min_space_count,min_pack,new_length,skipp;
+ my_off_t space_count,min_space_count,min_pack,new_length,skip;
length_bits=max_bit(max_space_length);
@@ -1110,15 +1120,15 @@ test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records,
min_space_count=space_count;
}
/* Test with length-flag */
- for (skipp=0L, i=0 ; i < 8 ; i++)
+ for (skip=0L, i=0 ; i < 8 ; i++)
{
if (space_counts[i])
{
if (i)
huff_counts->counts[(uint) ' ']+=space_counts[i];
- skipp+=huff_counts->pre_space[i];
+ skip+=huff_counts->pre_space[i];
new_length=calc_packed_length(huff_counts,0)+
- (records+(records-skipp)*(1+length_bits))/8;
+ (records+(records-skip)*(1+length_bits))/8;
if (new_length < min_pack)
{
min_pos=(int) i;
@@ -1665,6 +1675,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
HUFF_COUNTS *count,*end_count;
HUFF_TREE *tree;
MI_INFO *isam_file=mrg->file[0];
+ uint pack_version= (uint) isam_file->s->pack.version;
DBUG_ENTER("compress_isam_file");
if (!(record=(byte*) my_alloca(isam_file->s->base.reclength)))
@@ -1692,23 +1703,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
huff_counts[i].tree->height+huff_counts[i].length_bits;
}
max_calc_length/=8;
- if (max_calc_length < 254)
- pack_ref_length=1;
- else if (max_calc_length <= 65535)
- pack_ref_length=3;
- else
- pack_ref_length=4;
+ pack_ref_length= calc_pack_length(pack_version, max_calc_length);
record_count=0;
- pack_blob_length=0;
- if (isam_file->s->base.blobs)
- {
- if (mrg->max_blob_length < 254)
- pack_blob_length=1;
- else if (mrg->max_blob_length <= 65535)
- pack_blob_length=3;
- else
- pack_blob_length=4;
- }
+ pack_blob_length= isam_file->s->base.blobs ?
+ calc_pack_length(pack_version, mrg->max_blob_length) : 0;
max_pack_length=pack_ref_length+pack_blob_length;
mrg_reset(mrg);
@@ -1717,7 +1715,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
ulong tot_blob_length=0;
if (! error)
{
- if (flush_buffer(max_calc_length+max_pack_length))
+ if (flush_buffer((ulong) max_calc_length + (ulong) max_pack_length))
break;
record_pos=file_buffer.pos;
file_buffer.pos+=max_pack_length;
@@ -1807,7 +1805,8 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
break;
case FIELD_INTERVALL:
global_count=count;
- pos=(byte*) tree_search(&count->int_tree,start_pos);
+ pos=(byte*) tree_search(&count->int_tree, start_pos,
+ count->int_tree.custom_arg);
intervall=(uint) (pos - count->tree_buff)/field_length;
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
start_pos=end_pos;
@@ -1863,9 +1862,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
flush_bits();
length=(ulong) (file_buffer.pos-record_pos)-max_pack_length;
- pack_length=save_pack_length(record_pos,length);
+ pack_length= save_pack_length(pack_version, record_pos, length);
if (pack_blob_length)
- pack_length+=save_pack_length(record_pos+pack_length,tot_blob_length);
+ pack_length+= save_pack_length(pack_version, record_pos + pack_length,
+ tot_blob_length);
/* Correct file buffer if the header was smaller */
if (pack_length != max_pack_length)
@@ -1930,14 +1930,27 @@ static void init_file_buffer(File file, pbool read_buffer)
file_buffer.pos=file_buffer.buffer;
file_buffer.bits=BITS_SAVED;
}
- file_buffer.byte=0;
+ file_buffer.current_byte=0;
}
static int flush_buffer(ulong neaded_length)
{
ulong length;
- if ((ulong) (file_buffer.end - file_buffer.pos) > neaded_length)
+
+ /*
+ file_buffer.end is 8 bytes lower than the real end of the buffer.
+ This is done so that the end-of-buffer condition does not need to be
+ checked for every byte (see write_bits()). Consequently,
+ file_buffer.pos can become greater than file_buffer.end. The
+ algorithms in the other functions ensure that there will never be
+ more than 8 bytes written to the buffer without an end-of-buffer
+ check. So the buffer cannot be overrun. But we need to check for the
+ near-to-buffer-end condition to avoid a negative result, which is
+ casted to unsigned and thus becomes giant.
+ */
+ if ((file_buffer.pos < file_buffer.end) &&
+ ((ulong) (file_buffer.end - file_buffer.pos) > neaded_length))
return 0;
length=(ulong) (file_buffer.pos-file_buffer.buffer);
file_buffer.pos=file_buffer.buffer;
@@ -1979,14 +1992,14 @@ static void write_bits (register ulong value, register uint bits)
{
if ((file_buffer.bits-=(int) bits) >= 0)
{
- file_buffer.byte|=value << file_buffer.bits;
+ file_buffer.current_byte|=value << file_buffer.bits;
}
else
{
reg3 uint byte_buff;
bits= (uint) -file_buffer.bits;
DBUG_ASSERT(bits <= 8 * sizeof(value));
- byte_buff= (file_buffer.byte |
+ byte_buff= (file_buffer.current_byte |
((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0));
#if BITS_SAVED == 32
*file_buffer.pos++= (byte) (byte_buff >> 24) ;
@@ -2013,9 +2026,9 @@ static void write_bits (register ulong value, register uint bits)
}
#endif
if (file_buffer.pos >= file_buffer.end)
- VOID(flush_buffer((uint) ~0));
+ VOID(flush_buffer(~ (ulong) 0));
file_buffer.bits=(int) (BITS_SAVED - bits);
- file_buffer.byte=(uint) (value << (BITS_SAVED - bits));
+ file_buffer.current_byte=(uint) (value << (BITS_SAVED - bits));
}
return;
}
@@ -2027,7 +2040,7 @@ static void flush_bits (void)
uint bits,byte_buff;
bits=(file_buffer.bits) & ~7;
- byte_buff = file_buffer.byte >> bits;
+ byte_buff = file_buffer.current_byte >> bits;
bits=BITS_SAVED - bits;
while (bits > 0)
{
@@ -2035,7 +2048,7 @@ static void flush_bits (void)
*file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
}
file_buffer.bits=BITS_SAVED;
- file_buffer.byte=0;
+ file_buffer.current_byte=0;
return;
}
@@ -2061,7 +2074,7 @@ 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)
+ if (share->state.key_map != (ULL(1) << share->base.keys) - 1)
{
/*
Some indexes are disabled, cannot use current key_file_length value