diff options
Diffstat (limited to 'myisam/myisampack.c')
-rw-r--r-- | myisam/myisampack.c | 89 |
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 |